diff options
Diffstat (limited to 'db/concurrency.h')
-rw-r--r-- | db/concurrency.h | 162 |
1 files changed, 42 insertions, 120 deletions
diff --git a/db/concurrency.h b/db/concurrency.h index e841d61..9b91b0f 100644 --- a/db/concurrency.h +++ b/db/concurrency.h @@ -29,25 +29,11 @@ #pragma once -#if BOOST_VERSION >= 103500 -#include <boost/thread/shared_mutex.hpp> -#undef assert -#define assert xassert -#define HAVE_READLOCK -#else -#warning built with boost version 1.34 or older - limited concurrency -#endif +#include "../util/concurrency/rwlock.h" +#include "../util/mmap.h" namespace mongo { - inline bool readLockSupported(){ -#ifdef HAVE_READLOCK - return true; -#else - return false; -#endif - } - string sayClientState(); bool haveClient(); @@ -87,11 +73,9 @@ namespace mongo { } }; -#ifdef HAVE_READLOCK -//#if 0 class MongoMutex { MutexInfo _minfo; - boost::shared_mutex _m; + RWLock _m; ThreadLocalValue<int> _state; /* we use a separate TLS value for releasedEarly - that is ok as @@ -99,13 +83,16 @@ namespace mongo { */ ThreadLocalValue<bool> _releasedEarly; public: + MongoMutex(const char * name) : _m(name) { } + /** * @return * > 0 write lock * = 0 no lock * < 0 read lock */ - int getState(){ return _state.get(); } + int getState() { return _state.get(); } + bool isWriteLocked() { return getState() > 0; } void assertWriteLocked() { assert( getState() > 0 ); DEV assert( !_releasedEarly.get() ); @@ -129,7 +116,6 @@ namespace mongo { } void lock() { - if ( _checkWriteLockAlready() ) return; @@ -140,27 +126,28 @@ namespace mongo { curopGotLock(); _minfo.entered(); + + MongoFile::lockAll(); } - bool lock_try() { + bool lock_try( int millis ) { if ( _checkWriteLockAlready() ) - return true; - - curopWaitingForLock( 1 ); + return true; - boost::system_time until = get_system_time(); - until += boost::posix_time::milliseconds(0); - bool got = _m.timed_lock( until ); + curopWaitingForLock( 1 ); + bool got = _m.lock_try( millis ); curopGotLock(); if ( got ){ _minfo.entered(); _state.set(1); + MongoFile::lockAll(); } return got; } - + + void unlock() { //DEV cout << "UNLOCK" << endl; int s = _state.get(); @@ -175,6 +162,9 @@ namespace mongo { } massert( 12599, "internal error: attempt to unlock when wasn't in a write lock", false); } + + MongoFile::unlockAll(); + _state.set(0); _minfo.leaving(); _m.unlock(); @@ -218,10 +208,8 @@ namespace mongo { lock_shared(); return true; } - - boost::system_time until = get_system_time(); - until += boost::posix_time::milliseconds(2); - bool got = _m.timed_lock_shared( until ); + + bool got = _m.lock_shared_try( millis ); if ( got ) _state.set(-1); return got; @@ -246,82 +234,11 @@ namespace mongo { MutexInfo& info() { return _minfo; } }; -#else - /* this will be for old versions of boost */ - class MongoMutex { - MutexInfo _minfo; - boost::recursive_mutex m; - ThreadLocalValue<bool> _releasedEarly; - public: - MongoMutex() { } - void lock() { -#ifdef HAVE_READLOCK - m.lock(); -#error this should be impossible? -#else - boost::detail::thread::lock_ops<boost::recursive_mutex>::lock(m); -#endif - _minfo.entered(); - } - - bool lock_try(){ - lock(); - return true; - } - - void releaseEarly() { - assertWriteLocked(); // aso must not be recursive, although we don't verify that in the old boost version - assert( !_releasedEarly.get() ); - _releasedEarly.set(true); - _unlock(); - } - - void _unlock() { - _minfo.leaving(); -#ifdef HAVE_READLOCK - m.unlock(); -#else - boost::detail::thread::lock_ops<boost::recursive_mutex>::unlock(m); -#endif - } - void unlock() { - if( _releasedEarly.get() ) { - _releasedEarly.set(false); - return; - } - _unlock(); - } - - void lock_shared() { lock(); } - bool lock_shared_try( int millis ) { - while ( millis-- ){ - if ( getState() ){ - sleepmillis(1); - continue; - } - lock_shared(); - return true; - } - return false; - } - - void unlock_shared() { unlock(); } - MutexInfo& info() { return _minfo; } - void assertWriteLocked() { - assert( info().isLocked() ); - } - void assertAtLeastReadLocked() { - assert( info().isLocked() ); - } - bool atLeastReadLocked() { return info().isLocked(); } - int getState(){ return info().isLocked() ? 1 : 0; } - }; -#endif extern MongoMutex &dbMutex; - void dbunlocking_write(); - void dbunlocking_read(); + inline void dbunlocking_write() { } + inline void dbunlocking_read() { } struct writelock { writelock(const string& ns) { @@ -357,29 +274,36 @@ namespace mongo { dbMutex.unlock_shared(); } } - bool got(){ - return _got; - } + bool got() const { return _got; } + private: bool _got; }; struct writelocktry { - writelocktry( const string&ns ){ - _got = dbMutex.lock_try(); + writelocktry( const string&ns , int tryms ){ + _got = dbMutex.lock_try( tryms ); } ~writelocktry() { if ( _got ){ - dbunlocking_write(); + dbunlocking_read(); dbMutex.unlock(); } } - bool got(){ - return _got; - } + bool got() const { return _got; } + private: bool _got; }; - + struct readlocktryassert : public readlocktry { + readlocktryassert(const string& ns, int tryms) : + readlocktry(ns,tryms) { + uassert(13142, "timeout getting readlock", got()); + } + }; + + /** assure we have at least a read lock - they key with this being + if you have a write lock, that's ok too. + */ struct atleastreadlock { atleastreadlock( const string& ns ){ _prev = dbMutex.getState(); @@ -390,7 +314,7 @@ namespace mongo { if ( _prev == 0 ) dbMutex.unlock_shared(); } - + private: int _prev; }; @@ -419,11 +343,9 @@ namespace mongo { void releaseAndWriteLock(); }; - /* use writelock and readlock instead */ + /* use writelock and readlock instead */ struct dblock : public writelock { dblock() : writelock("") { } - ~dblock() { - } }; // eliminate |