summaryrefslogtreecommitdiff
path: root/db/concurrency.h
diff options
context:
space:
mode:
Diffstat (limited to 'db/concurrency.h')
-rw-r--r--db/concurrency.h162
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