[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[fluid-dev] Thread safety
[fluid-dev] Thread safety
Sun, 17 May 2009 10:20:18 +0200
Thunderbird 184.108.40.206 (X11/20090409)
I've been looking at the threading strategy in Fluidsynth, which seems
to need some review. While thinking about this, my first priority have
been to avoid concurrency issues, at all costs (an underrun is bad, but
a segfault is 100 times worse), and my second priority has been to avoid
unnecessary thread synchronization costs when it is not needed.
Given that priority list, we should make the fluid_synth_t class
single-threaded and avoid mutexes altogether. One reason for this is
that one of Fluidsynth's most important usages are as a virtual
instrument in MusE/Rosegarden/etc, and there I assume it is used
single-threaded anyway. And given the current behavior (some amount of
synchronization but not fully functional), I think we could say that
getting rid of the synchronization would be backwards compatible.
This means some additional work for the audio thread, i e it has to
process midi events. I think this is unavoidable for the moment. Btw, if
we want to speed up audio processing, I think parallellizing voices (i e
two CPU cores could render two different voices simultaneously) could be
a fun thing to investigate. But that is in the distant future (at least
not scheduled for 1.1.0).
Back to the threading. Leaving fluid_synth_t single-threaded means that
other threads cannot call fluid_synth_noteon and friends. For the midi
player, this is already implemented with the sample timers. For the midi
drivers, I'm working on a patch that will use the sequencer as a buffer
for this case.
So the thread synchronization is limited to the sequencer. Here's the
suggested rules for using the sequencer in a thread-safe way:
- Only one thread at a time can call fluid_sequencer_process. This would
normally be the audio thread, via the sample timer callback.
- Any thread can call fluid_sequencer_send_at. The shortcut from
fluid_sequencer_send_at to fluid_sequencer_send_now is removed. This is
a subtle change of behavior but it is more consistent with the
documentation (i e "MAKES A COPY").
- fluid_sequencer_get_tick can be called from any thread (and should be
implemented with glib atomic integers).
- fluid_sequencer_send_now and fluid_sequencer_process are the only
public API calls that can result in midi events being sent. Midi events
are sent before the call returns and in the context of the calling thread.
- Don't mess around with registering clients, or anything else, while
another thread makes a call to the sequencer.
A question would be whether this means we should leave up to the
libfluidsynth user to insert a sequencer in the midi processing chain,
or if we should create it automatically behind the scenes somehow (and
if so, what component should create it?). What do you think?