version 1.3, 2006/01/30 16:17:05
|
version 1.12, 2008/08/15 17:24:52
|
|
|
// | // |
//============================================================================== | //============================================================================== |
// | // |
// Author: Mike Day (mdday@us.ibm.com) |
|
// |
|
// Modified By: Markus Mueller |
|
// Ramnath Ravindran (Ramnath.Ravindran@compaq.com) |
|
// David Eger (dteger@us.ibm.com) |
|
// Amit K Arora, IBM (amita@in.ibm.com) for PEP#101 |
|
// Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com) |
|
// Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
|
// David Dillard, VERITAS Software Corp. |
|
// (david.dillard@veritas.com) |
|
// Aruran, IBM (ashanmug@in.ibm.com) for BUG# 3518 |
|
// |
|
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#include "Mutex.h" | #include "Mutex.h" |
|
#include "Time.h" |
|
#include "PegasusAssert.h" |
|
#include "Once.h" |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
|
//============================================================================== |
|
// |
|
// PEGASUS_HAVE_PTHREADS |
|
// |
|
//============================================================================== |
|
|
|
#if defined(PEGASUS_HAVE_PTHREADS) |
|
|
|
static Once _once = PEGASUS_ONCE_INITIALIZER; |
|
static pthread_mutexattr_t _attr; |
|
|
|
static void _init_attr() |
|
{ |
|
pthread_mutexattr_init(&_attr); |
|
pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE); |
|
} |
|
|
|
Mutex::Mutex() |
|
{ |
|
once(&_once, _init_attr); |
|
pthread_mutex_init(&_rep.mutex, &_attr); |
|
#if defined(PEGASUS_DEBUG) |
|
_rep.count = 0; |
|
#endif |
|
} |
|
|
|
Mutex::Mutex(RecursiveTag) |
|
{ |
|
once(&_once, _init_attr); |
|
pthread_mutex_init(&_rep.mutex, &_attr); |
|
#if defined(PEGASUS_DEBUG) |
|
_rep.count = 0; |
|
#endif |
|
} |
|
|
|
Mutex::Mutex(NonRecursiveTag) |
|
{ |
|
pthread_mutex_init(&_rep.mutex, NULL); |
|
#if defined(PEGASUS_DEBUG) |
|
_rep.count = 0; |
|
#endif |
|
} |
|
|
|
Mutex::~Mutex() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
pthread_mutex_destroy(&_rep.mutex); |
|
} |
|
|
|
void Mutex::lock() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
|
|
switch (pthread_mutex_lock(&_rep.mutex)) |
|
{ |
|
case 0: |
|
#if defined(PEGASUS_DEBUG) |
|
_rep.count++; |
|
#endif |
|
break; |
|
|
|
default: |
|
throw WaitFailed(Threads::self()); |
|
} |
|
} |
|
|
|
Boolean Mutex::try_lock() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
|
|
int r = pthread_mutex_trylock(&_rep.mutex); |
|
if (r == -1) |
|
r=errno; |
|
|
|
if (r == 0) |
|
{ |
|
#if defined(PEGASUS_DEBUG) |
|
_rep.count++; |
|
#endif |
|
return true; |
|
} |
|
|
|
if (r == EBUSY) |
|
{ |
|
return false; |
|
} |
|
|
|
throw WaitFailed(Threads::self()); |
|
} |
|
|
|
Boolean Mutex::timed_lock(Uint32 milliseconds) |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
|
|
struct timeval now; |
|
struct timeval finish; |
|
struct timeval remaining; |
|
{ |
|
Uint32 usec; |
|
gettimeofday(&finish, NULL); |
|
finish.tv_sec += (milliseconds / 1000 ); |
|
milliseconds %= 1000; |
|
usec = finish.tv_usec + ( milliseconds * 1000 ); |
|
finish.tv_sec += (usec / 1000000); |
|
finish.tv_usec = usec % 1000000; |
|
} |
|
|
|
for (;;) |
|
{ |
|
int r=pthread_mutex_trylock(&_rep.mutex); |
|
if (r == -1) |
|
r = errno; |
|
|
|
if (r == 0) |
|
{ |
|
break; |
|
} |
|
else if (r == EBUSY) |
|
{ |
|
gettimeofday(&now, NULL); |
|
|
|
if (Time::subtract(&remaining, &finish, &now)) |
|
{ |
|
return false; |
|
} |
|
|
|
Threads::yield(); |
|
} |
|
else |
|
{ |
|
throw WaitFailed(Threads::self()); |
|
} |
|
} |
|
|
|
#if defined(PEGASUS_DEBUG) |
|
_rep.count++; |
|
#endif |
|
return true; |
|
} |
|
|
|
void Mutex::unlock() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
PEGASUS_DEBUG_ASSERT(_rep.count > 0); |
|
|
|
#if defined(PEGASUS_DEBUG) |
|
_rep.count--; |
|
#endif |
|
|
|
if (pthread_mutex_unlock(&_rep.mutex) != 0) |
|
throw Permission(Threads::self()); |
|
} |
|
|
|
#if defined(PEGASUS_OS_LINUX) || \ |
|
(defined(PEGASUS_OS_ZOS) && !(__TARGET_LIB__ < 0x41090000)) |
|
void Mutex::reinitialize() |
|
{ |
|
pthread_mutex_init(&_rep.mutex, &_attr); |
|
#if defined(PEGASUS_DEBUG) |
|
_rep.count = 0; |
|
#endif |
|
} |
|
#endif |
|
|
|
#endif /* PEGASUS_HAVE_PTHREADS */ |
|
|
|
//============================================================================== |
|
// |
|
// PEGASUS_HAVE_WINDOWS_THREADS |
|
// |
|
//============================================================================== |
|
|
|
#if defined(PEGASUS_HAVE_WINDOWS_THREADS) |
|
|
|
static inline void _initialize(MutexRep& rep) |
|
{ |
|
rep.handle = CreateMutex(NULL, FALSE, NULL); |
|
rep.count = 0; |
|
} |
|
|
|
Mutex::Mutex() |
|
{ |
|
_initialize(_rep); |
|
} |
|
|
|
Mutex::Mutex(RecursiveTag) |
|
{ |
|
_initialize(_rep); |
|
} |
|
|
|
Mutex::Mutex(NonRecursiveTag) |
|
{ |
|
_initialize(_rep); |
|
} |
|
|
|
Mutex::~Mutex() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
|
|
WaitForSingleObject(_rep.handle, INFINITE); |
|
CloseHandle(_rep.handle); |
|
} |
|
|
|
void Mutex::lock() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
|
|
DWORD rc = WaitForSingleObject(_rep.handle, INFINITE); |
|
|
|
if (rc == WAIT_FAILED) |
|
throw WaitFailed(Threads::self()); |
|
|
|
_rep.count++; |
|
} |
|
|
|
Boolean Mutex::try_lock() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
|
|
DWORD rc = WaitForSingleObject(_rep.handle, 0); |
|
|
|
if (rc == WAIT_TIMEOUT) |
|
{ |
|
return false; |
|
} |
|
|
|
if (rc == WAIT_FAILED) |
|
{ |
|
throw WaitFailed(Threads::self()); |
|
} |
|
|
|
_rep.count++; |
|
return true; |
|
} |
|
|
|
Boolean Mutex::timed_lock(Uint32 milliseconds) |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
|
|
DWORD rc = WaitForSingleObject(_rep.handle, milliseconds); |
|
|
|
if (rc == WAIT_TIMEOUT) |
|
return false; |
|
|
|
if (rc == WAIT_FAILED) |
|
throw WaitFailed(Threads::self()); |
|
|
|
_rep.count++; |
|
return true; |
|
} |
|
|
|
void Mutex::unlock() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
PEGASUS_DEBUG_ASSERT(_rep.count > 0); |
|
|
|
_rep.count--; |
|
ReleaseMutex(_rep.handle); |
|
} |
|
|
|
#endif /* PEGASUS_HAVE_WINDOWS_THREADS */ |
|
|
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |