mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2024-11-13 08:07:23 +00:00
avoid data races in rvoice_eventhandler and cleanup
- an element from the queue might be requested from thread A - thread A is put to sleep just before he could insert his event and increment queue_stored - thread B request an element from queue, gets the same as thread A - thread B commits his changes and increases queue_stored - thread A wakes up, commits his changes - event of thread B is lost
This commit is contained in:
parent
ef9564e000
commit
680fcf1f88
1 changed files with 39 additions and 50 deletions
|
@ -65,6 +65,9 @@
|
||||||
event->realparams[1], event->realparams[2], event->realparams[3]); \
|
event->realparams[1], event->realparams[2], event->realparams[3]); \
|
||||||
return; }
|
return; }
|
||||||
|
|
||||||
|
|
||||||
|
static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* handler, const fluid_rvoice_event_t* src_event);
|
||||||
|
|
||||||
void
|
void
|
||||||
fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event)
|
fluid_rvoice_event_dispatch(fluid_rvoice_event_t* event)
|
||||||
{
|
{
|
||||||
|
@ -131,25 +134,14 @@ fluid_rvoice_eventhandler_push(fluid_rvoice_eventhandler_t* handler,
|
||||||
void* method, void* object, int intparam,
|
void* method, void* object, int intparam,
|
||||||
fluid_real_t realparam)
|
fluid_real_t realparam)
|
||||||
{
|
{
|
||||||
fluid_rvoice_event_t* event;
|
|
||||||
fluid_rvoice_event_t local_event;
|
fluid_rvoice_event_t local_event;
|
||||||
event = handler->is_threadsafe ?
|
|
||||||
fluid_ringbuffer_get_inptr(handler->queue, handler->queue_stored) : &local_event;
|
local_event.method = method;
|
||||||
|
local_event.object = object;
|
||||||
if (event == NULL) {
|
local_event.intparam = intparam;
|
||||||
FLUID_LOG(FLUID_WARN, "Ringbuffer full, try increasing polyphony!");
|
local_event.realparams[0] = realparam;
|
||||||
return FLUID_FAILED; // Buffer full...
|
|
||||||
}
|
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
|
||||||
|
|
||||||
event->method = method;
|
|
||||||
event->object = object;
|
|
||||||
event->intparam = intparam;
|
|
||||||
event->realparams[0] = realparam;
|
|
||||||
if (handler->is_threadsafe)
|
|
||||||
handler->queue_stored++;
|
|
||||||
else
|
|
||||||
fluid_rvoice_event_dispatch(event);
|
|
||||||
return FLUID_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -157,24 +149,13 @@ int
|
||||||
fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t* handler,
|
fluid_rvoice_eventhandler_push_ptr(fluid_rvoice_eventhandler_t* handler,
|
||||||
void* method, void* object, void* ptr)
|
void* method, void* object, void* ptr)
|
||||||
{
|
{
|
||||||
fluid_rvoice_event_t* event;
|
|
||||||
fluid_rvoice_event_t local_event;
|
fluid_rvoice_event_t local_event;
|
||||||
event = handler->is_threadsafe ?
|
|
||||||
fluid_ringbuffer_get_inptr(handler->queue, handler->queue_stored) : &local_event;
|
local_event.method = method;
|
||||||
|
local_event.object = object;
|
||||||
if (event == NULL) {
|
local_event.ptr = ptr;
|
||||||
FLUID_LOG(FLUID_WARN, "Ringbuffer full, try increasing polyphony!");
|
|
||||||
return FLUID_FAILED; // Buffer full...
|
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
|
||||||
}
|
|
||||||
|
|
||||||
event->method = method;
|
|
||||||
event->object = object;
|
|
||||||
event->ptr = ptr;
|
|
||||||
if (handler->is_threadsafe)
|
|
||||||
handler->queue_stored++;
|
|
||||||
else
|
|
||||||
fluid_rvoice_event_dispatch(event);
|
|
||||||
return FLUID_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,28 +165,36 @@ fluid_rvoice_eventhandler_push5(fluid_rvoice_eventhandler_t* handler,
|
||||||
fluid_real_t r1, fluid_real_t r2,
|
fluid_real_t r1, fluid_real_t r2,
|
||||||
fluid_real_t r3, fluid_real_t r4, fluid_real_t r5)
|
fluid_real_t r3, fluid_real_t r4, fluid_real_t r5)
|
||||||
{
|
{
|
||||||
fluid_rvoice_event_t* event;
|
|
||||||
fluid_rvoice_event_t local_event;
|
fluid_rvoice_event_t local_event;
|
||||||
event = handler->is_threadsafe ?
|
|
||||||
fluid_ringbuffer_get_inptr(handler->queue, handler->queue_stored) : &local_event;
|
local_event.method = method;
|
||||||
|
local_event.object = object;
|
||||||
|
local_event.intparam = intparam;
|
||||||
|
local_event.realparams[0] = r1;
|
||||||
|
local_event.realparams[1] = r2;
|
||||||
|
local_event.realparams[2] = r3;
|
||||||
|
local_event.realparams[3] = r4;
|
||||||
|
local_event.realparams[4] = r5;
|
||||||
|
|
||||||
|
return fluid_rvoice_eventhandler_push_LOCAL(handler, &local_event);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fluid_rvoice_eventhandler_push_LOCAL(fluid_rvoice_eventhandler_t* handler, const fluid_rvoice_event_t* src_event)
|
||||||
|
{
|
||||||
|
fluid_rvoice_event_t* event;
|
||||||
|
int old_queue_stored = fluid_atomic_int_add(&handler->queue_stored, 1);
|
||||||
|
|
||||||
|
event = fluid_ringbuffer_get_inptr(handler->queue, old_queue_stored);
|
||||||
|
|
||||||
if (event == NULL) {
|
if (event == NULL) {
|
||||||
|
fluid_atomic_int_dec_and_test(&handler->queue_stored);
|
||||||
FLUID_LOG(FLUID_WARN, "Ringbuffer full, try increasing polyphony!");
|
FLUID_LOG(FLUID_WARN, "Ringbuffer full, try increasing polyphony!");
|
||||||
return FLUID_FAILED; // Buffer full...
|
return FLUID_FAILED; // Buffer full...
|
||||||
}
|
}
|
||||||
|
|
||||||
event->method = method;
|
memcpy(event, src_event, sizeof(*event));
|
||||||
event->object = object;
|
|
||||||
event->intparam = intparam;
|
|
||||||
event->realparams[0] = r1;
|
|
||||||
event->realparams[1] = r2;
|
|
||||||
event->realparams[2] = r3;
|
|
||||||
event->realparams[3] = r4;
|
|
||||||
event->realparams[4] = r5;
|
|
||||||
if (handler->is_threadsafe)
|
|
||||||
handler->queue_stored++;
|
|
||||||
else
|
|
||||||
fluid_rvoice_event_dispatch(event);
|
|
||||||
return FLUID_OK;
|
return FLUID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue