diff options
Diffstat (limited to 'src/pool.h')
-rw-r--r-- | src/pool.h | 74 |
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_ */ |