Synchronous call to lambda on the main thread from another

I want to replicate the behavior of MessageManager::callFunctionOnMessageThread() (i.e. block until invocation has been performed), but passing a simple lambda to be called.

MessageManager::callAsync() looked promising but it does not wait for the function to be invoked on the main thread, therefore that’s not what I am looking for (although the doc could specify clearly whether it waits or not: I had to look at the code to be certain).

Anyway, after searching around for a while I didn’t seem to find what I was looking for so I implemented it myself below.

Have I reinvented some wheel or was this actually missing from JUCE?

void callOnMessageThread (std::function <void ()> f)
    struct Helper
        std::function <void ()> func;

        Helper (std::function <void ()> f) : func (f) { }

        static void* invokeFunc (void* data)    // respects the MessageCallbackFunction prototype
            Helper* const helper = static_cast <Helper*> (data);
            helper->func ();
            return nullptr;

    Helper helper (f);
    MessageManager::getInstance()->callFunctionOnMessageThread (Helper::invokeFunc, &helper);

It’s missing because I’d really rather not encourage people to do that - it’s a recipe for deadlock! See the notes for callFunctionOnMessageThread.

TBH we should probably deprecate callFunctionOnMessageThread because I think it’s fundamentally impossible to use it without some risk of locking up…

IMHO it will be much easier for developers to shoot themselves in the foot with a deadlock if they try to implement these by themselves, which they will try doing anyway if this functionality goes missing

1 Like