Use boost::thread locking instead of interprocess

This commit is contained in:
Pieter Wuille 2012-05-13 17:55:23 +02:00
parent 4a9130aca2
commit 660ff174f2
3 changed files with 52 additions and 57 deletions

View file

@ -3,8 +3,9 @@
// file license.txt or http://www.opensource.org/licenses/mit-license.php. // file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "sync.h" #include "sync.h"
#include "util.h"
#include <boost/foreach.hpp>
#ifdef DEBUG_LOCKORDER #ifdef DEBUG_LOCKORDER
// //
@ -40,7 +41,7 @@ private:
typedef std::vector< std::pair<void*, CLockLocation> > LockStack; typedef std::vector< std::pair<void*, CLockLocation> > LockStack;
static boost::interprocess::interprocess_mutex dd_mutex; static boost::mutex dd_mutex;
static std::map<std::pair<void*, void*>, LockStack> lockorders; static std::map<std::pair<void*, void*>, LockStack> lockorders;
static boost::thread_specific_ptr<LockStack> lockstack; static boost::thread_specific_ptr<LockStack> lockstack;
@ -66,7 +67,6 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
{ {
bool fOrderOK = true;
if (lockstack.get() == NULL) if (lockstack.get() == NULL)
lockstack.reset(new LockStack); lockstack.reset(new LockStack);
@ -75,20 +75,21 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
(*lockstack).push_back(std::make_pair(c, locklocation)); (*lockstack).push_back(std::make_pair(c, locklocation));
if (!fTry) BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack)) if (!fTry) {
{ BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack)) {
if (i.first == c) break; if (i.first == c) break;
std::pair<void*, void*> p1 = std::make_pair(i.first, c); std::pair<void*, void*> p1 = std::make_pair(i.first, c);
if (lockorders.count(p1)) if (lockorders.count(p1))
continue; continue;
lockorders[p1] = (*lockstack); lockorders[p1] = (*lockstack);
std::pair<void*, void*> p2 = std::make_pair(c, i.first); std::pair<void*, void*> p2 = std::make_pair(c, i.first);
if (lockorders.count(p2)) if (lockorders.count(p2))
{ {
potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
break; break;
}
} }
} }
dd_mutex.unlock(); dd_mutex.unlock();

View file

@ -5,19 +5,19 @@
#ifndef BITCOIN_SYNC_H #ifndef BITCOIN_SYNC_H
#define BITCOIN_SYNC_H #define BITCOIN_SYNC_H
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/thread/recursive_mutex.hpp>
#include <boost/interprocess/sync/interprocess_semaphore.hpp> #include <boost/thread/locks.hpp>
#include <boost/interprocess/sync/lock_options.hpp> #include <boost/thread/condition_variable.hpp>
/** Wrapped boost mutex: supports recursive locking, but no waiting */ /** Wrapped boost mutex: supports recursive locking, but no waiting */
typedef boost::interprocess::interprocess_recursive_mutex CCriticalSection; typedef boost::recursive_mutex CCriticalSection;
/** Wrapped boost mutex: supports waiting but not recursive locking */ /** Wrapped boost mutex: supports waiting but not recursive locking */
typedef boost::interprocess::interprocess_mutex CWaitableCriticalSection; typedef boost::mutex CWaitableCriticalSection;
#ifdef DEBUG_LOCKORDER #ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false); void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
@ -32,12 +32,12 @@ template<typename Mutex>
class CMutexLock class CMutexLock
{ {
private: private:
boost::interprocess::scoped_lock<Mutex> lock; boost::unique_lock<Mutex> lock;
public: public:
void Enter(const char* pszName, const char* pszFile, int nLine) void Enter(const char* pszName, const char* pszFile, int nLine)
{ {
if (!lock.owns()) if (!lock.owns_lock())
{ {
EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex())); EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
#ifdef DEBUG_LOCKCONTENTION #ifdef DEBUG_LOCKCONTENTION
@ -55,7 +55,7 @@ public:
void Leave() void Leave()
{ {
if (lock.owns()) if (lock.owns_lock())
{ {
lock.unlock(); lock.unlock();
LeaveCritical(); LeaveCritical();
@ -64,17 +64,17 @@ public:
bool TryEnter(const char* pszName, const char* pszFile, int nLine) bool TryEnter(const char* pszName, const char* pszFile, int nLine)
{ {
if (!lock.owns()) if (!lock.owns_lock())
{ {
EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true); EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
lock.try_lock(); lock.try_lock();
if (!lock.owns()) if (!lock.owns_lock())
LeaveCritical(); LeaveCritical();
} }
return lock.owns(); return lock.owns_lock();
} }
CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::interprocess::defer_lock) CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock)
{ {
if (fTry) if (fTry)
TryEnter(pszName, pszFile, nLine); TryEnter(pszName, pszFile, nLine);
@ -84,16 +84,16 @@ public:
~CMutexLock() ~CMutexLock()
{ {
if (lock.owns()) if (lock.owns_lock())
LeaveCritical(); LeaveCritical();
} }
operator bool() operator bool()
{ {
return lock.owns(); return lock.owns_lock();
} }
boost::interprocess::scoped_lock<Mutex> &GetLock() boost::unique_lock<Mutex> &GetLock()
{ {
return lock; return lock;
} }
@ -117,47 +117,40 @@ typedef CMutexLock<CCriticalSection> CCriticalBlock;
LeaveCritical(); \ LeaveCritical(); \
} }
#ifdef MAC_OSX
// boost::interprocess::interprocess_semaphore seems to spinlock on OSX; prefer polling instead
class CSemaphore class CSemaphore
{ {
private: private:
CCriticalSection cs; boost::condition_variable condition;
int val; boost::mutex mutex;
int value;
public: public:
CSemaphore(int init) : val(init) {} CSemaphore(int init) : value(init) {}
void wait() { void wait() {
do { boost::unique_lock<boost::mutex> lock(mutex);
{ while (value < 1) {
LOCK(cs); condition.wait(lock);
if (val>0) { }
val--; value--;
return;
}
}
Sleep(100);
} while(1);
} }
bool try_wait() { bool try_wait() {
LOCK(cs); boost::unique_lock<boost::mutex> lock(mutex);
if (val>0) { if (value < 1)
val--; return false;
return true; value--;
} return true;
return false;
} }
void post() { void post() {
LOCK(cs); {
val++; boost::unique_lock<boost::mutex> lock(mutex);
value++;
}
condition.notify_one();
} }
}; };
#else
typedef boost::interprocess::interprocess_semaphore CSemaphore;
#endif
/** RAII-style semaphore lock */ /** RAII-style semaphore lock */
class CSemaphoreGrant class CSemaphoreGrant

View file

@ -27,6 +27,7 @@ namespace boost {
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <stdarg.h>
#ifdef WIN32 #ifdef WIN32
#ifdef _MSC_VER #ifdef _MSC_VER