Evilness of MessageManager::getInstance()->runDispatchLoopUntil();

Hi everybody,

as the title already suggests, I know that you shouldn’t lock the GUI thread.

This being said, on a scale from 1 to #define true 0, how evil is calling runDispatchLoopUntil() given the fact that it’s the last resort (with values below 20 ms) ? The code will never run on Android, so modal loops are not per se impossible, but it will definitely run in plugins and iOS and I know Jules stated in another thread that it’s particularly troublesome in a plugin scenario.

What might go wrong there? I don’t care about unresponsiveness in this case (it’s just an edge case situation where the execution of a script needs to pause until all voices are killed (usually within 30-40ms) so that the audio thread can be suspended during the construction of a larger object).

Using a state-machine solution in this scenario would mean winding up the stacktrace of the script execution and resume at exact this point, which is possible, but definitely not on my list of “fun things to code”.

following, because that made me laugh out loud hahaha

2 Likes

The reason it’s bad is because you have an unknown pile of in-progress code below you on the call stack when you invoke the run-loop.

And when the run-loop function returns, literally ANYTHING could have happened. All your windows might be gone, all your objects could have changed. The host app may have quit. Memory could be freed.

But no matter what has happened, your caller function still has to return, and the stack that was originally there has to unwind, and any caller functions will carry on from where they left off.

It’s an insidious problem because usually you’ll get away with it, and it’ll just cause occasional, hard-to-reproduce bugs.

In plugins the most common bug is when the host unloads your plugin and frees its DLL during the run-loop. So the run-loop returns and your stack is getting unwound, the whole stack memory itself, and any functions that are due to be called during unwinding is all gone.

1 Like

Ah, makes sense. In this case, I’ll try busy waiting, although that seems even more stupid:

// Waiting like it's 1966...
// (https://en.wikipedia.org/wiki/Thread_(computing)#History)
while(voicesAreKilled() && timeOut < 0.1)
{
    timeOut = Time::getCurrentMilliseconds() - waitStart;
}

If this is some kind of script then I’d have thought that you should have it running on a thread, where it’s fine to block and wait for things like this to finish?

Hmm, I knew you won’t let me get away this lazy… :slight_smile:

2 Likes