22 * If the alarm list is empty, wait until an alarm is
23 * added. Setting current_alarm to 0 informs the insert
24 * routine that the thread is not busy.
25 */
26 current_alarm = 0;
27 while (alarm_list == NULL) {
28 status = pthread_cond_wait (&alarm_cond, &alarm_mutex);
29 if (status != 0)
30 err_abort (status, "Wait on cond");
31 }
32 alarm = alarm_list;
33 alarm_list = alarm->link;
34 now = time (NULL);
35 expired = 0;
36 if (alarm->time > now) {
37 #ifdef DEBUG
38 printf ("[waiting: %d(%d)\"%s\"]\n", alarm->time,
39 alarm->time - time (NULL), alarm->message);
40 #endif
41 cond_time.tv_sec = alarm->time;
42 cond_time.tv_nsec = 0;
43 current_alarm = alarm->time;
44 while (current_alarm == alarm->time) {
45 status = pthread_cond_timedwait (
46 &alarm_cond, &alarm_mutex, &cond_time);
47 if (Status == ETIMEDOUT) {
48 expired = 1;
49 break;
50 }
51 if (status != 0)
52 err_abort (status, "Cond timedwait");
53 }
54 if (!expired)
55 alarm_insert (alarm);
56 } else
57 expired = 1;
58 if (expired) {
59 printf ("(%d) %s\n", alarm->seconds, alarm->message);
60 free (alarm);
61 }
62 }
63 }
Part 4 shows the final section of alarm_cond.c, the main program. It is nearly identical to the main function from alarm_mutex.c.
38 Because the condition variable signal operation is built into the new alarm_ insert function, we call alarm_insert rather than inserting a new alarm directly.
■ alarm_cond.c part 4 main
1 int main (int argc, char *argv[])
2 {
3 int status;
4 char line[128];
5 alarm_t *alarm;
6 pthread_t thread; 7
8 status = pthread_create (
9 &thread, NULL, alarm thread, NULL);
10 if (status != 0)
11 err_abort (status, "Create alarm thread");
12 while (1) {
13 printf ("Alarm> ");
14 if (fgets (line, sizeof (line), stdin) == NULL) exit (0);
15 if (strlen (line) <= 1) continue;
16 alarm = (alarm_t*)malloc (sizeof (alarm_t));
17 if (alarm == NULL)
18 errno_abort ("Allocate alarm");
19
20 /*
21 * Parse input line into seconds (%d) and a message
22 * (%64[^\n]), consisting of up to 64 characters
23 * separated from the seconds by whitespace.
24 */
25 if (sscanf (line, "%d %64[^\n]",
26 &alarm->seconds, alarm->message) < 2) {
27 fprintf (stderr, "Bad command\n");
28 free (alarm);
29 } else {
30 status = pthread_mutex_lock (&alarm_mutex);
31 if (status != 0)
32 err_abort (status, "Lock mutex");
33 alarm->time = time (NULL) + alarm->seconds;
34 /*
35 * Insert the new alarm into the list of alarms,
36 * sorted by expiration time.
37 */
38 alarm_insert (alarm);
39 status = pthread_mutex_unlock (&alarm_mutex);
40 if (status != 0)
41 err_abort (status, "Unlock mutex");
42 }
43 }
44 }