diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-03-11 13:57:50 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-03-11 13:57:50 -0500 |
commit | 28887d5145e41c9e073c7c6e6990c4e218e05628 (patch) | |
tree | faf919c15c7e71ac859e505f4fc6ca967863e057 /wg.c |
stuff
Diffstat (limited to 'wg.c')
-rw-r--r-- | wg.c | 43 |
1 files changed, 43 insertions, 0 deletions
@@ -0,0 +1,43 @@ +#include <unistd.h> +#include <error.h> +#include <errno.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(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"); + } +} |