version 1.7, 2006/08/21 15:46:16
|
version 1.14, 2008/09/16 18:37:03
|
|
|
#include "Time.h" | #include "Time.h" |
#include "PegasusAssert.h" | #include "PegasusAssert.h" |
#include "Once.h" | #include "Once.h" |
|
#include "Exception.h" |
|
#include "System.h" |
|
|
|
#define MUTEX_LOCK_FAILED_KEY "Common.InternalException.MUTEX_LOCK_FAILED" |
|
#define MUTEX_LOCK_FAILED_MSG "Failed to acquire mutex lock: $0" |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
|
|
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
| |
switch (pthread_mutex_lock(&_rep.mutex)) |
int r = pthread_mutex_lock(&_rep.mutex); |
|
|
|
if (r == 0) |
{ | { |
case 0: |
|
#if defined(PEGASUS_DEBUG) | #if defined(PEGASUS_DEBUG) |
_rep.count++; | _rep.count++; |
#endif | #endif |
break; |
} |
|
else |
|
{ |
|
if (r != -1) |
|
{ |
|
// Special behavior for Single UNIX Specification, Version 3 |
|
errno = r; |
|
} |
| |
default: |
throw Exception(MessageLoaderParms( |
throw WaitFailed(Threads::self()); |
MUTEX_LOCK_FAILED_KEY, |
|
MUTEX_LOCK_FAILED_MSG, |
|
PEGASUS_SYSTEM_ERRORMSG_NLS)); |
} | } |
} | } |
| |
void Mutex::try_lock() |
Boolean Mutex::try_lock() |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
| |
int r = pthread_mutex_trylock(&_rep.mutex); | int r = pthread_mutex_trylock(&_rep.mutex); |
if (r == -1) |
|
r=errno; |
if (r == 0) |
switch (r) |
|
{ | { |
case 0: |
|
#if defined(PEGASUS_DEBUG) | #if defined(PEGASUS_DEBUG) |
_rep.count++; | _rep.count++; |
#endif | #endif |
break; |
return true; |
|
} |
| |
case EBUSY: |
if (r != -1) |
throw AlreadyLocked(Threads::self()); |
{ |
|
// Special behavior for Single UNIX Specification, Version 3 |
|
errno = r; |
|
} |
| |
default: |
if (errno == EBUSY) |
throw WaitFailed(Threads::self()); |
{ |
|
return false; |
} | } |
|
|
|
throw Exception(MessageLoaderParms( |
|
MUTEX_LOCK_FAILED_KEY, |
|
MUTEX_LOCK_FAILED_MSG, |
|
PEGASUS_SYSTEM_ERRORMSG_NLS)); |
} | } |
| |
void Mutex::timed_lock(Uint32 milliseconds) |
Boolean Mutex::timed_lock(Uint32 milliseconds) |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); |
|
|
|
struct timeval now; | struct timeval now; |
struct timeval finish; | struct timeval finish; |
struct timeval remaining; | struct timeval remaining; |
|
|
finish.tv_usec = usec % 1000000; | finish.tv_usec = usec % 1000000; |
} | } |
| |
for (;;) |
while (!try_lock()) |
{ |
|
int r=pthread_mutex_trylock(&_rep.mutex); |
|
if (r == -1) |
|
r = errno; |
|
switch (r) |
|
{ |
|
case 0: |
|
#if defined(PEGASUS_DEBUG) |
|
_rep.count++; |
|
#endif |
|
return; |
|
|
|
case EBUSY: |
|
{ | { |
gettimeofday(&now, NULL); | gettimeofday(&now, NULL); |
| |
if (Time::subtract(&remaining, &finish, &now)) | if (Time::subtract(&remaining, &finish, &now)) |
throw TimeOut(Threads::self()); |
{ |
|
return false; |
|
} |
| |
Threads::yield(); | Threads::yield(); |
break; |
|
} | } |
| |
default: |
return true; |
throw WaitFailed(Threads::self()); |
|
} |
|
} |
|
} | } |
| |
void Mutex::unlock() | void Mutex::unlock() |
|
|
_rep.count--; | _rep.count--; |
#endif | #endif |
| |
if (pthread_mutex_unlock(&_rep.mutex) != 0) |
int rc = pthread_mutex_unlock(&_rep.mutex); |
throw Permission(Threads::self()); |
// All documented error codes represent coding errors. |
|
PEGASUS_ASSERT(rc == 0); |
} | } |
| |
|
#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 */ | #endif /* PEGASUS_HAVE_PTHREADS */ |
| |
//============================================================================== | //============================================================================== |
|
|
static inline void _initialize(MutexRep& rep) | static inline void _initialize(MutexRep& rep) |
{ | { |
rep.handle = CreateMutex(NULL, FALSE, NULL); | rep.handle = CreateMutex(NULL, FALSE, NULL); |
#if defined(PEGASUS_DEBUG) |
|
rep.count = 0; | rep.count = 0; |
#endif |
|
} | } |
| |
Mutex::Mutex() | Mutex::Mutex() |
|
|
DWORD rc = WaitForSingleObject(_rep.handle, INFINITE); | DWORD rc = WaitForSingleObject(_rep.handle, INFINITE); |
| |
if (rc == WAIT_FAILED) | if (rc == WAIT_FAILED) |
throw WaitFailed(Threads::self()); |
{ |
|
throw Exception(MessageLoaderParms( |
|
MUTEX_LOCK_FAILED_KEY, |
|
MUTEX_LOCK_FAILED_MSG, |
|
PEGASUS_SYSTEM_ERRORMSG_NLS)); |
|
} |
| |
#if defined(PEGASUS_DEBUG) |
|
_rep.count++; | _rep.count++; |
#endif |
|
} | } |
| |
void Mutex::try_lock() |
Boolean Mutex::try_lock() |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
| |
DWORD rc = WaitForSingleObject(_rep.handle, 0); | DWORD rc = WaitForSingleObject(_rep.handle, 0); |
| |
if (rc == WAIT_TIMEOUT) | if (rc == WAIT_TIMEOUT) |
throw AlreadyLocked(Threads::self()); |
{ |
|
return false; |
|
} |
| |
if (rc == WAIT_FAILED) | if (rc == WAIT_FAILED) |
throw WaitFailed(Threads::self()); |
{ |
|
throw Exception(MessageLoaderParms( |
|
MUTEX_LOCK_FAILED_KEY, |
|
MUTEX_LOCK_FAILED_MSG, |
|
PEGASUS_SYSTEM_ERRORMSG_NLS)); |
|
} |
| |
#if defined(PEGASUS_DEBUG) |
|
_rep.count++; | _rep.count++; |
#endif |
return true; |
} | } |
| |
void Mutex::timed_lock(Uint32 milliseconds) |
Boolean Mutex::timed_lock(Uint32 milliseconds) |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
| |
DWORD rc = WaitForSingleObject(_rep.handle, milliseconds); | DWORD rc = WaitForSingleObject(_rep.handle, milliseconds); |
| |
if (rc == WAIT_TIMEOUT) | if (rc == WAIT_TIMEOUT) |
throw TimeOut(Threads::self()); |
return false; |
| |
if (rc == WAIT_FAILED) | if (rc == WAIT_FAILED) |
throw WaitFailed(Threads::self()); |
{ |
|
throw Exception(MessageLoaderParms( |
|
MUTEX_LOCK_FAILED_KEY, |
|
MUTEX_LOCK_FAILED_MSG, |
|
PEGASUS_SYSTEM_ERRORMSG_NLS)); |
|
} |
| |
#if defined(PEGASUS_DEBUG) |
|
_rep.count++; | _rep.count++; |
#endif |
return true; |
} | } |
| |
void Mutex::unlock() | void Mutex::unlock() |
|
|
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
PEGASUS_DEBUG_ASSERT(_rep.count > 0); | PEGASUS_DEBUG_ASSERT(_rep.count > 0); |
| |
#if defined(PEGASUS_DEBUG) |
|
_rep.count--; | _rep.count--; |
#endif |
|
ReleaseMutex(_rep.handle); | ReleaseMutex(_rep.handle); |
} | } |
| |