更新时间:2022-10-15 14:32:11
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.