after reading the c++ standards, I am still somewhat unclear as to what should happen when there are more then one thread blocked on a conditional and a third thread signals the condition.
From the spec:
The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond).
If more than one thread is blocked on a condition variable, the scheduling policy shall determine the order in which threads are unblocked.
Here it says at least one... but what does that really mean? - one and only one, or some undefined number of threads with a minimum of one?
I tested this with 3 threads (just showing the main loop): Note: This is pointless code, I am just using it to learn, and I know I can use pthread_cond_broadcast(), but I just want to fully understand pthread_cond_signal() first.
ticker thread: increments 'counter' and signals 'tickOccured' i.e. 'counter' has changed
while (1)
{
// Get the mutex
pthread_mutex_lock(&mutex);
counter++;
std::cout << "\t\t ticker: " << counter << std::endl;
// Tell others that a tick has occured
pthread_cond_signal(&tickOccured);
// Release
pthread_mutex_unlock(&mutex);
sleep(1);
}
worker thread: checks the value of 'counter' and determines if thread3 should end by setting flag 'closeStarter'
while (1)
{
// Get the mutex
pthread_mutex_lock(&mutex);
// Wait for a tick
std::cout << "\t\t\t\t waiting..." << std::endl;
pthread_cond_wait(&tickOccured, &mutex);
std::cout << "\t\t\t\t worker: " << counter << std::endl;
// Check if its time to end the starter
if (counter >= TIME_FOR_STARTER_TO_EXIT)
{
// Set close starter flag
closeStarter = true;
}
// Release
pthread_mutex_unlock(&mutex);
}
starter thread: checks the flag 'closeStarter' and if its true exits
// Monitor things for a while and then exit when its time
while (!closeStarter)
{
// Get the mutex
pthread_mutex_lock(&mutex);
std::cout << "Starter: waiting..." << std::endl;
pthread_cond_wait(&tickOccured, &mutex);
std::cout << "Starter: " << counter << std::endl;
// Release
pthread_mutex_unlock(&mutex);
}
std::cout << "Starter: Exiting..." << std::endl;
pthread_exit(NULL);
Result: What I observe is
Starter: Starting...
ticker: Starting...
ticker: 1
worker: Starting...
Starter: waiting...
worker: waiting...
ticker: 2
Starter: 2
Starter: waiting...
ticker: 3
worker: 3
worker: waiting...
ticker: 4
Starter: 4
Starter: waiting...
ticker: 5
worker: 5
worker: waiting...
ticker: 6
Starter: 6
Starter: Exiting...
ticker: 7
worker: 7
worker: waiting...
ticker: 8
worker: 8
worker: waiting...
ticker: 9
worker: 9
worker: waiting...
So when both starter and worker are waiting, only one or other get the signal, but never both. When starter exists, then worker always gets the signal. You would expect this behaviour as well if the spec read: one and only one thread will be unblocked, but it says at least one, so is there a case where more then one thread can be unblocked?
It's probably a fringe case I am talking about here, but I want to understand what this means. Example, if I wanted keep a queue of threads waiting for the same event, then I would need to ensure that only one receives the signal...