#include <errno.h>
#include <sys/time.h> // for struct timespec and gettimeofday()
#include "DSSemaphore.h"
DSSemaphore::DSSemaphore (
sInt32 initialCount)
: mExcessSignals (initialCount), mDestroying (false)
{
::pthread_mutex_init (&mConditionLock, NULL);
::pthread_cond_init (&mSemaphore, NULL);
}
DSSemaphore::~DSSemaphore (void)
{
::pthread_mutex_lock (&mConditionLock);
mDestroying = true;
::pthread_cond_broadcast (&mSemaphore);
::pthread_mutex_unlock (&mConditionLock);
::pthread_cond_destroy (&mSemaphore);
::pthread_mutex_destroy (&mConditionLock);
}
void
DSSemaphore::Signal (void)
{
::pthread_mutex_lock (&mConditionLock);
mExcessSignals++;
::pthread_cond_signal (&mSemaphore);
::pthread_mutex_unlock (&mConditionLock);
}
sInt32 DSSemaphore::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 ? semDestroyedErr : semNoErr);
}