summaryrefslogtreecommitdiff
path: root/wg.c
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-03-11 13:57:50 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-03-11 13:57:50 -0500
commit28887d5145e41c9e073c7c6e6990c4e218e05628 (patch)
treefaf919c15c7e71ac859e505f4fc6ca967863e057 /wg.c
stuff
Diffstat (limited to 'wg.c')
-rw-r--r--wg.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/wg.c b/wg.c
new file mode 100644
index 0000000..3208aa1
--- /dev/null
+++ b/wg.c
@@ -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");
+ }
+}