diff options
Diffstat (limited to 'src/wg.c')
-rw-r--r-- | src/wg.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/wg.c b/src/wg.c new file mode 100644 index 0000000..4f60765 --- /dev/null +++ b/src/wg.c @@ -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"); + } +} |