aboutsummaryrefslogtreecommitdiffstats
path: root/libaxl_generate_id.c
diff options
context:
space:
mode:
Diffstat (limited to 'libaxl_generate_id.c')
-rw-r--r--libaxl_generate_id.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/libaxl_generate_id.c b/libaxl_generate_id.c
index 232ef4d..91b5aa6 100644
--- a/libaxl_generate_id.c
+++ b/libaxl_generate_id.c
@@ -5,8 +5,34 @@ libaxl_id_t
libaxl_generate_id(LIBAXL_CONTEXT *ctx)
{
LIBAXL_CONNECTION *conn = ctx->conn;
+ struct id_pool *pool = NULL, *next, *last;
uint32_t id;
+ pool = atomic_exchange(&conn->xid_pool, pool);
+ if (pool) {
+ id = pool->first;
+ pool->first += (uint32_t)1 << conn->xid_shift;
+ if (id == pool->last) {
+ next = pool->next;
+ if (next) {
+ free(pool);
+ pool = next;
+ }
+ next = NULL;
+ if (atomic_compare_exchange_strong(&conn->xid_pool, &next, pool))
+ return id;
+ if (!pool->next) {
+ free(pool);
+ return id;
+ }
+ }
+ while ((pool = atomic_exchange(&conn->xid_pool, pool))) {
+ for (last = pool; last->next; last = last->next);
+ last->next = atomic_exchange(&conn->xid_pool, NULL);
+ }
+ return id;
+ }
+
id = atomic_fetch_add(&conn->xid_last, 1);
if (id <= conn->xid_max)
return (id << conn->xid_shift) | conn->xid_base;