aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2011-08-29 19:15:22 -0700
committerChris Robinson <[email protected]>2011-08-29 19:15:22 -0700
commitb283dd3682e5c56483e69c4b65e889563e95d8c0 (patch)
treeda8c0a315549ef88f6506df8be0c091d64231dce
parent4a5dd73a3cd38c20b4b2ca45026167eb5ce0bc95 (diff)
Use a read-write lock to protect access to the UInt maps
-rw-r--r--Alc/helpers.c72
-rw-r--r--OpenAL32/Include/alMain.h50
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"