#include #include #include #include "wg.h" /* Thread management tools modeled on https://golang.org/pkg/sync/#WaitGroup */ /* pthread_cond_t is overly complicated. Just use a self-pipe. */ void wg_init(struct wg *wg) { wg->count = 0; pthread_mutex_init(&wg->lock, NULL); int fds[2]; if (pipe(fds) != 0) error(1, errno, "pipe"); wg->fd_wait = fds[0]; wg->fd_signal = fds[1]; } void wg_add(struct wg *wg, unsigned int n) { pthread_mutex_lock(&wg->lock); wg->count += n; pthread_mutex_unlock(&wg->lock); } void wg_sub(struct wg *wg, unsigned int n) { pthread_mutex_lock(&wg->lock); wg->count -= n; if (wg->count == 0) write(wg->fd_signal, " ", 1); pthread_mutex_unlock(&wg->lock); } void wg_wait(struct wg *wg) { char b; retry: if (read(wg->fd_wait, &b, 1) == -1) { if (errno == EINTR) goto retry; error(1, errno, "wg_wait"); } }