version 1.9, 2006/12/01 21:31:45
|
version 1.9.16.1, 2007/09/11 16:32:43
|
|
|
| |
//============================================================================== | //============================================================================== |
// | // |
// PEGASUS_HAVE_PTHREADS |
// Mutex implementation with PTHREAD_MUTEX_RECURSIVE feature. |
// | // |
//============================================================================== | //============================================================================== |
| |
#if defined(PEGASUS_HAVE_PTHREADS) |
#if defined(PEGASUS_HAVE_PTHREADS) && defined(PEGASUS_HAVE_RECURSIVE_MUTEXES) |
| |
static Once _once = PEGASUS_ONCE_INITIALIZER; | static Once _once = PEGASUS_ONCE_INITIALIZER; |
static pthread_mutexattr_t _attr; | static pthread_mutexattr_t _attr; |
|
|
} | } |
#endif | #endif |
| |
#endif /* PEGASUS_HAVE_PTHREADS */ |
#endif /* PEGASUS_HAVE_PTHREADS && PEGASUS_HAVE_RECURSIVE_MUTEXES */ |
|
|
|
//============================================================================== |
|
// |
|
// Mutex implementation without PTHREAD_MUTEX_RECURSIVE feature. |
|
// |
|
//============================================================================== |
|
|
|
#if defined(PEGASUS_HAVE_PTHREADS) && !defined(PEGASUS_HAVE_RECURSIVE_MUTEXES) |
|
|
|
Mutex::Mutex() |
|
{ |
|
pthread_mutex_init(&_rep.mutex, NULL); |
|
pthread_cond_init(&_rep.cond, NULL); |
|
_rep.owner = 0; |
|
_rep.count = 0; |
|
} |
|
|
|
Mutex::Mutex(RecursiveTag) |
|
{ |
|
pthread_mutex_init(&_rep.mutex, NULL); |
|
pthread_cond_init(&_rep.cond, NULL); |
|
_rep.owner = 0; |
|
_rep.count = 0; |
|
} |
|
|
|
Mutex::Mutex(NonRecursiveTag) |
|
{ |
|
pthread_mutex_init(&_rep.mutex, NULL); |
|
pthread_cond_init(&_rep.cond, NULL); |
|
_rep.owner = 0; |
|
_rep.count = 0; |
|
} |
|
|
|
Mutex::~Mutex() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
pthread_mutex_destroy(&_rep.mutex); |
|
pthread_cond_destroy(&_rep.cond); |
|
} |
|
|
|
void Mutex::lock() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
pthread_t self = pthread_self(); |
|
|
|
pthread_mutex_lock(&_rep.mutex); |
|
{ |
|
if (_rep.count == 0) |
|
{ |
|
_rep.owner = self; |
|
} |
|
else if (!pthread_equal(_rep.owner, self)) |
|
{ |
|
while (_rep.count > 0) |
|
pthread_cond_wait(&_rep.cond, &_rep.mutex); |
|
|
|
_rep.owner = self; |
|
} |
|
|
|
_rep.count++; |
|
} |
|
pthread_mutex_unlock(&_rep.mutex); |
|
} |
|
|
|
void Mutex::try_lock() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
pthread_t self = pthread_self(); |
|
|
|
pthread_mutex_lock(&_rep.mutex); |
|
{ |
|
if (_rep.count == 0) |
|
{ |
|
_rep.owner = self; |
|
_rep.count = 1; |
|
} |
|
else if (pthread_equal(_rep.owner, self)) |
|
{ |
|
_rep.count++; |
|
} |
|
else |
|
{ |
|
pthread_mutex_unlock(&_rep.mutex); |
|
throw AlreadyLocked(Threads::self()); |
|
} |
|
} |
|
pthread_mutex_unlock(&_rep.mutex); |
|
} |
|
|
|
void Mutex::timed_lock(Uint32 milliseconds) |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
pthread_t self = pthread_self(); |
|
|
|
pthread_mutex_lock(&_rep.mutex); |
|
{ |
|
if (_rep.count == 0) |
|
{ |
|
_rep.owner = self; |
|
} |
|
else if (!pthread_equal(_rep.owner, self)) |
|
{ |
|
timespec ts; |
|
clock_gettime(CLOCK_REALTIME, &ts); |
|
|
|
ts.tv_sec += milliseconds / 1000; |
|
ts.tv_nsec += (milliseconds % 1000) * 1000000; |
|
|
|
while (_rep.count > 0) |
|
{ |
|
if (pthread_cond_timedwait(&_rep.cond, &_rep.mutex, &ts) != 0) |
|
{ |
|
pthread_mutex_unlock(&_rep.mutex); |
|
throw TimeOut(Threads::self()); |
|
} |
|
} |
|
|
|
_rep.owner = self; |
|
} |
|
|
|
_rep.count++; |
|
} |
|
pthread_mutex_unlock(&_rep.mutex); |
|
} |
|
|
|
void Mutex::unlock() |
|
{ |
|
PEGASUS_DEBUG_ASSERT(_magic); |
|
pthread_t self = pthread_self(); |
|
|
|
pthread_mutex_lock(&_rep.mutex); |
|
{ |
|
// If not locked or if calling thread is not the locker. |
|
|
|
if (_rep.count == 0 || !pthread_equal(_rep.owner, self)) |
|
PEGASUS_DEBUG_ASSERT(0); |
|
|
|
_rep.count--; |
|
_rep.owner = 0; |
|
pthread_cond_signal(&_rep.cond); |
|
} |
|
pthread_mutex_unlock(&_rep.mutex); |
|
} |
|
|
|
#endif /* PEGASUS_HAVE_PTHREADS && !PEGASUS_HAVE_RECURSIVE_MUTEXES */ |
| |
//============================================================================== | //============================================================================== |
// | // |