A note on using ci::signals
in a multi-threaded situation. To me, signals are a great solution in UI code, but in multi-threaded situations, especially in real-time sensitive situations such as audio and midi, they provide many shortcomings. For one, you need to be clear what thread you’re on in a callback especially if it isn’t the UI thread, since most graphics calls will cause undefined behavior (crash). Secondly, calling out from secondary real-time threads makes it difficult to ensure that everything will get processed fast enough to avoid glitches (in audio this would be an overrun, MIDI you would just be out of sync).
But I think there are generally two cases you’d want to cover: callbacks occurring on the main thread that are meant to affect visuals or UI. and callbacks occuring on a real-time thread that you want to use to trigger something (most commonly audio). In the former case, using ci::signals
will work just fine, as long as you emit them on the main thread (can be done with something like app::App::dispatchAsync()
or some sort of message queue). Here, you just want to schedule the callback as quick as possible and return to doing your real-time business.
The latter case is more intricate, and there usually isn’t a nice generic solution for it. @notlion can probably give some nice tips from experience here, and I can’t say I’ve ever personally needed to do this with MIDI, but I imagine that you need a mechanism more low level than signals to handle what should happen when a MIDI event fires on a real-time thread, and you want to schedule something else to occur in real-time (like start playback on an audio::GenNode
or something).
To be clear about the current ci::signals
limitations, emitting a signal from a background thread is fraught with peril. If a connection or disconnection happens from a different thread (ex. the main one) while the emit() is firing, you have trouble. This is especially difficult to avoid if you’re wisely using ci::signals::ScopedConnection
or ConnectionList
, as those will disconnect when they get destroyed and that is usually on the main thread. I’ve thought a bit about whether we could support this in the future and we probably could (either with a separate SignalMultithreaded
or some sort of deferred connection / disconnection technique), but so far the use cases haven’t justified the time invested to properly implement and test. People seem to want to do it, though.
If folks would like to explore more on how to design real-time callbacks for midi -> audio, I’d be happy to join in those discussions.
Also to note, fullbuild.sh isn’t deprecated, nor are the xcode projects shipped with cinder. For the time being, CMake is an alternative to using the xcode projects on OS X.