At first glance the proposed actor model seems like a great fit in the audio space, potentially also in gaming and other highly concurrent applications. There seems to be one caveat though (unless I'm missing something of course).
In certain applications, ordered messaging is not the only way actors can meaningfully and safely communicate. In audio for example, there's typically a high-priority thread that periodically asks actors (audio units) to generate, analyse or mutate sound. In many cases messages sent to the units from other threads, e.g. the UI thread, will be ignored and only the last one that the actor picks up before the next rendering cycle will take effect. In other situations it is necessary to send out-of-order messages (MIDI "panic reset" comes to mind though there may be others).
Suppose you have an EQ filter as an actor in your audio processing chain. The filter has certain parameters that can be changed from the UI: e.g. bypass
, gain
, or a whole structure eqParameters
, etc. Audio units typically protect these properties with a sync primitive like a semaphore. There is no queue here since any changes to e.g. the bypass
flag that happened between the rendering cycles don't matter to the unit; it will only pick up the last value before the start of a cycle.
What this means is, changing these parameters may look like you are sending messages to the actor whereas in fact there is no queue there, just a single slot for the latest message - not sure if there is a proper term for this in multithreading (mailbox?).
Similar scenarios I believe are possible in gaming, though I'm not experienced in this specific area.
So, I'm either not seeing how the proposed actor model can cover this use case, or the model in fact doesn't. Sending parameter changes via a serialized queue to this type of actors would be an overkill. On the other hand, the actor isolation rules will probably prevent the developers from implementing the "mailbox" properties manually.
Other than that, audio units are certainly actors. In some implementations the entire processing chain in your application may be wrapped in a single actor for efficiency, but it doesn't change the fact that the actor may need to bypass the serial queue, again, for efficiency reasons.
What am I missing?
(In any case I'm very much looking forward to the implementation of these proposals. Seems like a lot of things will be rewritten to look nicer and cleaner, which means the boundaries of maintainability of Swift projects will moved further to cover more complex applications. This is really exciting!)