summaryrefslogtreecommitdiff
path: root/src/pool.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/pool.h')
-rw-r--r--src/pool.h74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/pool.h b/src/pool.h
new file mode 100644
index 0000000..675c184
--- /dev/null
+++ b/src/pool.h
@@ -0,0 +1,74 @@
+#ifndef _POOL_H_
+#define _POOL_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <atomic.h>
+
+/* A pool like a stack with an iterator walking from the bottom to the
+ * top. The memory foot print for a pool never shrinks. Thus this is
+ * not suitable for long-term uses. */
+
+struct pool_struct {
+ void **array;
+ size_t len; /* length of array */
+ size_t num; /* number of items in the array */
+ size_t idx; /* index used dy iter */
+ int state;
+ lock lock;
+};
+
+typedef struct pool_struct pool;
+
+pool *pool_new(void);
+void pool_free(pool *p);
+
+#define pool_lock(p) LOCK_ACQUIRE(&(p->lock))
+#define pool_unlock(p) LOCK_RELEASE()
+
+/*
+ * pool_push() pushes *v to pool *p. pool_push_lock() does this while
+ * locking *p.
+ */
+int pool_push(pool *p, void *v);
+int pool_push_lock(pool *p, void *v);
+
+/*
+ * pool_pop() pops the last *v pushed to *p. pool_pop_lock() does this
+ * while locking *p.
+ */
+void *pool_pop(pool *p);
+void *pool_pop_lock(pool *p);
+
+#define pool_size(p) ((p)->num)
+#define pool_get(p, idx) ((p->num <= idx) ? NULL : p->array[idx])
+
+/*
+ * pool->idx indicates next *v in an iteration. This has two
+ * use-cases.
+ *
+ * (1) A simple list: just a single thread has a pool, and the thread
+ * can call pool_iter_for_each() for the pool (not thread safe).
+ *
+ * (2) A thread-safe queue: one thread initializes the iterator for a
+ * pool by pool_iter_init(). Then, multiple threads get a next *v
+ * concurrently by pool_iter_next_lock(), which means dequeuing. At
+ * this time, other thread can add new *v by pool_push_lock(), which
+ * means enqueuing. During this, other threads must not intercept the
+ * pool by pool_iter_* functions.
+ */
+
+#define pool_iter_init(p) (p->idx = 0)
+void *pool_iter_next(pool *p);
+void *pool_iter_next_lock(pool *p);
+
+#define pool_iter_for_each(p, v) \
+ pool_iter_init(p); \
+ for (v = pool_iter_next(p); v != NULL; v = pool_iter_next(p))
+
+#define pool_for_each(p, v, idx) \
+ idx = 0; \
+ for (v = pool_get(p, idx); v != NULL; v = pool_get(p, ++idx))
+
+#endif /* _POOL_H_ */