| git.druid.rocks | index | militantprogrammer | astral_canvas | src/ | lib/ | id.c |
src/lib/id.c
#include "lib/id.h"
#include <pthread.h>
#include <stdlib.h>
static pthread_mutex_t mu;
static int ready;
static unsigned short next_id;
static unsigned short *free_ids;
static unsigned free_count;
static unsigned free_cap;
int idPoolInit(void)
{
if (ready)
idPoolDestroy();
if (pthread_mutex_init(&mu, NULL) != 0)
return -1;
next_id = 1;
free_ids = NULL;
free_count = 0;
free_cap = 0;
ready = 1;
return 0;
}
void idPoolDestroy(void)
{
if (!ready)
return;
pthread_mutex_lock(&mu);
free(free_ids);
free_ids = NULL;
free_count = 0;
free_cap = 0;
next_id = 1;
pthread_mutex_unlock(&mu);
pthread_mutex_destroy(&mu);
ready = 0;
}
unsigned short libAllocId(void)
{
unsigned short id;
if (!ready)
return 0;
pthread_mutex_lock(&mu);
if (free_count > 0) {
free_count--;
id = free_ids[free_count];
pthread_mutex_unlock(&mu);
return id;
}
id = next_id;
if (id == 0) {
pthread_mutex_unlock(&mu);
return 0;
}
next_id++;
pthread_mutex_unlock(&mu);
return id;
}
void libFreeId(unsigned short id)
{
unsigned short *grown;
unsigned cap;
if (!ready || id == 0)
return;
pthread_mutex_lock(&mu);
if (free_count == free_cap) {
cap = free_cap ? free_cap * 2 : 16;
grown = realloc(free_ids, cap * sizeof(*grown));
if (!grown) {
pthread_mutex_unlock(&mu);
return;
}
free_ids = grown;
free_cap = cap;
}
free_ids[free_count++] = id;
pthread_mutex_unlock(&mu);
}