I’m trying to implement a sort of thread pool whereby I keep threads in a FIFO and process a bunch of images. Unfortunately, for some reason my cond_wait doesn’t always wake even though it’s been signaled.
// Initialize the thread pool
for(i=0;i<numThreads;i++)
{
pthread_t *tmpthread = (pthread_t *) malloc(sizeof(pthread_t));
struct Node* newNode;
newNode=(struct Node *) malloc(sizeof(struct Node));
newNode->Thread = tmpthread;
newNode->Id = i;
newNode->threadParams = 0;
pthread_cond_init(&(newNode->cond),NULL);
pthread_mutex_init(&(newNode->mutx),NULL);
pthread_create( tmpthread, NULL, someprocess, (void*) newNode);
push_back(newNode, &threadPool);
}
for() //stuff here
{
//...stuff
pthread_mutex_lock(&queueMutex);
struct Node *tmpNode = pop_front(&threadPool);
pthread_mutex_unlock(&queueMutex);
if(tmpNode != 0)
{
pthread_mutex_lock(&(tmpNode->mutx));
pthread_cond_signal(&(tmpNode->cond)); // Not starting mutex sometimes?
pthread_mutex_unlock(&(tmpNode->mutx));
}
//...stuff
}
destroy_threads=1;
//loop through and signal all the threads again so they can exit.
//pthread_join here
}
void *someprocess(void* threadarg)
{
do
{
//...stuff
pthread_mutex_lock(&(threadNode->mutx));
pthread_cond_wait(&(threadNode->cond), &(threadNode->mutx));
// Doesn't always seem to resume here after signalled.
pthread_mutex_unlock(&(threadNode->mutx));
} while(!destroy_threads);
pthread_exit(NULL);
}
Am I missing something? It works about half of the time, so I would assume that I have a race somewhere, but the only thing I can think of is that I’m screwing up the mutexes? I read something about not signalling before locking or something, but I don’t really understand what’s going on.
Any suggestions?
Thanks!
Firstly, your example shows you locking the
queueMutexaround the call topop_front, but not roundpush_back. Typically you would need to lock round both, unless you can guarantee that all the pushes happen-before all the pops.Secondly, your call to
pthread_cond_waitdoesn’t seem to have an associated predicate. Typical usage of condition variables is:In this example,
readyis some variable that is set by another thread whilst that thread holds a lock onmtx.If the waiting thread is not blocked in the
pthread_cond_waitwhenpthread_cond_signalis called then the signal will be ignored. The associatedreadyvariable allows you to handle this scenario, and also allows you to handle so-called spurious wake-ups where the call topthread_cond_waitreturns without a corresponding call topthread_cond_signalfrom another thread.