From b89cc3417b5c0396082b5fe0d5175bf625f0d3c4 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 11 May 2014 03:52:22 -0700 Subject: Avoid locking the mixer when unqueueing buffers --- OpenAL32/alSource.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'OpenAL32') diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index d707f226..f0fb374f 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -33,6 +33,8 @@ #include "alThunk.h" #include "alAuxEffectSlot.h" +#include "threads.h" + enum Resampler DefaultResampler = LinearResampler; const ALsizei ResamplerPadding[ResamplerMax] = { @@ -2223,10 +2225,20 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint OldHead = ExchangePtr((XchgPtr*)&source->queue, BufferList); if(BufferList) { - LockContext(context); - BufferList->prev->next = NULL; - BufferList->prev = NULL; - UnlockContext(context); + ALCdevice *device = context->Device; + RefCount count; + + /* Cut the new head's link back to the old body. The mixer is robust + * enough to handle the link back going away. Once the active mix (if + * any) is complete, it's safe to finish cutting the old tail from the + * new head. */ + BufferList = ExchangePtr((XchgPtr*)&BufferList->prev, NULL); + if(((count=device->MixCount)&1) != 0) + { + while(count == device->MixCount) + althrd_yield(); + } + BufferList->next = NULL; } WriteUnlock(&source->queue_lock); -- cgit v1.2.3