Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115633
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Subscribers
None
View Options
diff --git a/src/sync.h b/src/sync.h
index 78b9043477..705647e4a5 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -1,280 +1,280 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SYNC_H
#define BITCOIN_SYNC_H
#include "threadsafety.h"
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp>
////////////////////////////////////////////////
// //
// THE SIMPLE DEFINITON, EXCLUDING DEBUG CODE //
// //
////////////////////////////////////////////////
/*
CCriticalSection mutex;
boost::recursive_mutex mutex;
LOCK(mutex);
boost::unique_lock<boost::recursive_mutex> criticalblock(mutex);
LOCK2(mutex1, mutex2);
boost::unique_lock<boost::recursive_mutex> criticalblock1(mutex1);
boost::unique_lock<boost::recursive_mutex> criticalblock2(mutex2);
TRY_LOCK(mutex, name);
boost::unique_lock<boost::recursive_mutex> name(mutex, boost::try_to_lock_t);
ENTER_CRITICAL_SECTION(mutex); // no RAII
mutex.lock();
LEAVE_CRITICAL_SECTION(mutex); // no RAII
mutex.unlock();
*/
///////////////////////////////
// //
// THE ACTUAL IMPLEMENTATION //
// //
///////////////////////////////
/**
* Template mixin that adds -Wthread-safety locking
* annotations to a subset of the mutex API.
*/
template <typename PARENT>
class LOCKABLE AnnotatedMixin : public PARENT
{
public:
void lock() EXCLUSIVE_LOCK_FUNCTION()
{
PARENT::lock();
}
void unlock() UNLOCK_FUNCTION()
{
PARENT::unlock();
}
bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
{
return PARENT::try_lock();
}
};
/**
* Wrapped boost mutex: supports recursive locking, but no waiting
* TODO: We should move away from using the recursive lock by default.
*/
typedef AnnotatedMixin<boost::recursive_mutex> CCriticalSection;
/** Wrapped boost mutex: supports waiting but not recursive locking */
typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection;
/** Just a typedef for boost::condition_variable, can be wrapped later if desired */
typedef boost::condition_variable CConditionVariable;
#ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
std::string LocksHeld();
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
#else
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {}
void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {}
#endif
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
#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
+class SCOPED_LOCKABLE CMutexLock
{
private:
boost::unique_lock<Mutex> lock;
void Enter(const char* pszName, const char* pszFile, int nLine)
{
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
}
bool TryEnter(const char* pszName, const char* pszFile, int nLine)
{
EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
lock.try_lock();
if (!lock.owns_lock())
LeaveCritical();
return lock.owns_lock();
}
public:
- CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock)
+ CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, boost::defer_lock)
{
if (fTry)
TryEnter(pszName, pszFile, nLine);
else
Enter(pszName, pszFile, nLine);
}
- CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false)
+ CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
{
if (!pmutexIn) return;
lock = boost::unique_lock<Mutex>(*pmutexIn, boost::defer_lock);
if (fTry)
TryEnter(pszName, pszFile, nLine);
else
Enter(pszName, pszFile, nLine);
}
- ~CMutexLock()
+ ~CMutexLock() UNLOCK_FUNCTION()
{
if (lock.owns_lock())
LeaveCritical();
}
operator bool()
{
return lock.owns_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 // BITCOIN_SYNC_H
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Mar 2, 11:36 (1 d, 2 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5180109
Default Alt Text
(7 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment