blob: 472823ac3db887a9bb58b8d99e6d15e17da17395 [file] [log] [blame]
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Microsoft Corporation
*
* -=- Robust Distributed System Nucleus (rDSN) -=-
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <algorithm>
#include <atomic>
#include "utils/utils.h"
#include "utils/ports.h"
///
/// synchronization objects of rDSN.
///
/// you MUST always use these objects to do synchronization when you write code
/// in rdsn's "service_app", because different implementations may be provided
/// when then program is running in different mode(nativerun/simulator).
///
/// As for the synchronize objects in "utils/synchronize.h", they are
/// used for synchronization inner the rdsn core runtime.
///
namespace dsn {
class ilock;
class zlock
{
public:
zlock(bool recursive = false);
~zlock();
void lock();
bool try_lock();
void unlock();
private:
DISALLOW_COPY_AND_ASSIGN(zlock);
ilock *_h;
};
class rwlock_nr_provider;
class zrwlock_nr
{
public:
zrwlock_nr();
~zrwlock_nr();
void lock_read();
void unlock_read();
bool try_lock_read();
void lock_write();
void unlock_write();
bool try_lock_write();
private:
DISALLOW_COPY_AND_ASSIGN(zrwlock_nr);
rwlock_nr_provider *_h;
};
class semaphore_provider;
class zsemaphore
{
public:
zsemaphore(int initial_count = 0);
~zsemaphore();
void signal(int count = 1);
bool wait(int timeout_milliseconds = TIME_MS_MAX);
private:
DISALLOW_COPY_AND_ASSIGN(zsemaphore);
semaphore_provider *_h;
};
class zevent
{
public:
zevent(bool manualReset, bool initState = false);
~zevent();
void set();
void reset();
bool wait(int timeout_milliseconds = TIME_MS_MAX);
private:
DISALLOW_COPY_AND_ASSIGN(zevent);
zsemaphore _sema;
std::atomic<bool> _signaled;
bool _manualReset;
};
}
///
/// RAII wrapper of rdsn's synchronization objects
///
namespace dsn {
class zauto_lock
{
public:
zauto_lock() : _locked(false), _lock(nullptr) {}
zauto_lock(zlock &lock) : _locked(true), _lock(&lock) { _lock->lock(); }
~zauto_lock()
{
if (_locked) {
_lock->unlock();
_locked = false;
}
}
void swap(zauto_lock &other)
{
std::swap(_locked, other._locked);
std::swap(_lock, other._lock);
}
private:
bool _locked;
zlock *_lock;
};
class zauto_read_lock
{
public:
zauto_read_lock() : _locked(false), _lock(nullptr) {}
zauto_read_lock(zrwlock_nr &lock) : _locked(true), _lock(&lock) { _lock->lock_read(); }
~zauto_read_lock()
{
if (_locked) {
_lock->unlock_read();
_locked = false;
}
}
void swap(zauto_read_lock &other)
{
std::swap(_locked, other._locked);
std::swap(_lock, other._lock);
}
private:
bool _locked;
zrwlock_nr *_lock;
};
class zauto_write_lock
{
public:
zauto_write_lock() : _locked(false), _lock(nullptr) {}
zauto_write_lock(zrwlock_nr &lock) : _locked(true), _lock(&lock) { _lock->lock_write(); }
~zauto_write_lock()
{
if (_locked) {
_lock->unlock_write();
_locked = false;
}
}
void swap(zauto_write_lock &other)
{
std::swap(_locked, other._locked);
std::swap(_lock, other._lock);
}
private:
bool _locked;
zrwlock_nr *_lock;
};
}
///
/// utils function used to check the lock safety
///
namespace dsn {
namespace lock_checker {
void check_wait_safety();
void check_dangling_lock();
}
}