/* 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); } }