diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-04-08 16:39:03 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-04-08 16:39:03 -0400 |
commit | 608f4f254ccf95a01b5480e2dbe7a1b6e54c8609 (patch) | |
tree | b6a2dfe147ced25a86e1954c992435afd6b20678 /wg.c | |
parent | d3a6398406f1a3f222c7ca00d4e4608267148456 (diff) |
sitting here
Diffstat (limited to 'wg.c')
-rw-r--r-- | wg.c | 45 |
1 files changed, 45 insertions, 0 deletions
@@ -0,0 +1,45 @@ +#include <errno.h> +#include <error.h> +#include <stdlib.h> /* for EXIT_FAILURE */ +#include <unistd.h> + +#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(EXIT_FAILURE, 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) + if (write(wg->fd_signal, " ", 1) < 1) + error(EXIT_FAILURE, errno, "write"); + 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(EXIT_FAILURE, errno, "wg_wait"); + } +} |