liveBook · Manning

Cnd_wait

As explained in Modern C

cnd_wait is a C standard threads function that atomically releases a mutex while waiting on a condition variable and reacquires the mutex before returning.

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

How Modern C covers it

How deep it goes
Explains mutex handoff, predicate loops, signaling, and coupling rules, but defers implementation internals.
Examples
Uses account, update, and draw threads waiting on distinct predicates protected by one mutex.
What it assumes
Assumes mutexes, condition variables, shared state, and critical sections.
What you can do after
Apply cnd_wait in a mutex-protected predicate loop and coordinate wakeups with condition-variable signaling.
How it connects
Connects condition variables with mutexes, shared-state predicates, cnd_signal, and cnd_broadcast.

Also explained in

Compare how 2 books explain cnd_wait →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C. The section links point to the parts of the book it draws on.