diff options
author | Chris Robinson <[email protected]> | 2018-01-31 20:21:54 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2018-01-31 20:21:54 -0800 |
commit | 7256bc92fa954b6ff313f30694a27b7f47c1589d (patch) | |
tree | 7faf7ad76b9e8766c89936d850e1a3df915b6880 /Alc/ALc.c | |
parent | 0394d5a44fd5b1c90c7e4ae9d660bec8a19175f1 (diff) |
Add a thread to marshal events from the mixer
To avoid having unknown user code running in the mixer thread that could
significantly delay the mixed output, a lockless ringbuffer is used for the
mixer to provide events that a secondary thread will pop off and process.
Diffstat (limited to 'Alc/ALc.c')
-rw-r--r-- | Alc/ALc.c | 20 |
1 files changed, 19 insertions, 1 deletions
@@ -41,6 +41,7 @@ #include "bformatdec.h" #include "alu.h" #include "alconfig.h" +#include "ringbuffer.h" #include "fpu_modes.h" #include "cpu_caps.h" @@ -2611,8 +2612,11 @@ static ALvoid InitContext(ALCcontext *Context) Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT; ATOMIC_FLAG_TEST_AND_SET(&Context->PropsClean, almemory_order_relaxed); ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE); - almtx_init(&Context->EventCbLock, almtx_plain); + almtx_init(&Context->EventThrdLock, almtx_plain); + alcnd_init(&Context->EventCnd); + Context->AsyncEvents = NULL; ATOMIC_INIT(&Context->EnabledEvts, 0); + almtx_init(&Context->EventCbLock, almtx_plain); Context->EventCb = NULL; Context->EventParam = NULL; @@ -2743,7 +2747,21 @@ static void FreeContext(ALCcontext *context) } TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s"); + if(ATOMIC_EXCHANGE(&context->EnabledEvts, 0, almemory_order_acq_rel)) + { + static const AsyncEvent kill_evt = { 0 }; + while(ll_ringbuffer_write_space(context->AsyncEvents) == 0) + althrd_yield(); + ll_ringbuffer_write(context->AsyncEvents, (const char*)&kill_evt, 1); + althrd_join(context->EventThread, NULL); + } + almtx_destroy(&context->EventCbLock); + almtx_destroy(&context->EventThrdLock); + alcnd_destroy(&context->EventCnd); + + ll_ringbuffer_free(context->AsyncEvents); + context->AsyncEvents = NULL; ALCdevice_DecRef(context->Device); context->Device = NULL; |