condition variable - why calling pthread_cond_signal() before calling pthread_cond_wait() is a logical error?
The answer of blaze comes closest, but is not totally clear:
conditional variables should only be used to signal a change in a condition.
Thread 1 checks a condition. If the condition doesn't meet, he waits on the condition variable until the condition meets. Because the condition is checked first, he shouldn't care whether the condition variable was signaled:
pthread_mutex_lock(&mutex);
while (!condition)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
Thread 2 changes the condition and signals the change via the condition variable. He doesn't care whether threads are waiting or not:
pthread_mutex_lock(&mutex);
changeCondition();
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond)
The bottom line is: the communication is done via some condition. A condition variable only wakes up waiting threads so they can check the condition.
Examples for conditions:
- Queue is not empty, so an entry can be taken from the queue
- A boolean flag is set, so the thread wait s until the other thread signal it's okay to continue
- some bits in a bitset are set, so the waiting thread can handle the corresponding events
see also pthread example
My 2 cents: I do not know the side effects of calling *pthread_cond_signal()* when no thread has been blocked calling *pthread_cond_wait()*. This is really an implementation detail What I think is that, if your threading/timimg model do not guarantee the rigth order between wait and signal, probably you should consider a different sync mechanism [like a simple semaphore, for example] when you can signal the semaphore from thread B even if the thread A has nor reached the sync point. When thread A will reach the sync point, it will find the semaphore incremented and will enter the critical session.
A condition variable allows one thread to wake another up from a wait. They work only if there is a thread waiting at the moment when you trigger the condition. The way to ensure that this is the case is for the waiting thread to lock a mutex which is linked to the condition, and for the signalling thread to lock that mutex before triggering the condition. In other words, the signalling thread can only lock the mutex and trigger the condition if the other thread had the mutex locked but is now waiting.
I'm most familiar with boost, so I'll use that in this example:
// A shared mutex, global in this case.
boost::mutex myMutex;
// Condition variable
boost::condition_variable myCondition;
void threadProc()
{
// Lock the mutex while the thread is running.
boost::mutex::scoped_lock guard( myMutex );
while( true )
{
// Do stuff, then...
myCondition.wait( guard ); // Unlocks the mutex and waits for a notification.
}
}
void func()
{
// Function wants to trigger the other thread. Locks the mutex...
boost::mutex::scoped_lock guard( myMutex );
// Since the mutex is locked, we know that the other thread is
// waiting on the condition variable...
myCondition.notify_all();
}
To signal a condition variable when there is no corresponding wait is a logical error because nothing will ever receive the signal. Condition variables don't remain in a signalled state.