version 1.3.14.2, 2006/07/28 17:41:27
|
version 1.3.14.9, 2006/07/31 17:37:18
|
|
|
// | // |
//============================================================================== | //============================================================================== |
// | // |
// Author: Mike Day (mdday@us.ibm.com) |
// Author: Mike Brasher (m.brasher@inovadevelopment.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 |
|
// |
|
// Reworked By: Mike Brasher (m.brasher@inovadevelopment.com) |
|
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#include "Mutex.h" | #include "Mutex.h" |
#include "Time.h" | #include "Time.h" |
#include "PegasusAssert.h" | #include "PegasusAssert.h" |
|
#include "Once.h" |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
|
|
| |
#if defined(PEGASUS_HAVE_PTHREADS) | #if defined(PEGASUS_HAVE_PTHREADS) |
| |
Mutex::Mutex() |
static Once _once = PEGASUS_ONCE_INITIALIZER; |
{ |
static pthread_mutexattr_t _attr; |
pthread_mutexattr_init(&_rep.attr); |
|
| |
// If your platform does not define PTHREAD_MUTEX_RECURSIVE, try |
static void _init_attr() |
// PTHREAD_MUTEX_RECURSIVE_NP. |
{ |
pthread_mutexattr_settype(&_rep.attr, PTHREAD_MUTEX_RECURSIVE); |
pthread_mutexattr_init(&_attr); |
|
pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE); |
|
} |
| |
pthread_mutex_init(&_rep.mutex, &_rep.attr); |
Mutex::Mutex() |
_rep.owner.clear(); |
{ |
|
once(&_once, _init_attr); |
|
pthread_mutex_init(&_rep.mutex, &_attr); |
|
_rep.count = 0; |
} | } |
| |
Mutex::~Mutex() | Mutex::~Mutex() |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
|
pthread_mutex_destroy(&_rep.mutex); |
if (pthread_mutex_destroy(&_rep.mutex) == 0) |
_rep.count = -1; |
pthread_mutexattr_destroy(&_rep.attr); |
|
} | } |
| |
void Mutex::lock(ThreadType caller) |
void Mutex::lock() |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
| |
switch (pthread_mutex_lock(&_rep.mutex)) | switch (pthread_mutex_lock(&_rep.mutex)) |
{ | { |
case 0: | case 0: |
_rep.owner = caller; |
_rep.count++; |
break; | break; |
| |
case EDEADLK: | case EDEADLK: |
throw Deadlock(_rep.owner); |
throw Deadlock(ThreadType()); |
| |
default: | default: |
throw WaitFailed(_rep.owner); |
throw WaitFailed(ThreadType()); |
} | } |
} | } |
| |
void Mutex::try_lock(ThreadType caller) |
void Mutex::try_lock() |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
| |
switch (pthread_mutex_trylock(&_rep.mutex)) | switch (pthread_mutex_trylock(&_rep.mutex)) |
{ | { |
case 0: | case 0: |
_rep.owner = caller; |
_rep.count++; |
break; | break; |
| |
case EBUSY: | case EBUSY: |
throw AlreadyLocked(_rep.owner); |
throw AlreadyLocked(ThreadType()); |
| |
case EDEADLK: | case EDEADLK: |
throw Deadlock(_rep.owner); |
throw Deadlock(ThreadType()); |
| |
default: | default: |
throw WaitFailed(_rep.owner); |
throw WaitFailed(ThreadType()); |
} | } |
} | } |
| |
void Mutex::timed_lock(Uint32 milliseconds, ThreadType caller) |
void Mutex::timed_lock(Uint32 milliseconds) |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
| |
|
|
switch (pthread_mutex_trylock(&_rep.mutex)) | switch (pthread_mutex_trylock(&_rep.mutex)) |
{ | { |
case 0: | case 0: |
|
_rep.count++; |
return; | return; |
| |
case EBUSY: | case EBUSY: |
|
|
void Mutex::unlock() | void Mutex::unlock() |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
|
PEGASUS_DEBUG_ASSERT(_rep.count > 0); |
ThreadType owner = _rep.owner; |
|
_rep.owner.clear(); |
|
| |
if (pthread_mutex_unlock(&_rep.mutex) != 0) | if (pthread_mutex_unlock(&_rep.mutex) != 0) |
{ |
throw Permission(ThreadType()); |
_rep.owner = owner; |
|
throw Permission(_rep.owner); |
_rep.count--; |
} |
|
} | } |
| |
#endif /* PEGASUS_HAVE_PTHREADS */ | #endif /* PEGASUS_HAVE_PTHREADS */ |
|
|
Mutex::Mutex() | Mutex::Mutex() |
{ | { |
_rep.handle = CreateMutex(NULL, FALSE, NULL); | _rep.handle = CreateMutex(NULL, FALSE, NULL); |
_rep.owner = ThreadType(0); |
Threads::clear(ThreadType()); |
_rep.count.clear(); |
_rep.count = 0; |
} | } |
| |
Mutex::~Mutex() | Mutex::~Mutex() |
|
|
CloseHandle(_rep.handle); | CloseHandle(_rep.handle); |
} | } |
| |
void Mutex::lock(ThreadType caller) |
void Mutex::lock() |
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
| |
DWORD rc = WaitForSingleObject(_rep.handle, INFINITE); | DWORD rc = WaitForSingleObject(_rep.handle, INFINITE); |
| |
if (rc == WAIT_FAILED) | if (rc == WAIT_FAILED) |
throw WaitFailed(_rep.owner); |
throw WaitFailed(ThreadType()); |
| |
_rep.owner = caller; |
|
_rep.count++; | _rep.count++; |
} | } |
| |
void Mutex::try_lock(ThreadType caller) |
void 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(_rep.owner); |
throw AlreadyLocked(ThreadType()); |
| |
if (rc == WAIT_FAILED) | if (rc == WAIT_FAILED) |
throw WaitFailed(_rep.owner); |
throw WaitFailed(ThreadType()); |
| |
_rep.owner = caller; |
|
_rep.count++; | _rep.count++; |
} | } |
| |
void Mutex::timed_lock(Uint32 milliseconds , ThreadType caller) |
void 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(_rep.owner); |
throw TimeOut(ThreadType()); |
| |
if (rc == WAIT_FAILED) | if (rc == WAIT_FAILED) |
throw WaitFailed(_rep.owner); |
throw WaitFailed(ThreadType()); |
| |
_rep.owner = caller; |
|
_rep.count++; | _rep.count++; |
} | } |
| |
|
|
{ | { |
PEGASUS_DEBUG_ASSERT(_magic); | PEGASUS_DEBUG_ASSERT(_magic); |
| |
_rep.owner.clear(); |
Threads::clear(ThreadType()); |
_rep.count--; | _rep.count--; |
ReleaseMutex(_rep.handle); | ReleaseMutex(_rep.handle); |
} | } |