diff options
author | Chris Robinson <[email protected]> | 2011-08-29 19:15:22 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2011-08-29 19:15:22 -0700 |
commit | b283dd3682e5c56483e69c4b65e889563e95d8c0 (patch) | |
tree | da8c0a315549ef88f6506df8be0c091d64231dce | |
parent | 4a5dd73a3cd38c20b4b2ca45026167eb5ce0bc95 (diff) |
Use a read-write lock to protect access to the UInt maps
-rw-r--r-- | Alc/helpers.c | 72 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 50 |
2 files changed, 97 insertions, 25 deletions
diff --git a/Alc/helpers.c b/Alc/helpers.c index 85433368..265c8210 100644 --- a/Alc/helpers.c +++ b/Alc/helpers.c @@ -266,25 +266,75 @@ void SetRTPriority(void) } +static void Lock(volatile ALenum *l) +{ + while(Exchange_ALenum(l, AL_TRUE) == AL_TRUE) + Sleep(0); +} + +static void Unlock(volatile ALenum *l) +{ + Exchange_ALenum(l, AL_FALSE); +} + +void ReadLock(RWLock *lock) +{ + Lock(&lock->read_entry_lock); + Lock(&lock->read_lock); + if(IncrementRef(&lock->read_count) == 1) + Lock(&lock->write_lock); + Unlock(&lock->read_lock); + Unlock(&lock->read_entry_lock); +} + +void ReadUnlock(RWLock *lock) +{ + if(DecrementRef(&lock->read_count) == 0) + Unlock(&lock->write_lock); +} + +void WriteLock(RWLock *lock) +{ + if(IncrementRef(&lock->write_count) == 1) + Lock(&lock->read_lock); + Lock(&lock->write_lock); +} + +void WriteUnlock(RWLock *lock) +{ + Unlock(&lock->write_lock); + if(DecrementRef(&lock->write_count) == 0) + Unlock(&lock->read_lock); +} + + void InitUIntMap(UIntMap *map) { map->array = NULL; map->size = 0; map->maxsize = 0; + map->lock.read_count = 0; + map->lock.write_count = 0; + map->lock.read_lock = AL_FALSE; + map->lock.read_entry_lock = AL_FALSE; + map->lock.write_lock = AL_FALSE; } void ResetUIntMap(UIntMap *map) { + WriteLock(&map->lock); free(map->array); map->array = NULL; map->size = 0; map->maxsize = 0; + WriteUnlock(&map->lock); } ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value) { ALsizei pos = 0; + WriteLock(&map->lock); if(map->size > 0) { ALsizei low = 0; @@ -306,15 +356,17 @@ ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value) { if(map->size == map->maxsize) { - ALvoid *temp; + ALvoid *temp = NULL; ALsizei newsize; newsize = (map->maxsize ? (map->maxsize<<1) : 4); - if(newsize < map->maxsize) + if(newsize >= map->maxsize) + temp = realloc(map->array, newsize*sizeof(map->array[0])); + if(!temp) + { + WriteUnlock(&map->lock); return AL_OUT_OF_MEMORY; - - temp = realloc(map->array, newsize*sizeof(map->array[0])); - if(!temp) return AL_OUT_OF_MEMORY; + } map->array = temp; map->maxsize = newsize; } @@ -326,12 +378,14 @@ ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value) } map->array[pos].key = key; map->array[pos].value = value; + WriteUnlock(&map->lock); return AL_NO_ERROR; } void RemoveUIntMapKey(UIntMap *map, ALuint key) { + WriteLock(&map->lock); if(map->size > 0) { ALsizei low = 0; @@ -352,10 +406,13 @@ void RemoveUIntMapKey(UIntMap *map, ALuint key) map->size--; } } + WriteUnlock(&map->lock); } ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key) { + ALvoid *ptr = NULL; + ReadLock(&map->lock); if(map->size > 0) { ALsizei low = 0; @@ -369,7 +426,8 @@ ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key) high = mid; } if(map->array[low].key == key) - return map->array[low].value; + ptr = map->array[low].value; } - return NULL; + ReadUnlock(&map->lock); + return ptr; } diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index a9f5813d..fd645218 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -161,22 +161,6 @@ typedef ptrdiff_t ALsizeiptrEXT; #endif -typedef struct UIntMap { - struct { - ALuint key; - ALvoid *value; - } *array; - ALsizei size; - ALsizei maxsize; -} UIntMap; - -void InitUIntMap(UIntMap *map); -void ResetUIntMap(UIntMap *map); -ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value); -void RemoveUIntMapKey(UIntMap *map, ALuint key); -ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key); - - #ifdef _WIN32 #ifndef _WIN32_WINNT @@ -184,8 +168,6 @@ ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key); #endif #include <windows.h> -extern UIntMap TlsDestructor; - typedef DWORD pthread_key_t; int pthread_key_create(pthread_key_t *key, void (*callback)(void*)); int pthread_key_delete(pthread_key_t key); @@ -309,6 +291,38 @@ DECL_TEMPLATE(ALenum) #undef DECL_TEMPLATE +typedef struct { + volatile RefCount read_count; + volatile RefCount write_count; + volatile ALenum read_lock; + volatile ALenum read_entry_lock; + volatile ALenum write_lock; +} RWLock; + +void ReadLock(RWLock *lock); +void ReadUnlock(RWLock *lock); +void WriteLock(RWLock *lock); +void WriteUnlock(RWLock *lock); + + +typedef struct UIntMap { + struct { + ALuint key; + ALvoid *value; + } *array; + ALsizei size; + ALsizei maxsize; + RWLock lock; +} UIntMap; +extern UIntMap TlsDestructor; + +void InitUIntMap(UIntMap *map); +void ResetUIntMap(UIntMap *map); +ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value); +void RemoveUIntMapKey(UIntMap *map, ALuint key); +ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key); + + #include "alListener.h" #include "alu.h" |