Skip to content

Commit 2821a61

Browse files
committed
avoid cond_wait when not intending to change the queue
This also simplifies the signal/unlock code so that it actually uses singal first and then unlock to be in line with SUSv3 recommendation.
1 parent 29ad58b commit 2821a61

File tree

1 file changed

+21
-20
lines changed

1 file changed

+21
-20
lines changed

cond-variables/queue-simulation.c

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
* A randomness factor is used here to have the queue get some items in it and
1313
* also to hit both boundary cases (empty and full queue) from time to time.
14-
* When hitting a boundary, one of the thread actualy gets blocked on the
14+
* When hitting a boundary, one of the threads actualy gets blocked on the
1515
* condition variable.
1616
*
1717
@@ -41,6 +41,12 @@ producer(void *x)
4141
int msg_created;
4242

4343
while (1) {
44+
poll(NULL, 0, 95); /* sleep 95 ms */
45+
46+
msg_created = random() % 2;
47+
if (msg_created == 0)
48+
continue;
49+
4450
pthread_mutex_lock(&mutex);
4551
/* We can't insert a "message" when the queue is full. */
4652
while (in_queue == capacity) {
@@ -50,9 +56,7 @@ producer(void *x)
5056
(void) printf("Producer: woken up.\n");
5157
}
5258

53-
msg_created = random() % 2;
54-
55-
in_queue = in_queue + msg_created;
59+
in_queue += msg_created;
5660

5761
/*
5862
* If the queue was empty and we produced a "message", we must
@@ -64,16 +68,12 @@ producer(void *x)
6468
* We could also signal each time we insert a message but that
6569
* is really not necessary and would be actually wasteful.
6670
*/
67-
if (in_queue == 1 && msg_created > 0) {
68-
pthread_mutex_unlock(&mutex);
71+
if (in_queue == 1) {
6972
(void) printf("Producer: we inserted a message to "
7073
"an empty queue, signalling the consumer.\n");
7174
pthread_cond_signal(&cond);
72-
} else {
73-
pthread_mutex_unlock(&mutex);
7475
}
75-
76-
poll(NULL, 0, 95); /* sleep 95 ms */
76+
pthread_mutex_unlock(&mutex);
7777
}
7878
/* NOTREACHED */
7979
}
@@ -84,6 +84,12 @@ consumer(void *x)
8484
int msg_removed;
8585

8686
while (1) {
87+
poll(NULL, 0, 100); /* sleep 100 ms */
88+
89+
msg_removed = random() % 2;
90+
if (msg_removed == 0)
91+
continue;
92+
8793
pthread_mutex_lock(&mutex);
8894

8995
/*
@@ -98,24 +104,19 @@ consumer(void *x)
98104
}
99105

100106
int orig_in_queue = in_queue;
101-
msg_removed = random() % 2;
102107

103108
/*
104-
* If the queue was full and we pulled a "message(s)" from it we
105-
* will signal the producer so that it can start producing
109+
* If the queue was full and we pulled a "message(s)" from it,
110+
* signal the producer so that it can start producing
106111
* messages again.
107112
*/
108-
in_queue = in_queue - msg_removed;
109-
if (orig_in_queue == capacity && msg_removed > 0) {
113+
in_queue -= msg_removed;
114+
if (orig_in_queue == capacity) {
110115
(void) printf("Consumer: queue no longer full, "
111116
"signalling the producer.\n");
112-
pthread_mutex_unlock(&mutex);
113117
pthread_cond_signal(&cond);
114-
} else {
115-
pthread_mutex_unlock(&mutex);
116118
}
117-
118-
poll(NULL, 0, 100); /* sleep 100 ms */
119+
pthread_mutex_unlock(&mutex);
119120
}
120121

121122
/* NOTREACHED */

0 commit comments

Comments
 (0)