title: In pthread, how to reliably pass signal to another thread?
body: <p>I'm trying to write a simple thread pool program in pthread. However, it seems that <code>pthread_cond_signal</code> doesn't block, which creates a problem. For example, let's say I have a "producer-consumer" program:</p>
  
  <pre><code>pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER;
  pthread_mutex_t my_cond_m = PTHREAD_MUTEX_INITIALIZER;
  
  void * liberator(void * arg)
  {
      // XXX make sure he is ready to be freed
      sleep(1);
  
      pthread_mutex_lock(&amp;my_cond_m);
      pthread_cond_signal(&amp;my_cond);
      pthread_mutex_unlock(&amp;my_cond_m);
  
      return NULL;
  }
  
  int main()
  {
      pthread_t t1;
      pthread_create(&amp;t1, NULL, liberator, NULL);
  
      // XXX Don't take too long to get ready. Otherwise I'll miss 
      // the wake up call forever
      //sleep(3);
  
      pthread_mutex_lock(&amp;my_cond_m);
      pthread_cond_wait(&amp;my_cond, &amp;my_cond_m);
      pthread_mutex_unlock(&amp;my_cond_m);
  
      pthread_join(t1, NULL);
  
      return 0;
  }
  </code></pre>
  
  <p>As described in the two <code>XXX</code> marks, if I take away the <code>sleep</code> calls, then <code>main()</code> may stall because it has missed the wake up call from <code>liberator()</code>. Of course, <code>sleep</code> isn't a very robust way to ensure that either.</p>
  
  <p>In real life situation, this would be a worker thread telling the manager thread that it is ready for work, or the manager thread announcing that new work is available.</p>
  
  <p>How would you do this reliably in pthread?</p>
  
  <hr>
  
  <h2>Elaboration</h2>
  
  <p>@Borealid's answer kind of works, but his explanation of the problem could be better. I suggest anyone looking at this question to read the discussion in the comments to understand what's going on.</p>
  
  <p>In particular, I myself would amend his answer and code example like this, to make this clearer. (Since Borealid's original answer, while compiled and worked, confused me a lot)</p>
  
  <pre><code>// In main
  pthread_mutex_lock(&amp;my_cond_m);
  
  // If the flag is not set, it means liberator has not 
  // been run yet. I'll wait for him through pthread's signaling 
  // mechanism
  
  // If it _is_ set, it means liberator has been run. I'll simply 
  // skip waiting since I've already synchronized. I don't need to 
  // use pthread's signaling mechanism
  if(!flag) pthread_cond_wait(&amp;my_cond, &amp;my_cond_m);
  
  pthread_mutex_unlock(&amp;my_cond_m);
  
  // In liberator thread
  pthread_mutex_lock(&amp;my_cond_m);
  
  // Signal anyone who's sleeping. If no one is sleeping yet, 
  // they should check this flag which indicates I have already 
  // sent the signal. This is needed because pthread's signals 
  // is not like a message queue -- a sent signal is lost if 
  // nobody's waiting for a condition when it's sent.
  // You can think of this flag as a "persistent" signal
  flag = 1;
  pthread_cond_signal(&amp;my_cond);
  pthread_mutex_unlock(&amp;my_cond_m);
  </code></pre>