olegst
olegst

Reputation: 1267

pthread_cond_signal from multiple threads

Let's imagine there is a thread which calls pthread_cond_wait and waits for signals:

   pthread_mutex_lock(&m);
         .....
   while(run) 
   {
      do {
        pthread_cond_wait(&cond,&m);
      } while(!got_signal);
      got_signal = false;
      do_something();
   }

And there are multiple threads which are supposed to deliver signals:

pthread_mutex_lock(&m);
got_signal = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);

Is this solution safe enough? What will happen if multiple threads send signals? Does m mutex suffice to guarantee all signals are serialized and won't be lost?

Upvotes: 1

Views: 3196

Answers (1)

sonicwave
sonicwave

Reputation: 6092

In the code you posted, the only place where threads are allowed to call pthread_cond_signal() is when they can acquire m, and that can only happen when your waiting thread is blocked on pthread_cond_wait().

However, it might happen that two signaling threads acquire the mutex after each other, before the waiting thread is woken up and can acquire the mutex. In that case you'll lose the second signal (and any further signals that might arrive after that, before the waiting thread runs), since your waiting thread can only "see" that it has been signaled, but not how many times this has happened.

To make sure that you don't lose any signals, you could use a counter instead of your got_signal flag:

Waiting thread:

pthread_mutex_lock(&m);
     .....
while(run) 
{
   while(signal_count == 0) {
     pthread_cond_wait(&cond,&m);
   } 
   --signal_count;
   do_something();
}

Signaling threads:

pthread_mutex_lock(&m);
++signal_count;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);

(Also note that I've exchanged the do...whileloop with a while loop, to make sure that pthread_cond_wait() isn't called if there's still an unprocessed signal left.)

Now, if multiple threads end up signaling straight after each other, signal_count will become more than one, which will cause the waiting thread to run its do_something() multiple times instead of just once.

Upvotes: 3

Related Questions