summaryrefslogtreecommitdiff
path: root/util/concurrency/mutex.h
diff options
context:
space:
mode:
Diffstat (limited to 'util/concurrency/mutex.h')
-rw-r--r--util/concurrency/mutex.h103
1 files changed, 75 insertions, 28 deletions
diff --git a/util/concurrency/mutex.h b/util/concurrency/mutex.h
index c463498..f17c3f0 100644
--- a/util/concurrency/mutex.h
+++ b/util/concurrency/mutex.h
@@ -19,11 +19,12 @@
#include <map>
#include <set>
-
#include "../heapcheck.h"
namespace mongo {
+ void printStackTrace( ostream &o );
+
class mutex;
inline boost::xtime incxtimemillis( long long s ) {
@@ -50,7 +51,6 @@ namespace mongo {
map< mid, set<mid> > followers;
boost::mutex &x;
unsigned magic;
-
void aBreakPoint() { } // for debugging
public:
// set these to create an assert that
@@ -147,20 +147,16 @@ namespace mongo {
~StaticObserver() { _destroyingStatics = true; }
};
- /** On pthread systems, it is an error to destroy a mutex while held. Static global
- * mutexes may be held upon shutdown in our implementation, and this way we avoid
- * destroying them.
- * NOT recursive.
+ /** On pthread systems, it is an error to destroy a mutex while held (boost mutex
+ * may use pthread). Static global mutexes may be held upon shutdown in our
+ * implementation, and this way we avoid destroying them.
+ * NOT recursive.
*/
class mutex : boost::noncopyable {
public:
#if defined(_DEBUG)
const char * const _name;
-#endif
-
-#if defined(_DEBUG)
- mutex(const char *name)
- : _name(name)
+ mutex(const char *name) : _name(name)
#else
mutex(const char *)
#endif
@@ -184,44 +180,47 @@ namespace mongo {
#else
ok( _l.locked() )
#endif
- {
- }
-
- ~try_lock() {
- }
-
+ { }
private:
boost::timed_mutex::scoped_timed_lock _l;
-
public:
const bool ok;
};
-
class scoped_lock : boost::noncopyable {
+ public:
#if defined(_DEBUG)
- mongo::mutex *mut;
+ struct PostStaticCheck {
+ PostStaticCheck() {
+ if ( StaticObserver::_destroyingStatics ) {
+ cout << "trying to lock a mongo::mutex during static shutdown" << endl;
+ printStackTrace( cout );
+ }
+ }
+ };
+
+ PostStaticCheck _check;
+ mongo::mutex * const _mut;
#endif
- public:
- scoped_lock( mongo::mutex &m ) : _l( m.boost() ) {
+ scoped_lock( mongo::mutex &m ) :
+#if defined(_DEBUG)
+ _mut(&m),
+#endif
+ _l( m.boost() ) {
#if defined(_DEBUG)
- mut = &m;
- mutexDebugger.entering(mut->_name);
+ mutexDebugger.entering(_mut->_name);
#endif
}
~scoped_lock() {
#if defined(_DEBUG)
- mutexDebugger.leaving(mut->_name);
+ mutexDebugger.leaving(_mut->_name);
#endif
}
boost::timed_mutex::scoped_lock &boost() { return _l; }
private:
boost::timed_mutex::scoped_lock _l;
};
-
-
private:
-
boost::timed_mutex &boost() { return *_m; }
boost::timed_mutex *_m;
};
@@ -229,4 +228,52 @@ namespace mongo {
typedef mutex::scoped_lock scoped_lock;
typedef boost::recursive_mutex::scoped_lock recursive_scoped_lock;
+ /** The concept with SimpleMutex is that it is a basic lock/unlock with no
+ special functionality (such as try and try timeout). Thus it can be
+ implemented using OS-specific facilities in all environments (if desired).
+ On Windows, the implementation below is faster than boost mutex.
+ */
+#if defined(_WIN32)
+ class SimpleMutex : boost::noncopyable {
+ CRITICAL_SECTION _cs;
+ public:
+ SimpleMutex(const char *name) { InitializeCriticalSection(&_cs); }
+ ~SimpleMutex() { DeleteCriticalSection(&_cs); }
+
+ void lock() { EnterCriticalSection(&_cs); }
+ void unlock() { LeaveCriticalSection(&_cs); }
+
+ class scoped_lock : boost::noncopyable {
+ SimpleMutex& _m;
+ public:
+ scoped_lock( SimpleMutex &m ) : _m(m) { _m.lock(); }
+ ~scoped_lock() { _m.unlock(); }
+ };
+ };
+#else
+ class SimpleMutex : boost::noncopyable {
+ public:
+ SimpleMutex(const char* name) { assert( pthread_mutex_init(&_lock,0) == 0 ); }
+ ~SimpleMutex(){
+ if ( ! StaticObserver::_destroyingStatics ) {
+ assert( pthread_mutex_destroy(&_lock) == 0 );
+ }
+ }
+
+ void lock() { assert( pthread_mutex_lock(&_lock) == 0 ); }
+ void unlock() { assert( pthread_mutex_unlock(&_lock) == 0 ); }
+
+ class scoped_lock : boost::noncopyable {
+ SimpleMutex& _m;
+ public:
+ scoped_lock( SimpleMutex &m ) : _m(m) { _m.lock(); }
+ ~scoped_lock() { _m.unlock(); }
+ };
+
+ private:
+ pthread_mutex_t _lock;
+ };
+
+#endif
+
}