shown in the following example, cond_static.c.
¦ cond_static.c
1 #include <pthread.h>
2 #include 'errors.h'
3
4 /*
5 * Declare a structure, with a mutex and condition variable,
6 * statically initialized. This is the same as using
7 * pthread_mutex_init and pthread_cond_init, with the default
8 * attributes.
9 */
10 typedef struct my_struct_tag {
11 pthread_mutex_t mutex; /* Protects access to value */
12 pthread_cond_t cond; /* Signals change to value */
13 int value; /* Access protected by mutex */
14 } my_struct_t;
15
16 my_struct_t data = {
17 PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
18
19 int main (int argc, char *argv[])
20 {
21 return 0 ;
22 }
Condition variables and their predicates are 'linked'—for best results, treat them that way!
When you declare a condition variable, remember that a condition variable and the associated predicate are 'locked together.' You may save yourself (or your successor) some confusion by always declaring the condition variable and predicate together, if possible. I recommend that you try to encapsulate a set of invariants and predicates with its mutex and one or more condition variables as members in a structure, and carefully document the association.
Sometimes you cannot initialize a condition variable statically; for example, when you use malloc to create a structure that contains a condition variable. Then you will need to call pthread_cond_init to initialize the condition variable dynamically, as shown in the following example, cond_dynamic.c. You can also dynamically initialize condition variables that you declare statically—but you must ensure that each condition variable is initialized before it is used, and that each is initialized only once. You may initialize it before creating any threads, for example, or by using pthread_once (Section 5.1). If you need to initialize a condition variable with nondefault attributes, you must use dynamic initialization (see Section 5.2.2).
¦ cond_dynamic.c
1 #include <pthread.h>
2 #include 'errors.h' 3
4 /*
5 * Define a structure, with a mutex and condition variable.
6 */
7 typedef struct my_struct_tag {
8 pthread_mutex_t mutex; /* Protects access to value */
9 pthread_cond_t cond; /* Signals change to value */
10 int value; /* Access protected by mutex */
11 } my_struct_t;
12
13 int main (int argc, char *argv[])
14 {
15 my_struct_t *data;
16 int status;
17
18 data = malloc (sizeof (my_struct_t));
19 if (data == NULL)
20 errno_abort ('Allocate structure');
21 status = pthread_mutex_init (&data->mutex, NULL);
22 if (status != 0)
23 err_abort (status, 'Init mutex');
24 status = pthread_cond_init (&data->cond, NULL);
25 if (status != 0)
26 err_abort (status, 'Init condition');
27 status = pthread_cond_destroy (&data->cond);
28 if (status != 0)
29 err_abort (status, 'Destroy condition');
30 status = pthread_mutex_destroy (&data->mutex);
31 if (status != 0)
32 err_abort (status, 'Destroy mutex');
33 (void)free (data);
34 return status;
35 }
When you dynamically initialize a condition variable, you should destroy the condition variable when you no longer need it, by calling pthread_cond_destroy. You do not need to destroy a condition variable that was statically initialized using the PTHREAD_COND_INITIALIZER macro.
It is safe to destroy a condition variable when you know that no threads can be blocked on the condition variable, and no additional threads will try to wait on, signal, or broadcast the condition variable. The best way to determine this is usually within a thread that has just successfully broadcast to unblock all waiters, when program logic ensures that no threads will try to use the condition variable later.
When a thread removes a structure containing a condition variable from a list, for example, and then broadcasts to awaken any waiters, it is safe (and also a very good idea) to destroy the condition variable before freeing the storage that the condition variable occupies. The awakened threads should check their wait predicate when they resume, so you must make sure that you don't free resources required for the predicate before they've done so—this may require additional synchronization.
3.3.2 Waiting on a condition variable
int pthread_cond_wait (pthread_cond_t *cond,
pthread_mutex_t *mutex);
int pthread_cond_timedwait (pthread_cond_t *cond,
pthread_mutex_t *mutex,
struct timespec *expiration);
Each condition variable must be associated with a specific mutex, and with a predicate condition. When a thread waits on a condition variable it must always have the associated mutex locked. Remember that the condition variable wait operation will
All threads that wait on any one condition variable concurrently (at the same time) must specify the