Advanced Programming in the UNIX® Environment

(lily) #1
ptg10805159

416 Threads Chapter 11


#include <pthread.h>
struct msg {
struct msg *m_next;
/* ... more stuff here ... */
};
struct msg *workq;
pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;

void
process_msg(void)
{
struct msg *mp;
for (;;) {
pthread_mutex_lock(&qlock);
while (workq == NULL)
pthread_cond_wait(&qready, &qlock);
mp = workq;
workq = mp->m_next;
pthread_mutex_unlock(&qlock);
/* now process the message mp */
}
}
void
enqueue_msg(struct msg *mp)
{
pthread_mutex_lock(&qlock);
mp->m_next = workq;
workq = mp;
pthread_mutex_unlock(&qlock);
pthread_cond_signal(&qready);
}

Figure 11.15 Using a condition variable

The condition is the state of the work queue.We protect the condition with a mutex
and evaluate the condition in awhileloop. When we put a message on the work
queue, we need to hold the mutex, but we don’t need to hold the mutex when we signal
the waiting threads. As long as it is okay for a thread to pull the message offthe queue
before we callcond_signal, we can do this after releasing the mutex. Since we check
the condition in awhileloop, this doesn’t present a problem; a thread will wake up,
find that the queue is still empty,and go back to waiting again. If the code couldn’t
tolerate this race, we would need to hold the mutex when we signal the threads.
Free download pdf