diff options
-rw-r--r-- | OpenAL32/alSource.c | 20 |
1 files changed, 16 insertions, 4 deletions
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); |