You want to use pthread_cond_broadcast()
instead of pthread_cond_signal()
. The former unblocks all threads waiting on a given condition.
views:
176answers:
4I have never used pthreads directly (I prefer Boost.Threads), but I think you should be calling pthread_cancel
instead of pthread_cond_signal
.
Firstly, you have to change your predicate from
if ( msq.empty() ) {
// no messages so wait for one.
pthread_cond_wait( &cnd, &lock );
}
to
while ( msq.empty() ) {
// no messages so wait for one.
pthread_cond_wait( &cnd, &lock );
}
That's a pthreads thing, you have to guard yourself against spurious wakeups.
Now you can change that to
while ( msq.empty() && !finished) {
// no messages so wait for one.
pthread_cond_wait( &cnd, &lock );
}
Since after that check, you already test whether finished is set and exits if so, all you have to do is signal all the threads.
So, in your teardown function, replace the loop with:
pthread_cond_broadcast(&cond);
That should ensure all threads wake up, and will see finished
set to true
and exit.
This is safe even if your threads are not stuck in pthread_cond_wait
. If the threads are processing a message, they will not get the wakeup signal, however they will finish that processing, enter the loop again and see that finished == false
and exit.
Another common pattern for this is to inject a poison message. A poison message is simply a special message your thread could recognise that would mean "STOP", you would place as many of those messages in your queue as you have threads.
I guess you should be unlocking the mutex after the call to pthread_cond_signal. Also, please check the condition of "finished" before you enter into conditional wait after acquiring the mutex. Hope this helps!