aboutsummaryrefslogtreecommitdiffstats
path: root/common/uintmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/uintmap.c')
-rw-r--r--common/uintmap.c154
1 files changed, 96 insertions, 58 deletions
diff --git a/common/uintmap.c b/common/uintmap.c
index b7a9a29c..18d52d64 100644
--- a/common/uintmap.c
+++ b/common/uintmap.c
@@ -6,6 +6,8 @@
#include <stdlib.h>
#include <string.h>
+#include "almalloc.h"
+
extern inline void LockUIntMapRead(UIntMap *map);
extern inline void UnlockUIntMapRead(UIntMap *map);
@@ -15,9 +17,10 @@ extern inline void UnlockUIntMapWrite(UIntMap *map);
void InitUIntMap(UIntMap *map, ALsizei limit)
{
- map->array = NULL;
+ map->keys = NULL;
+ map->values = NULL;
map->size = 0;
- map->maxsize = 0;
+ map->capacity = 0;
map->limit = limit;
RWLockInit(&map->lock);
}
@@ -25,10 +28,11 @@ void InitUIntMap(UIntMap *map, ALsizei limit)
void ResetUIntMap(UIntMap *map)
{
WriteLock(&map->lock);
- free(map->array);
- map->array = NULL;
+ al_free(map->keys);
+ map->keys = NULL;
+ map->values = NULL;
map->size = 0;
- map->maxsize = 0;
+ map->capacity = 0;
WriteUnlock(&map->lock);
}
@@ -39,53 +43,77 @@ ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
WriteLock(&map->lock);
if(map->size > 0)
{
- ALsizei low = 0;
- ALsizei high = map->size - 1;
- while(low < high)
- {
- ALsizei mid = low + (high-low)/2;
- if(map->array[mid].key < key)
- low = mid + 1;
+ ALsizei count = map->size;
+ do {
+ ALsizei step = count>>1;
+ ALsizei i = pos+step;
+ if(!(map->keys[i] < key))
+ count = step;
else
- high = mid;
- }
- if(map->array[low].key < key)
- low++;
- pos = low;
+ {
+ pos = i+1;
+ count -= step+1;
+ }
+ } while(count > 0);
}
- if(pos == map->size || map->array[pos].key != key)
+ if(pos == map->size || map->keys[pos] != key)
{
- if(map->size == map->limit)
+ if(map->size >= map->limit)
{
WriteUnlock(&map->lock);
return AL_OUT_OF_MEMORY;
}
- if(map->size == map->maxsize)
+ if(map->size == map->capacity)
{
- ALvoid *temp = NULL;
- ALsizei newsize;
-
- newsize = (map->maxsize ? (map->maxsize<<1) : 4);
- if(newsize >= map->maxsize)
- temp = realloc(map->array, newsize*sizeof(map->array[0]));
- if(!temp)
+ 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;
}
- map->array = temp;
- map->maxsize = newsize;
+ 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->array[pos+1], &map->array[pos],
- (map->size-pos)*sizeof(map->array[0]));
+ {
+ 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->array[pos].key = key;
- map->array[pos].value = value;
+ map->keys[pos] = key;
+ map->values[pos] = value;
WriteUnlock(&map->lock);
return AL_NO_ERROR;
@@ -97,22 +125,29 @@ ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
WriteLock(&map->lock);
if(map->size > 0)
{
- ALsizei low = 0;
- ALsizei high = map->size - 1;
- while(low < high)
- {
- ALsizei mid = low + (high-low)/2;
- if(map->array[mid].key < key)
- low = mid + 1;
+ ALsizei pos = 0;
+ ALsizei count = map->size;
+ do {
+ ALsizei step = count>>1;
+ ALsizei i = pos+step;
+ if(!(map->keys[i] < key))
+ count = step;
else
- high = mid;
- }
- if(map->array[low].key == key)
+ {
+ pos = i+1;
+ count -= step+1;
+ }
+ } while(count > 0);
+ if(pos < map->size && map->keys[pos] == key)
{
- ptr = map->array[low].value;
- if(low < map->size-1)
- memmove(&map->array[low], &map->array[low+1],
- (map->size-1-low)*sizeof(map->array[0]));
+ 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--;
}
}
@@ -126,18 +161,21 @@ ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
ReadLock(&map->lock);
if(map->size > 0)
{
- ALsizei low = 0;
- ALsizei high = map->size - 1;
- while(low < high)
- {
- ALsizei mid = low + (high-low)/2;
- if(map->array[mid].key < key)
- low = mid + 1;
+ ALsizei pos = 0;
+ ALsizei count = map->size;
+ do {
+ ALsizei step = count>>1;
+ ALsizei i = pos+step;
+ if(!(map->keys[i] < key))
+ count = step;
else
- high = mid;
- }
- if(map->array[low].key == key)
- ptr = map->array[low].value;
+ {
+ 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;