cnd_wait blocks a thread until its condition variable is signaled, temporarily releasing the caller-held mutex and reacquiring it before returning. Test the shared condition in a loop, because returning does not by itself establish that the condition is true. section 18.5
Waiting until accounting work exists
mtx_lock(&L->mtx); while (!L->finished && (L->accounted == L->iteration)) cnd_wait(&L->acco, &L->mtx); life_account(L); mtx_unlock(&L->mtx); The mutex protects the condition and the data used after the wait. Another thread signals the condition after changing shared state. section 18.5
Use cnd_wait with these rules:
- Hold the mutex before calling cnd_wait. section 18.5
- Keep one mutex associated with a condition variable; one mutex may serve several condition variables. section 18.5
- Use cnd_signal to wake one waiter or cnd_broadcast to wake all waiters. section 18.5
Listing 18.2. The account thread function of B9
99 int account_thread(void* Lv) {
100 life*restrict L = Lv;
101 while (!L->finished) {
102 // Blocks until there is work
103 mtx_lock(&L->mtx);
104 while (!L->finished && (L->accounted == L->iteration))
105 life_wait(&L->acco, &L->mtx);
106
107 // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
108 life_account(L);
109 if ((L->last + repetition) < L->accounted) {
110 L->finished = true;
111 }
112 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
113
114 cnd_signal(&L->upda);
115 mtx_unlock(&L->mtx);
116 }
117 return 0;
118 }
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":1},{\"line\":0,\"ch\":3}],[{\"line\":0,\"ch\":6},{\"line\":0,\"ch\":9}],[{\"line\":0,\"ch\":25},{\"line\":0,\"ch\":29}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":3}],[{\"line\":1,\"ch\":13},{\"line\":1,\"ch\":21}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":3}],[{\"line\":2,\"ch\":8},{\"line\":2,\"ch\":13}],[{\"line\":5,\"ch\":10},{\"line\":5,\"ch\":15}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":3}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":3}],[{\"line\":4,\"ch\":10},{\"line\":4,\"ch\":18}],[{\"line\":5,\"ch\":0},{\"line\":5,\"ch\":3}],[{\"line\":2,\"ch\":8},{\"line\":2,\"ch\":13}],[{\"line\":5,\"ch\":10},{\"line\":5,\"ch\":15}],[{\"line\":6,\"ch\":0},{\"line\":6,\"ch\":3}],[{\"line\":7,\"ch\":0},{\"line\":7,\"ch\":3}],[{\"line\":8,\"ch\":0},{\"line\":8,\"ch\":3}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":3}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":3}],[{\"line\":1,\"ch\":9},{\"line\":1,\"ch\":11}],[{\"line\":6,\"ch\":13},{\"line\":6,\"ch\":15}],[{\"line\":9,\"ch\":11},{\"line\":9,\"ch\":13}],[{\"line\":10,\"ch\":10},{\"line\":10,\"ch\":12}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":3}],[{\"line\":11,\"ch\":26},{\"line\":11,\"ch\":30}],[{\"line\":12,\"ch\":0},{\"line\":12,\"ch\":3}],[{\"line\":13,\"ch\":0},{\"line\":13,\"ch\":3}],[{\"line\":14,\"ch\":0},{\"line\":14,\"ch\":3}],[{\"line\":15,\"ch\":0},{\"line\":15,\"ch\":3}],[{\"line\":15,\"ch\":10},{\"line\":15,\"ch\":20}],[{\"line\":16,\"ch\":0},{\"line\":16,\"ch\":3}],[{\"line\":16,\"ch\":10},{\"line\":16,\"ch\":20}],[{\"line\":17,\"ch\":0},{\"line\":17,\"ch\":3}],[{\"line\":18,\"ch\":0},{\"line\":18,\"ch\":3}],[{\"line\":18,\"ch\":8},{\"line\":18,\"ch\":14}],[{\"line\":19,\"ch\":0},{\"line\":19,\"ch\":3}]]"}
!@%STYLE%@!
Browse the complete account-thread example showing mutex acquisition, predicate checking, cnd_wait, work, signaling, and unlock. section 18.5

