summaryrefslogtreecommitdiff
path: root/src/mongo/util/concurrency/rwlockimpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/concurrency/rwlockimpl.h')
-rw-r--r--src/mongo/util/concurrency/rwlockimpl.h170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/mongo/util/concurrency/rwlockimpl.h b/src/mongo/util/concurrency/rwlockimpl.h
new file mode 100644
index 00000000000..4e07231447b
--- /dev/null
+++ b/src/mongo/util/concurrency/rwlockimpl.h
@@ -0,0 +1,170 @@
+// @file rwlockimpl.h
+
+#pragma once
+
+#if defined(MONGO_USE_SRW_ON_WINDOWS) && defined(_WIN32)
+
+// windows slimreaderwriter version. newer windows versions only
+
+namespace mongo {
+ class RWLockBase : boost::noncopyable {
+ SRWLOCK _lock;
+ protected:
+ RWLockBase() { InitializeSRWLock(&_lock); }
+ ~RWLockBase() {
+ // no special action needed to destroy a SRWLOCK
+ }
+ void lock() { AcquireSRWLockExclusive(&_lock); }
+ void unlock() { ReleaseSRWLockExclusive(&_lock); }
+ void lock_shared() { AcquireSRWLockShared(&_lock); }
+ void unlock_shared() { ReleaseSRWLockShared(&_lock); }
+ bool lock_shared_try( int millis ) {
+ if( TryAcquireSRWLockShared(&_lock) )
+ return true;
+ if( millis == 0 )
+ return false;
+ unsigned long long end = curTimeMicros64() + millis*1000;
+ while( 1 ) {
+ Sleep(1);
+ if( TryAcquireSRWLockShared(&_lock) )
+ return true;
+ if( curTimeMicros64() >= end )
+ break;
+ }
+ return false;
+ }
+ bool lock_try( int millis = 0 ) {
+ if( TryAcquireSRWLockExclusive(&_lock) ) // quick check to optimistically avoid calling curTimeMicros64
+ return true;
+ if( millis == 0 )
+ return false;
+ unsigned long long end = curTimeMicros64() + millis*1000;
+ do {
+ Sleep(1);
+ if( TryAcquireSRWLockExclusive(&_lock) )
+ return true;
+ } while( curTimeMicros64() < end );
+ return false;
+ }
+ // no upgradable for this impl
+ void lockAsUpgradable() { lock(); }
+ void unlockFromUpgradable() { unlock(); }
+ void upgrade() { }
+ public:
+ const char * implType() const { return "WINSRW"; }
+ };
+}
+
+#elif( BOOST_VERSION < 103500 )
+
+# if defined(_WIN32)
+# error need boost >= 1.35 for windows
+# endif
+
+// pthreads version
+
+# include <pthread.h>
+
+namespace mongo {
+ class RWLockBase : boost::noncopyable {
+ pthread_rwlock_t _lock;
+ static void check( int x ) {
+ if( x == 0 ) return;
+ log() << "pthread rwlock failed: " << x << endl;
+ assert( x == 0 );
+ }
+
+ ~RWLockBase() {
+ if ( ! StaticObserver::_destroyingStatics ) {
+ wassert( pthread_rwlock_destroy( &_lock ) == 0 ); // wassert as don't want to throw from a destructor
+ }
+ }
+
+ protected:
+ RWLockBase() {
+ check( pthread_rwlock_init( &_lock , 0 ) );
+ }
+
+ void lock() { check( pthread_rwlock_wrlock( &_lock ) ); }
+ void unlock() { check( pthread_rwlock_unlock( &_lock ) ); }
+ void lock_shared() { check( pthread_rwlock_rdlock( &_lock ) ); }
+ void unlock_shared() { check( pthread_rwlock_unlock( &_lock ) ); }
+ bool lock_shared_try( int millis ) { return _try( millis , false ); }
+ bool lock_try( int millis = 0 ) { return _try( millis , true ); }
+ bool _try( int millis , bool write ) {
+ while ( true ) {
+ int x = write ?
+ pthread_rwlock_trywrlock( &_lock ) :
+ pthread_rwlock_tryrdlock( &_lock );
+ if ( x <= 0 )
+ return true;
+ if ( millis-- <= 0 )
+ return false;
+ if ( x == EBUSY ) {
+ sleepmillis(1);
+ continue;
+ }
+ check(x);
+ }
+ return false;
+ }
+ // no upgradable for this impl
+ void lockAsUpgradable() { lock(); }
+ void unlockFromUpgradable() { unlock(); }
+ void upgrade() { }
+ public:
+ const char * implType() const { return "posix"; }
+ };
+}
+
+#else
+
+// Boost version
+
+# if defined(_WIN32)
+# include "shared_mutex_win.hpp"
+namespace mongo { typedef boost::modified_shared_mutex shared_mutex; }
+# else
+# include <boost/thread/shared_mutex.hpp>
+namespace mongo { using boost::shared_mutex; }
+# endif
+# undef assert
+# define assert MONGO_assert
+
+namespace mongo {
+ class RWLockBase : boost::noncopyable {
+ shared_mutex _m;
+ protected:
+ void lock() {
+ _m.lock();
+ }
+ void unlock() {
+ _m.unlock();
+ }
+ void lockAsUpgradable() {
+ _m.lock_upgrade();
+ }
+ void unlockFromUpgradable() { // upgradable -> unlocked
+ _m.unlock_upgrade();
+ }
+ void upgrade() { // upgradable -> exclusive lock
+ _m.unlock_upgrade_and_lock();
+ }
+ void lock_shared() {
+ _m.lock_shared();
+ }
+ void unlock_shared() {
+ _m.unlock_shared();
+ }
+ bool lock_shared_try( int millis ) {
+ return _m.timed_lock_shared( boost::posix_time::milliseconds(millis) );
+ }
+ bool lock_try( int millis = 0 ) {
+ return _m.timed_lock( boost::posix_time::milliseconds(millis) );
+ }
+ public:
+ const char * implType() const { return "boost"; }
+ };
+}
+
+#endif