Do a pointer exchange when replacing the source buffer queue

This commit is contained in:
Chris Robinson
2011-08-29 23:55:24 -07:00
parent cc67f45892
commit f02d9e22d7
2 changed files with 33 additions and 16 deletions
+16
View File
@@ -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);
+17 -16
View File
@@ -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);