summaryrefslogtreecommitdiff
path: root/src/mongo/util/concurrency/rwlock.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/concurrency/rwlock.h')
-rw-r--r--src/mongo/util/concurrency/rwlock.h408
1 files changed, 222 insertions, 186 deletions
diff --git a/src/mongo/util/concurrency/rwlock.h b/src/mongo/util/concurrency/rwlock.h
index 22373efd421..b3988efa06b 100644
--- a/src/mongo/util/concurrency/rwlock.h
+++ b/src/mongo/util/concurrency/rwlock.h
@@ -39,217 +39,253 @@
namespace mongo {
- class RWLock : public RWLockBase {
- enum { NilState, UpgradableState, Exclusive } x; // only bother to set when doing upgradable related things
- public:
- const char * const _name;
- RWLock(const char *name) : _name(name) {
- x = NilState;
- }
- void lock() {
- RWLockBase::lock();
- }
- void unlock() {
- RWLockBase::unlock();
- }
+class RWLock : public RWLockBase {
+ enum {
+ NilState,
+ UpgradableState,
+ Exclusive
+ } x; // only bother to set when doing upgradable related things
+public:
+ const char* const _name;
+ RWLock(const char* name) : _name(name) {
+ x = NilState;
+ }
+ void lock() {
+ RWLockBase::lock();
+ }
+ void unlock() {
+ RWLockBase::unlock();
+ }
- void lock_shared() { RWLockBase::lock_shared(); }
- void unlock_shared() { RWLockBase::unlock_shared(); }
- private:
- void lockAsUpgradable() { RWLockBase::lockAsUpgradable(); }
- void unlockFromUpgradable() { // upgradable -> unlocked
- RWLockBase::unlockFromUpgradable();
- }
- public:
- void upgrade() { // upgradable -> exclusive lock
- verify( x == UpgradableState );
- RWLockBase::upgrade();
- x = Exclusive;
- }
+ void lock_shared() {
+ RWLockBase::lock_shared();
+ }
+ void unlock_shared() {
+ RWLockBase::unlock_shared();
+ }
- bool lock_shared_try( int millis ) { return RWLockBase::lock_shared_try(millis); }
+private:
+ void lockAsUpgradable() {
+ RWLockBase::lockAsUpgradable();
+ }
+ void unlockFromUpgradable() { // upgradable -> unlocked
+ RWLockBase::unlockFromUpgradable();
+ }
- bool lock_try( int millis = 0 ) {
- return RWLockBase::lock_try(millis);
- }
+public:
+ void upgrade() { // upgradable -> exclusive lock
+ verify(x == UpgradableState);
+ RWLockBase::upgrade();
+ x = Exclusive;
+ }
- /** acquire upgradable state. You must be unlocked before creating.
- unlocks on destruction, whether in upgradable state or upgraded to exclusive
- in the interim.
- */
- class Upgradable {
- MONGO_DISALLOW_COPYING(Upgradable);
- RWLock& _r;
- public:
- Upgradable(RWLock& r) : _r(r) {
- r.lockAsUpgradable();
- verify( _r.x == NilState );
- _r.x = RWLock::UpgradableState;
- }
- ~Upgradable() {
- if( _r.x == RWLock::UpgradableState ) {
- _r.x = NilState;
- _r.unlockFromUpgradable();
- }
- else {
- //TEMP verify( _r.x == Exclusive ); // has been upgraded
- _r.x = NilState;
- _r.unlock();
- }
- }
- };
- };
+ bool lock_shared_try(int millis) {
+ return RWLockBase::lock_shared_try(millis);
+ }
- /** throws on failure to acquire in the specified time period. */
- class rwlock_try_write {
- MONGO_DISALLOW_COPYING(rwlock_try_write);
- public:
- struct exception { };
- rwlock_try_write(RWLock& l, int millis = 0) : _l(l) {
- if( !l.lock_try(millis) )
- throw exception();
- }
- ~rwlock_try_write() { _l.unlock(); }
- private:
- RWLock& _l;
- };
+ bool lock_try(int millis = 0) {
+ return RWLockBase::lock_try(millis);
+ }
- class rwlock_shared {
- MONGO_DISALLOW_COPYING(rwlock_shared);
- public:
- rwlock_shared(RWLock& rwlock) : _r(rwlock) {_r.lock_shared(); }
- ~rwlock_shared() { _r.unlock_shared(); }
- private:
+ /** acquire upgradable state. You must be unlocked before creating.
+ unlocks on destruction, whether in upgradable state or upgraded to exclusive
+ in the interim.
+ */
+ class Upgradable {
+ MONGO_DISALLOW_COPYING(Upgradable);
RWLock& _r;
- };
- /* scoped lock for RWLock */
- class rwlock {
- MONGO_DISALLOW_COPYING(rwlock);
public:
- /**
- * @param write acquire write lock if true sharable if false
- * @param lowPriority if > 0, will try to get the lock non-greedily for that many ms
- */
- rwlock( const RWLock& lock , bool write, /* bool alreadyHaveLock = false , */int lowPriorityWaitMS = 0 )
- : _lock( (RWLock&)lock ) , _write( write ) {
- {
- if ( _write ) {
- _lock.lock();
- }
- else {
- _lock.lock_shared();
- }
- }
+ Upgradable(RWLock& r) : _r(r) {
+ r.lockAsUpgradable();
+ verify(_r.x == NilState);
+ _r.x = RWLock::UpgradableState;
}
- ~rwlock() {
- if ( _write )
- _lock.unlock();
- else
- _lock.unlock_shared();
+ ~Upgradable() {
+ if (_r.x == RWLock::UpgradableState) {
+ _r.x = NilState;
+ _r.unlockFromUpgradable();
+ } else {
+ // TEMP verify( _r.x == Exclusive ); // has been upgraded
+ _r.x = NilState;
+ _r.unlock();
+ }
}
- private:
- RWLock& _lock;
- const bool _write;
};
+};
- // ----------------------------------------------------------------------------------------
+/** throws on failure to acquire in the specified time period. */
+class rwlock_try_write {
+ MONGO_DISALLOW_COPYING(rwlock_try_write);
- /** recursive on shared locks is ok for this implementation */
- class RWLockRecursive : protected RWLockBase {
- protected:
- ThreadLocalValue<int> _state;
- void lock(); // not implemented - Lock() should be used; didn't overload this name to avoid mistakes
- virtual void Lock() { RWLockBase::lock(); }
- public:
- virtual ~RWLockRecursive() { }
- const char * const _name;
- RWLockRecursive(const char *name) : _name(name) { }
+public:
+ struct exception {};
+ rwlock_try_write(RWLock& l, int millis = 0) : _l(l) {
+ if (!l.lock_try(millis))
+ throw exception();
+ }
+ ~rwlock_try_write() {
+ _l.unlock();
+ }
+
+private:
+ RWLock& _l;
+};
+
+class rwlock_shared {
+ MONGO_DISALLOW_COPYING(rwlock_shared);
+
+public:
+ rwlock_shared(RWLock& rwlock) : _r(rwlock) {
+ _r.lock_shared();
+ }
+ ~rwlock_shared() {
+ _r.unlock_shared();
+ }
+
+private:
+ RWLock& _r;
+};
- void assertAtLeastReadLocked() {
- verify( _state.get() != 0 );
+/* scoped lock for RWLock */
+class rwlock {
+ MONGO_DISALLOW_COPYING(rwlock);
+
+public:
+ /**
+ * @param write acquire write lock if true sharable if false
+ * @param lowPriority if > 0, will try to get the lock non-greedily for that many ms
+ */
+ rwlock(const RWLock& lock,
+ bool write,
+ /* bool alreadyHaveLock = false , */ int lowPriorityWaitMS = 0)
+ : _lock((RWLock&)lock), _write(write) {
+ {
+ if (_write) {
+ _lock.lock();
+ } else {
+ _lock.lock_shared();
+ }
+ }
+ }
+ ~rwlock() {
+ if (_write)
+ _lock.unlock();
+ else
+ _lock.unlock_shared();
+ }
+
+private:
+ RWLock& _lock;
+ const bool _write;
+};
+
+// ----------------------------------------------------------------------------------------
+
+/** recursive on shared locks is ok for this implementation */
+class RWLockRecursive : protected RWLockBase {
+protected:
+ ThreadLocalValue<int> _state;
+ void
+ lock(); // not implemented - Lock() should be used; didn't overload this name to avoid mistakes
+ virtual void Lock() {
+ RWLockBase::lock();
+ }
+
+public:
+ virtual ~RWLockRecursive() {}
+ const char* const _name;
+ RWLockRecursive(const char* name) : _name(name) {}
+
+ void assertAtLeastReadLocked() {
+ verify(_state.get() != 0);
+ }
+ void assertExclusivelyLocked() {
+ verify(_state.get() < 0);
+ }
+
+ class Exclusive {
+ MONGO_DISALLOW_COPYING(Exclusive);
+ RWLockRecursive& _r;
+
+ public:
+ Exclusive(RWLockRecursive& r) : _r(r) {
+ int s = _r._state.get();
+ dassert(s <= 0);
+ if (s == 0)
+ _r.Lock();
+ _r._state.set(s - 1);
}
- void assertExclusivelyLocked() {
- verify( _state.get() < 0 );
+ ~Exclusive() {
+ int s = _r._state.get();
+ DEV wassert(s < 0); // wassert: don't throw from destructors
+ ++s;
+ _r._state.set(s);
+ if (s == 0)
+ _r.unlock();
}
+ };
- class Exclusive {
- MONGO_DISALLOW_COPYING(Exclusive);
- RWLockRecursive& _r;
- public:
- Exclusive(RWLockRecursive& r) : _r(r) {
- int s = _r._state.get();
- dassert( s <= 0 );
- if( s == 0 )
- _r.Lock();
- _r._state.set(s-1);
+ class Shared {
+ MONGO_DISALLOW_COPYING(Shared);
+ RWLockRecursive& _r;
+ bool _alreadyLockedExclusiveByUs;
+
+ public:
+ Shared(RWLockRecursive& r) : _r(r) {
+ int s = _r._state.get();
+ _alreadyLockedExclusiveByUs = s < 0;
+ if (!_alreadyLockedExclusiveByUs) {
+ dassert(s >= 0); // -1 would mean exclusive
+ if (s == 0)
+ _r.lock_shared();
+ _r._state.set(s + 1);
}
- ~Exclusive() {
- int s = _r._state.get();
- DEV wassert( s < 0 ); // wassert: don't throw from destructors
- ++s;
+ }
+ ~Shared() {
+ if (_alreadyLockedExclusiveByUs) {
+ DEV wassert(_r._state.get() < 0);
+ } else {
+ int s = _r._state.get() - 1;
+ DEV wassert(s >= 0);
_r._state.set(s);
- if ( s == 0 )
- _r.unlock();
+ if (s == 0)
+ _r.unlock_shared();
}
- };
-
- class Shared {
- MONGO_DISALLOW_COPYING(Shared);
- RWLockRecursive& _r;
- bool _alreadyLockedExclusiveByUs;
- public:
- Shared(RWLockRecursive& r) : _r(r) {
- int s = _r._state.get();
- _alreadyLockedExclusiveByUs = s < 0;
- if( !_alreadyLockedExclusiveByUs ) {
- dassert( s >= 0 ); // -1 would mean exclusive
- if( s == 0 )
- _r.lock_shared();
- _r._state.set(s+1);
- }
- }
- ~Shared() {
- if( _alreadyLockedExclusiveByUs ) {
- DEV wassert( _r._state.get() < 0 );
- }
- else {
- int s = _r._state.get() - 1;
- DEV wassert( s >= 0 );
- _r._state.set(s);
- if( s == 0 )
- _r.unlock_shared();
- }
- }
- };
+ }
};
+};
- class RWLockRecursiveNongreedy : public RWLockRecursive {
- virtual void Lock() {
- bool got = false;
- for ( int i=0; i<lowPriorityWaitMS; i++ ) {
- if ( lock_try(0) ) {
- got = true;
- break;
- }
- int sleep = 1;
- if ( i > ( lowPriorityWaitMS / 20 ) )
- sleep = 10;
- sleepmillis(sleep);
- i += ( sleep - 1 );
- }
- if ( ! got ) {
- RWLockBase::lock();
+class RWLockRecursiveNongreedy : public RWLockRecursive {
+ virtual void Lock() {
+ bool got = false;
+ for (int i = 0; i < lowPriorityWaitMS; i++) {
+ if (lock_try(0)) {
+ got = true;
+ break;
}
+ int sleep = 1;
+ if (i > (lowPriorityWaitMS / 20))
+ sleep = 10;
+ sleepmillis(sleep);
+ i += (sleep - 1);
}
+ if (!got) {
+ RWLockBase::lock();
+ }
+ }
- public:
- const int lowPriorityWaitMS;
- RWLockRecursiveNongreedy(const char *nm, int lpwaitms) : RWLockRecursive(nm), lowPriorityWaitMS(lpwaitms) { }
- const char * implType() const { return RWLockRecursive::implType(); }
-
- //just for testing:
- bool __lock_try( int millis ) { return RWLockRecursive::lock_try(millis); }
- };
+public:
+ const int lowPriorityWaitMS;
+ RWLockRecursiveNongreedy(const char* nm, int lpwaitms)
+ : RWLockRecursive(nm), lowPriorityWaitMS(lpwaitms) {}
+ const char* implType() const {
+ return RWLockRecursive::implType();
+ }
+ // just for testing:
+ bool __lock_try(int millis) {
+ return RWLockRecursive::lock_try(millis);
+ }
+};
}