Craig Rodrigues
It is possible to implement semaphore's with mutexes and condition variables. I looked at the source code for FreeBSD 5.2's implementation of semaphores to see how this was done:
http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/lib/libpthread/thre ad/thr_sem.c
I even took a whack at writing one based on Boost (it may be buggy):
#include
#include struct mysem { mysem(unsigned int count): count_(count) {}
void post() { boost::mutex::scoped_lock l(sem_mutex_); ++count_; sem_cond_.notify_all();
notify_one() should be safe and more efficient here, because any of the waiters can be satisfied by the change you have made. Use notify_all() where waiters are waiting for different conditions on the same condition variable. (I'm not sure I expressed that exactly correctly - can anyone improve on that?)
}
void wait() { boost::mutex::scoped_lock l(sem_mutex_); for(;;) {
if( count_ == 0 ) sem_cond_.wait(l);
This is wrong - you must always use while rather than if to test the inverse of the condition you are waiting for because it is possible that the condition is no longer true when wait() returns. (There is also a function template for wait() that tests a predicate for you.) It is even possible on some systems for wait() to return even though no-one called notify_one() or notify_all().
else { --count_; break; } } }
private: unsigned int count_; boost::mutex sem_mutex_; boost::condition sem_cond_; };
What kinds of things can go wrong if I use this class?
<snip> The other potential problem I see is overflow of count_, but it is exceedingly unlikely that you will be able to create enough threads to cause that.