#include <sys/time.h> // for struct timespec and gettimeofday()
#include "NSLSemaphore.h"
NSLSemaphore::NSLSemaphore (
SInt32 initialCount)
: mExcessSignals (initialCount), mDestroying (false)
{
::pthread_mutex_init (&mConditionLock, NULL) ;
::pthread_cond_init (&mSemaphore, NULL) ;
}
NSLSemaphore::~NSLSemaphore (void)
{
::pthread_mutex_lock (&mConditionLock) ;
mDestroying = true ;
::pthread_mutex_unlock (&mConditionLock) ;
::pthread_cond_broadcast (&mSemaphore) ;
::pthread_cond_destroy (&mSemaphore) ;
::pthread_mutex_destroy (&mConditionLock) ;
}
void
NSLSemaphore::Signal (void)
{
::pthread_mutex_lock (&mConditionLock) ;
mExcessSignals++ ;
::pthread_mutex_unlock (&mConditionLock) ;
::pthread_cond_signal (&mSemaphore) ;
}
OSStatus
NSLSemaphore::Wait (SInt32 milliSecs)
{
::pthread_mutex_lock (&mConditionLock) ;
if ((mExcessSignals <= 0) && (milliSecs == kNever)) {
::pthread_mutex_unlock (&mConditionLock) ;
return semTimedOutErr ;
}
if (milliSecs == kForever) {
while (!mDestroying && (mExcessSignals <= 0))
::pthread_cond_wait (&mSemaphore, &mConditionLock) ;
} else {
struct timeval tvNow ;
struct timespec tsTimeout ;
::gettimeofday (&tvNow, NULL) ;
TIMEVAL_TO_TIMESPEC (&tvNow, &tsTimeout) ;
tsTimeout.tv_sec += (milliSecs / 1000) ;
tsTimeout.tv_nsec += ((milliSecs % 1000) * 1000000) ;
while (!mDestroying && (mExcessSignals <= 0))
if (ETIMEDOUT == ::pthread_cond_timedwait (&mSemaphore,
&mConditionLock, &tsTimeout)) {
::pthread_mutex_unlock (&mConditionLock) ;
return semTimedOutErr ;
}
}
if (!mDestroying)
mExcessSignals-- ;
::pthread_mutex_unlock (&mConditionLock) ;
return (mDestroying ? (OSStatus)semDestroyedErr : noErr) ;
}