zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 0a5445867e602672beb45a2d1517abed414fbe25
parent 8484e6e4fdd6f1816506d17a7fad2f8fd5d927af
Author: Johannes Lorenz <j.git@lorenz-ho.me>
Date:   Sun, 28 Jul 2019 21:48:36 +0200

Master::runOsc(): Fix possible race condition

Fix a race condition when MiddleWare has taken over a dead Master, and
Master just came alive again. In such a case, only one thread does stuff
in Master::runOsc(), the other skips it.

Diffstat:
Msrc/Misc/Master.cpp | 51+++++++++++++++++++++++++++++++++------------------
Msrc/Misc/Master.h | 3+++
2 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp @@ -1123,28 +1123,43 @@ int msg_id=0; bool Master::runOSC(float *outl, float *outr, bool offline) { - //Handle user events - char loc_buf[1024]; - DataObj d{loc_buf, 1024, this, bToU}; - memset(loc_buf, 0, sizeof(loc_buf)); - - int events = 0; - for(; uToB && uToB->hasNext() && events < 100; ++msg_id, ++events) + // the following block is only ever entered by 1 thread at a time + // other threads have to ignore it + if(!run_osc_in_use.exchange(true)) // exchange returns value before call { - const char *msg = uToB->read(); - if(! applyOscEvent(msg, outl, outr, offline, true, d, msg_id) ) - return false; - } + /* + * WARNING: Do not return without "run_osc_in_use.store(false)" + */ - if(automate.damaged) { - d.broadcast("/damage", "s", "/automate/"); - automate.damaged = 0; - } + //Handle user events + char loc_buf[1024]; + DataObj d{loc_buf, 1024, this, bToU}; + memset(loc_buf, 0, sizeof(loc_buf)); - if(events>1 && false) - fprintf(stderr, "backend: %d events per cycle\n",events); + int events = 0; + for(; uToB && uToB->hasNext() && events < 100; ++msg_id, ++events) + { + const char *msg = uToB->read(); + if(! applyOscEvent(msg, outl, outr, offline, true, d, msg_id, + ) ) + { + run_osc_in_use.store(false); + return false; + } + } - return true; + if(automate.damaged) { + d.broadcast("/damage", "s", "/automate/"); + automate.damaged = 0; + } + + if(events>1 && false) + fprintf(stderr, "backend: %d events per cycle\n",events); + + run_osc_in_use.store(false); + return true; + } + else { return true; /* = no new master */ } } /* diff --git a/src/Misc/Master.h b/src/Misc/Master.h @@ -16,6 +16,7 @@ #define MASTER_H #include "../globals.h" #include "Microtonal.h" +#include <atomic> #include <rtosc/automations.h> #include <rtosc/savefile.h> @@ -215,6 +216,8 @@ class Master uint32_t last_beat = 0; uint32_t last_ack = 0; private: + std::atomic<bool> run_osc_in_use = { false }; + float sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; float sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; int keyshift;