d9bf4f7620
If the requested number of mono and stereo sources exceeds 256, the source limit will be expanded. Any config file setting overrides this. If the device is reset to have fewer sources than are currently allocated, excess sources will remain and be usable as normal, but no more can be generated until enough are delated to go back below the limit.
320 lines
8.2 KiB
C
320 lines
8.2 KiB
C
|
|
#include "config.h"
|
|
|
|
#include "uintmap.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "almalloc.h"
|
|
|
|
|
|
extern inline void LockUIntMapRead(UIntMap *map);
|
|
extern inline void UnlockUIntMapRead(UIntMap *map);
|
|
extern inline void LockUIntMapWrite(UIntMap *map);
|
|
extern inline void UnlockUIntMapWrite(UIntMap *map);
|
|
|
|
|
|
void InitUIntMap(UIntMap *map, ALsizei limit)
|
|
{
|
|
map->keys = NULL;
|
|
map->values = NULL;
|
|
map->size = 0;
|
|
map->capacity = 0;
|
|
map->limit = limit;
|
|
RWLockInit(&map->lock);
|
|
}
|
|
|
|
void ResetUIntMap(UIntMap *map)
|
|
{
|
|
WriteLock(&map->lock);
|
|
al_free(map->keys);
|
|
map->keys = NULL;
|
|
map->values = NULL;
|
|
map->size = 0;
|
|
map->capacity = 0;
|
|
WriteUnlock(&map->lock);
|
|
}
|
|
|
|
void RelimitUIntMapNoLock(UIntMap *map, ALsizei limit)
|
|
{
|
|
map->limit = limit;
|
|
}
|
|
|
|
ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
|
|
{
|
|
ALsizei pos = 0;
|
|
|
|
WriteLock(&map->lock);
|
|
if(map->size > 0)
|
|
{
|
|
ALsizei count = map->size;
|
|
do {
|
|
ALsizei step = count>>1;
|
|
ALsizei i = pos+step;
|
|
if(!(map->keys[i] < key))
|
|
count = step;
|
|
else
|
|
{
|
|
pos = i+1;
|
|
count -= step+1;
|
|
}
|
|
} while(count > 0);
|
|
}
|
|
|
|
if(pos == map->size || map->keys[pos] != key)
|
|
{
|
|
if(map->size >= map->limit)
|
|
{
|
|
WriteUnlock(&map->lock);
|
|
return AL_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if(map->size == map->capacity)
|
|
{
|
|
ALuint *keys = NULL;
|
|
ALvoid **values;
|
|
ALsizei newcap, keylen;
|
|
|
|
newcap = (map->capacity ? (map->capacity<<1) : 4);
|
|
if(map->limit > 0 && newcap > map->limit)
|
|
newcap = map->limit;
|
|
if(newcap > map->capacity)
|
|
{
|
|
/* Round the memory size for keys up to a multiple of the
|
|
* pointer size.
|
|
*/
|
|
keylen = newcap * sizeof(map->keys[0]);
|
|
keylen += sizeof(map->values[0]) - 1;
|
|
keylen -= keylen%sizeof(map->values[0]);
|
|
|
|
keys = al_malloc(16, keylen + newcap*sizeof(map->values[0]));
|
|
}
|
|
if(!keys)
|
|
{
|
|
WriteUnlock(&map->lock);
|
|
return AL_OUT_OF_MEMORY;
|
|
}
|
|
values = (ALvoid**)((ALbyte*)keys + keylen);
|
|
|
|
if(map->keys)
|
|
{
|
|
memcpy(keys, map->keys, map->size*sizeof(map->keys[0]));
|
|
memcpy(values, map->values, map->size*sizeof(map->values[0]));
|
|
}
|
|
al_free(map->keys);
|
|
map->keys = keys;
|
|
map->values = values;
|
|
map->capacity = newcap;
|
|
}
|
|
|
|
if(pos < map->size)
|
|
{
|
|
memmove(&map->keys[pos+1], &map->keys[pos],
|
|
(map->size-pos)*sizeof(map->keys[0]));
|
|
memmove(&map->values[pos+1], &map->values[pos],
|
|
(map->size-pos)*sizeof(map->values[0]));
|
|
}
|
|
map->size++;
|
|
}
|
|
map->keys[pos] = key;
|
|
map->values[pos] = value;
|
|
WriteUnlock(&map->lock);
|
|
|
|
return AL_NO_ERROR;
|
|
}
|
|
|
|
ALenum InsertUIntMapEntryNoLock(UIntMap *map, ALuint key, ALvoid *value)
|
|
{
|
|
ALsizei pos = 0;
|
|
|
|
if(map->size > 0)
|
|
{
|
|
ALsizei count = map->size;
|
|
do {
|
|
ALsizei step = count>>1;
|
|
ALsizei i = pos+step;
|
|
if(!(map->keys[i] < key))
|
|
count = step;
|
|
else
|
|
{
|
|
pos = i+1;
|
|
count -= step+1;
|
|
}
|
|
} while(count > 0);
|
|
}
|
|
|
|
if(pos == map->size || map->keys[pos] != key)
|
|
{
|
|
if(map->size >= map->limit)
|
|
return AL_OUT_OF_MEMORY;
|
|
|
|
if(map->size == map->capacity)
|
|
{
|
|
ALuint *keys = NULL;
|
|
ALvoid **values;
|
|
ALsizei newcap, keylen;
|
|
|
|
newcap = (map->capacity ? (map->capacity<<1) : 4);
|
|
if(map->limit > 0 && newcap > map->limit)
|
|
newcap = map->limit;
|
|
if(newcap > map->capacity)
|
|
{
|
|
/* Round the memory size for keys up to a multiple of the
|
|
* pointer size.
|
|
*/
|
|
keylen = newcap * sizeof(map->keys[0]);
|
|
keylen += sizeof(map->values[0]) - 1;
|
|
keylen -= keylen%sizeof(map->values[0]);
|
|
|
|
keys = al_malloc(16, keylen + newcap*sizeof(map->values[0]));
|
|
}
|
|
if(!keys)
|
|
return AL_OUT_OF_MEMORY;
|
|
values = (ALvoid**)((ALbyte*)keys + keylen);
|
|
|
|
if(map->keys)
|
|
{
|
|
memcpy(keys, map->keys, map->size*sizeof(map->keys[0]));
|
|
memcpy(values, map->values, map->size*sizeof(map->values[0]));
|
|
}
|
|
al_free(map->keys);
|
|
map->keys = keys;
|
|
map->values = values;
|
|
map->capacity = newcap;
|
|
}
|
|
|
|
if(pos < map->size)
|
|
{
|
|
memmove(&map->keys[pos+1], &map->keys[pos],
|
|
(map->size-pos)*sizeof(map->keys[0]));
|
|
memmove(&map->values[pos+1], &map->values[pos],
|
|
(map->size-pos)*sizeof(map->values[0]));
|
|
}
|
|
map->size++;
|
|
}
|
|
map->keys[pos] = key;
|
|
map->values[pos] = value;
|
|
|
|
return AL_NO_ERROR;
|
|
}
|
|
|
|
ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
|
|
{
|
|
ALvoid *ptr = NULL;
|
|
WriteLock(&map->lock);
|
|
if(map->size > 0)
|
|
{
|
|
ALsizei pos = 0;
|
|
ALsizei count = map->size;
|
|
do {
|
|
ALsizei step = count>>1;
|
|
ALsizei i = pos+step;
|
|
if(!(map->keys[i] < key))
|
|
count = step;
|
|
else
|
|
{
|
|
pos = i+1;
|
|
count -= step+1;
|
|
}
|
|
} while(count > 0);
|
|
if(pos < map->size && map->keys[pos] == key)
|
|
{
|
|
ptr = map->values[pos];
|
|
if(pos < map->size-1)
|
|
{
|
|
memmove(&map->keys[pos], &map->keys[pos+1],
|
|
(map->size-1-pos)*sizeof(map->keys[0]));
|
|
memmove(&map->values[pos], &map->values[pos+1],
|
|
(map->size-1-pos)*sizeof(map->values[0]));
|
|
}
|
|
map->size--;
|
|
}
|
|
}
|
|
WriteUnlock(&map->lock);
|
|
return ptr;
|
|
}
|
|
|
|
ALvoid *RemoveUIntMapKeyNoLock(UIntMap *map, ALuint key)
|
|
{
|
|
ALvoid *ptr = NULL;
|
|
if(map->size > 0)
|
|
{
|
|
ALsizei pos = 0;
|
|
ALsizei count = map->size;
|
|
do {
|
|
ALsizei step = count>>1;
|
|
ALsizei i = pos+step;
|
|
if(!(map->keys[i] < key))
|
|
count = step;
|
|
else
|
|
{
|
|
pos = i+1;
|
|
count -= step+1;
|
|
}
|
|
} while(count > 0);
|
|
if(pos < map->size && map->keys[pos] == key)
|
|
{
|
|
ptr = map->values[pos];
|
|
if(pos < map->size-1)
|
|
{
|
|
memmove(&map->keys[pos], &map->keys[pos+1],
|
|
(map->size-1-pos)*sizeof(map->keys[0]));
|
|
memmove(&map->values[pos], &map->values[pos+1],
|
|
(map->size-1-pos)*sizeof(map->values[0]));
|
|
}
|
|
map->size--;
|
|
}
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
|
|
{
|
|
ALvoid *ptr = NULL;
|
|
ReadLock(&map->lock);
|
|
if(map->size > 0)
|
|
{
|
|
ALsizei pos = 0;
|
|
ALsizei count = map->size;
|
|
do {
|
|
ALsizei step = count>>1;
|
|
ALsizei i = pos+step;
|
|
if(!(map->keys[i] < key))
|
|
count = step;
|
|
else
|
|
{
|
|
pos = i+1;
|
|
count -= step+1;
|
|
}
|
|
} while(count > 0);
|
|
if(pos < map->size && map->keys[pos] == key)
|
|
ptr = map->values[pos];
|
|
}
|
|
ReadUnlock(&map->lock);
|
|
return ptr;
|
|
}
|
|
|
|
ALvoid *LookupUIntMapKeyNoLock(UIntMap *map, ALuint key)
|
|
{
|
|
if(map->size > 0)
|
|
{
|
|
ALsizei pos = 0;
|
|
ALsizei count = map->size;
|
|
do {
|
|
ALsizei step = count>>1;
|
|
ALsizei i = pos+step;
|
|
if(!(map->keys[i] < key))
|
|
count = step;
|
|
else
|
|
{
|
|
pos = i+1;
|
|
count -= step+1;
|
|
}
|
|
} while(count > 0);
|
|
if(pos < map->size && map->keys[pos] == key)
|
|
return map->values[pos];
|
|
}
|
|
return NULL;
|
|
}
|