123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)
- #ifndef ECOIN_SYNC_H
- #define ECOIN_SYNC_H
- #include <boost/thread/mutex.hpp>
- #include <boost/thread/recursive_mutex.hpp>
- #include <boost/thread/locks.hpp>
- #include <boost/thread/condition_variable.hpp>
- /** Wrapped boost mutex: supports recursive locking, but no waiting */
- typedef boost::recursive_mutex CCriticalSection;
- /** Wrapped boost mutex: supports waiting but not recursive locking */
- typedef boost::mutex CWaitableCriticalSection;
- #ifdef DEBUG_LOCKORDER
- void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
- void LeaveCritical();
- #else
- void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
- void static inline LeaveCritical() {}
- #endif
- #ifdef DEBUG_LOCKCONTENTION
- void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
- #endif
- /** Wrapper around boost::unique_lock<Mutex> */
- template<typename Mutex>
- class CMutexLock
- {
- private:
- boost::unique_lock<Mutex> lock;
- public:
- void Enter(const char* pszName, const char* pszFile, int nLine)
- {
- if (!lock.owns_lock())
- {
- EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
- #ifdef DEBUG_LOCKCONTENTION
- if (!lock.try_lock())
- {
- PrintLockContention(pszName, pszFile, nLine);
- #endif
- lock.lock();
- #ifdef DEBUG_LOCKCONTENTION
- }
- #endif
- }
- }
- void Leave()
- {
- if (lock.owns_lock())
- {
- lock.unlock();
- LeaveCritical();
- }
- }
- bool TryEnter(const char* pszName, const char* pszFile, int nLine)
- {
- if (!lock.owns_lock())
- {
- EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
- lock.try_lock();
- if (!lock.owns_lock())
- LeaveCritical();
- }
- return lock.owns_lock();
- }
- CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock)
- {
- if (fTry)
- TryEnter(pszName, pszFile, nLine);
- else
- Enter(pszName, pszFile, nLine);
- }
- ~CMutexLock()
- {
- if (lock.owns_lock())
- LeaveCritical();
- }
- operator bool()
- {
- return lock.owns_lock();
- }
- boost::unique_lock<Mutex> &GetLock()
- {
- return lock;
- }
- };
- typedef CMutexLock<CCriticalSection> CCriticalBlock;
- #define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
- #define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__)
- #define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
- #define ENTER_CRITICAL_SECTION(cs) \
- { \
- EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
- (cs).lock(); \
- }
- #define LEAVE_CRITICAL_SECTION(cs) \
- { \
- (cs).unlock(); \
- LeaveCritical(); \
- }
- class CSemaphore
- {
- private:
- boost::condition_variable condition;
- boost::mutex mutex;
- int value;
- public:
- CSemaphore(int init) : value(init) {}
- void wait() {
- boost::unique_lock<boost::mutex> lock(mutex);
- while (value < 1) {
- condition.wait(lock);
- }
- value--;
- }
- bool try_wait() {
- boost::unique_lock<boost::mutex> lock(mutex);
- if (value < 1)
- return false;
- value--;
- return true;
- }
- void post() {
- {
- boost::unique_lock<boost::mutex> lock(mutex);
- value++;
- }
- condition.notify_one();
- }
- };
- /** RAII-style semaphore lock */
- class CSemaphoreGrant
- {
- private:
- CSemaphore *sem;
- bool fHaveGrant;
- public:
- void Acquire() {
- if (fHaveGrant)
- return;
- sem->wait();
- fHaveGrant = true;
- }
- void Release() {
- if (!fHaveGrant)
- return;
- sem->post();
- fHaveGrant = false;
- }
- bool TryAcquire() {
- if (!fHaveGrant && sem->try_wait())
- fHaveGrant = true;
- return fHaveGrant;
- }
- void MoveTo(CSemaphoreGrant &grant) {
- grant.Release();
- grant.sem = sem;
- grant.fHaveGrant = fHaveGrant;
- sem = NULL;
- fHaveGrant = false;
- }
- CSemaphoreGrant() : sem(NULL), fHaveGrant(false) {}
- CSemaphoreGrant(CSemaphore &sema, bool fTry = false) : sem(&sema), fHaveGrant(false) {
- if (fTry)
- TryAcquire();
- else
- Acquire();
- }
- ~CSemaphoreGrant() {
- Release();
- }
- operator bool() {
- return fHaveGrant;
- }
- };
- #endif
|