lw-support/src/liblw-support/Thread/Semaphore.cpp

83 lines
1.5 KiB
C++
Raw Normal View History

2006-08-25 00:09:46 +01:00
/* lw-support/src/lib/Thread/Semaphore.cpp
*
* (c)2005, Laurence Withers. Released under the GNU GPL. See file
* COPYING for more information / terms of license.
*/
namespace lw {
Semaphore::Semaphore(unsigned int init)
: val(init), waiting(0), err(false)
{
pthread_mutex_init(&mut, 0);
pthread_cond_init(&cond, 0);
}
Semaphore::~Semaphore()
{
signalError();
while(true) {
pthread_mutex_lock(&mut);
if(!waiting) break;
pthread_mutex_unlock(&mut);
pthread_yield();
}
pthread_mutex_unlock(&mut);
pthread_mutex_destroy(&mut);
}
void Semaphore::wait(int maxTime)
{
if(maxTime < 0) {
wait();
return;
}
// get current time
struct timeval tv;
gettimeofday(&tv, 0);
// compute absolute time
struct timespec ts;
ts.tv_sec = tv.tv_sec + (maxTime / 1000);
ts.tv_nsec = (tv.tv_usec * 1000) + (maxTime % 1000) * tenExp6;
if(ts.tv_nsec > tenExp9) {
++ts.tv_sec;
ts.tv_nsec -= tenExp9;
}
pthread_mutex_lock(&mut);
++waiting;
while(!val && !err) {
switch(pthread_cond_timedwait(&cond, &mut, &ts)) {
case ETIMEDOUT: {
--waiting;
pthread_mutex_unlock(&mut);
throw Timeout();
}
case 0: break;
}
}
if(err) {
--waiting;
pthread_mutex_unlock(&mut);
throw Error();
}
--val;
--waiting;
pthread_mutex_unlock(&mut);
}
}