aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2011-08-29 23:55:24 -0700
committerChris Robinson <[email protected]>2011-08-29 23:55:24 -0700
commitf02d9e22d755e69baab00f1d7ddceced6bac8136 (patch)
tree5c424026e216af09cddeb07f96472a2ed299ff02 /OpenAL32
parentcc67f4589256efceb17c58673159b3e687ec0436 (diff)
Do a pointer exchange when replacing the source buffer queue
Diffstat (limited to 'OpenAL32')
-rw-r--r--OpenAL32/Include/alMain.h16
-rw-r--r--OpenAL32/alSource.c33
2 files changed, 33 insertions, 16 deletions
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 454bb715..57eee33d 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -235,6 +235,10 @@ static __inline int ExchangeInt(volatile int *ptr, int newval)
{
return __sync_lock_test_and_set(ptr, newval);
}
+static __inline void *ExchangePtr(void *volatile*ptr, void *newval)
+{
+ return __sync_lock_test_and_set(ptr, newval);
+}
static __inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval)
{
return __sync_bool_compare_and_swap(ptr, oldval, newval);
@@ -258,6 +262,10 @@ static __inline int ExchangeInt(volatile int *ptr, int newval)
} u = { ptr };
return InterlockedExchange(u.l, newval);
}
+static __inline void *ExchangePtr(void *volatile*ptr, void *newval)
+{
+ return InterlockedExchangePtr(ptr, newval);
+}
static __inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval)
{
union {
@@ -286,6 +294,14 @@ static __inline int ExchangeInt(volatile int *ptr, int newval)
} while(!OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr));
return oldval;
}
+static __inline void *ExchangePtr(void *volatile*ptr, void *newval)
+{
+ void *oldval;
+ do {
+ oldval = *ptr;
+ } while(!OSAtomicCompareAndSwapPtrBarrier(oldval, newval, ptr));
+ return oldval;
+}
static __inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval)
{
return OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr);
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index 3e8d2b6a..9d4f048c 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -559,22 +559,14 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
case AL_BUFFER:
if(Source->state == AL_STOPPED || Source->state == AL_INITIAL)
{
+ ALbufferlistitem *oldlist;
ALbuffer *buffer = NULL;
if(lValue == 0 ||
(buffer=LookupBuffer(device->BufferMap, lValue)) != NULL)
{
- // Remove all elements in the queue
- while(Source->queue != NULL)
- {
- BufferListItem = Source->queue;
- Source->queue = BufferListItem->next;
-
- if(BufferListItem->buffer)
- DecrementRef(&BufferListItem->buffer->ref);
- free(BufferListItem);
- }
Source->BuffersInQueue = 0;
+ Source->BuffersPlayed = 0;
// Add the buffer to the queue (as long as it is NOT the NULL buffer)
if(buffer != NULL)
@@ -587,8 +579,10 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
BufferListItem->buffer = buffer;
BufferListItem->next = NULL;
BufferListItem->prev = NULL;
+ // Increment reference counter for buffer
+ IncrementRef(&buffer->ref);
- Source->queue = BufferListItem;
+ oldlist = ExchangePtr((void**)&Source->queue, BufferListItem);
Source->BuffersInQueue = 1;
Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
@@ -597,18 +591,25 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
Source->Update = CalcSourceParams;
else
Source->Update = CalcNonAttnSourceParams;
-
- // Increment reference counter for buffer
- IncrementRef(&buffer->ref);
+ Source->NeedsUpdate = AL_TRUE;
}
else
{
// Source is now in UNDETERMINED mode
Source->lSourceType = AL_UNDETERMINED;
+ oldlist = ExchangePtr((void**)&Source->queue, NULL);
}
- Source->BuffersPlayed = 0;
- Source->NeedsUpdate = AL_TRUE;
+ // Delete all previous elements in the queue
+ while(oldlist != NULL)
+ {
+ BufferListItem = oldlist;
+ oldlist = BufferListItem->next;
+
+ if(BufferListItem->buffer)
+ DecrementRef(&BufferListItem->buffer->ref);
+ free(BufferListItem);
+ }
}
else
alSetError(pContext, AL_INVALID_VALUE);