On Sun, Feb 17, 2013 at 10:35 AM, Harry van Haaren
<harryhaaren(a)gmail.com> wrote:
On Sun, Feb 17, 2013 at 3:57 AM, M Donalies
<ingeniousnebbish(a)cox.net>
wrote:
No locks or mutexes in a callback function. I need to think about that
one.
This is indeed a "lovely" topic for debate. I'm bound to say that, I'm
currently doing a final-year project for college on the topic.
I've came up with a solution, which I feel is the best balance between C++-y
style Event classes, and C-style simple code. Simple is great for
RT situations: its easy to see if something is RT or not.
In essence it boils down to this:
-Create an "EventBase" class with pure virtual type() and size()
functions
-Derive actual events like "EventPlay" overriding type() and size()
-Create a ringbuffer checkout the example, it uses the
JACK ringbuffer
-Create events *on the stack* ie EventPlay eventPlay();
-Write events into the ringbuffer using jack_ringbuffer_write();
The last two steps are key, as they enfore the event gets *copied* into the
ringbuffer, and the original goes out
of scope (and gets destroyed).
This solution is very workable, on the condition that only fundamental C
datatypes are passed trough the Event class.
Things will get nasty if you pass std::shared_ptr<> objects trough it, I've
made that mistake already :)
The following code shows communication from the GUI thread to the RT thread.
Create another ringbuffer and functions
for communicating in the other direction.
https://github.com/harryhaaren/realtimeAudioThreading
HTH, -Harry
This scheme sounds error prone. In general, copying C++ objects via
memcpy (or writing them 1 byte at a time into the ringbuffer, which is
what I think you're proposing) is a bad idea. JACK ringbuffers are
ideally suited to passing simple types (like floats), and not vairable
sized things (like different derived Event classes). Your enum for
event types is a bit of a red flag, too. While its perfectly valid,
"type flags" like this more often than not accompany inflexible,
tightly coupled code (which may be fine in a small audio app, but few
apps stay small).
What about passing pointers via the ringbuffer? To free the event
objects, you could pass them back via a second ringbuffer so the RT
threads aren't responsible for deleting them.