MessageManager::runDispatchLoopUntil() + 1ms timeout


#1

Hi,

MessageManager::runDispatchLoopUntil() does not work reliably when given a timeout value of 1ms.
https://github.com/julianstorer/JUCE/blob/master/modules/juce_events/messages/juce_MessageManager.cpp#L108

a) Passing -1 runs the loop forever.
b) Passing 0 never enters the loop.
c) Passing 1 may or may not enter the loop.
d) Passing 2 or higher always enters the loop.

The reason for c) is that Time::currentTimeMillis() is called twice, once to initialize endTime and a second time in the condition. The system’s milliseconds counter may well flip between the two calls, and the loop will not be entered if it does. To fix this problem, I suggest to introduce a currentTime variable, allowing initialization and condition to use the same time value:

bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
{
    jassert (isThisTheMessageThread()); // must only be called by the message thread

    int64 currentTime = Time::currentTimeMillis();
    const int64 endTime = currentTime + millisecondsToRunFor;

    while ((millisecondsToRunFor < 0 || endTime > currentTime) && ! quitMessageReceived)
    {
        JUCE_TRY
        {
            if (! dispatchNextMessageOnSystemQueue (millisecondsToRunFor >= 0))
            {
                const int msToWait = (int) (endTime - Time::currentTimeMillis());

                if (msToWait > 0)
                    Thread::sleep (jmin (5, msToWait));
            }
        }
        JUCE_CATCH_EXCEPTION

        currentTime = Time::currentTimeMillis();
    }

    return ! quitMessageReceived;
}

Cheers!


#2

Good catch! Thanks, I’ll sort that out!