#include "al_siteconfig.h" #include "al_debug.h" #include "al_source.h" #include "al_spool.h" #include #include /* * Resize spool to at least newsize units */ ALboolean spool_resize(spool_t *spool, size_t newsize) { void *temp; unsigned int i; if(newsize < 1) { newsize = 1; } if(spool->size >= newsize) { return AL_TRUE; /* no resize needed */ } /* * Resize the AL_source pool. */ temp = realloc(spool->pool, newsize * sizeof *spool->pool); if(temp == NULL) { return AL_FALSE; /* could not realloc */ } spool->pool = temp; /* * Set use flags for AL_source pool. */ for(i = spool->size; i < newsize; i++) { spool->pool[i].inuse = AL_FALSE; } /* * Resize the sid -> index map. */ temp = realloc(spool->map, newsize * sizeof *spool->map); if(temp == NULL) { return AL_FALSE; /* could not resize map */ } spool->map = temp; for(i = spool->size; i < newsize; i++) { spool->map[i] = 0; } spool->size = newsize; return AL_TRUE; } /* * Reserve an AL_source in spool, returning the index of the AL_source, * and mark it in use. Return -1 if no reservation is possible. */ int spool_alloc(spool_t *spool) { int sindex; sindex = spool_first_free_index(spool); if(sindex == -1) { if(spool_resize(spool, spool->size * 2) == AL_FALSE) { return -1; } sindex = spool_first_free_index(spool); } spool->pool[sindex].inuse = AL_TRUE; spool->map[sindex] = spool_next_id(); return spool->map[sindex]; } /* * Get the AL_source from sourcepool spool at index index, if * it's in use. Otherwise, return NULL. */ AL_source *spool_index(spool_t *spool, ALuint sid) { int sindex; sindex = spool_sid_to_index(spool, sid); if(sindex < 0) { return NULL; } if(sindex >= (int) spool->size) { return NULL; } if(spool->pool[sindex].inuse == AL_FALSE) { return NULL; } return &spool->pool[sindex].data; } int spool_first_free_index(spool_t *spool) { unsigned int i; for(i = 0; i < spool->size; i++) { if(spool->pool[i].inuse == AL_FALSE) { return i; } } return -1; } ALboolean spool_dealloc(spool_t *spool, ALuint sid, void (*freer_func)(void *)) { AL_source *src; int sindex; sindex = spool_sid_to_index(spool, sid); if(sindex < 0) { /* sid is invalid */ return AL_FALSE; } if(sindex >= (int) spool->size) { return AL_FALSE; } src = spool_index(spool, sid); if(src == NULL) { debug(ALD_SOURCE, __FILE__, __LINE__, "sid %d is a bad index", sid); return AL_FALSE; } if(spool->pool[sindex].inuse == AL_FALSE) { /* already deleted */ return AL_FALSE; } freer_func(src); spool->pool[sindex].inuse = AL_FALSE; return AL_TRUE; } void spool_free(spool_t *spool, void (*freer_func)(void *)) { unsigned int i; ALuint sid; for(i = 0; i < spool->size; i++) { if(spool->pool[i].inuse == AL_TRUE) { sid = spool->pool[i].data.sid; spool_dealloc(spool, sid, freer_func); } } if(spool->pool != NULL) { free(spool->pool); spool->pool = NULL; } if(spool->map != NULL) { free(spool->map); spool->map = NULL; } spool->size = 0; /* let the caller free spool itself */ return; } void spool_init(spool_t *spool) { if(spool == NULL) { return; } spool->size = 0; spool->pool = NULL; spool->map = NULL; return; } /* * Get unique id. */ ALuint spool_next_id(void) { static ALuint id = AL_FIRST_SOURCE_ID; return ++id; } /* * Convert the sid to an index in spool's pool. This is * to enable unique sids but reuse the indexes. * * FIXME: use binary search. */ int spool_sid_to_index(spool_t *spool, ALuint sid) { unsigned int i; for(i = 0; i < spool->size; i++) { if(spool->map[i] == sid) { return i; } } return -1; }