Files
mongo/util/concurrency/rwlockimpl.h
2011-10-06 17:14:36 -04:00

164 lines
5.0 KiB
C++

// @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); }
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 );
}
protected:
RWLockBase() {
check( pthread_rwlock_init( &_lock , 0 ) );
}
~RWLockBase() {
if ( ! StaticObserver::_destroyingStatics ) {
wassert( pthread_rwlock_destroy( &_lock ) == 0 ); // wassert as don't want to throw from a destructor
}
}
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>
# 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