aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32/alSource.c
diff options
context:
space:
mode:
Diffstat (limited to 'OpenAL32/alSource.c')
-rw-r--r--OpenAL32/alSource.c20
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);