Thread class lambda constructor?

More than once I have gone looking for the Thread constructor to do something like this:
(having forgotten each time that this does not exist)

void foo()
{
  Thread t([]() { wait(-1); cout << "hello" << endl; });
  t.notify();
  t.waitForThreadExit(10);
}

Is there a reason why Thread cannot take a lambda in the constructor and just make that the “run” method?

Maybe you should be using ThreadPool instead of Thread. The associated ThreadPoolJob class does have a lambda constructor, and using a ThreadPool will be a lot more efficient than starting up a new thread each time.

But if you really want a juce::Thread with a lambda constructor, it should be easy enough to make your own:

#include <functional>

class QuickThread : public juce::Thread
{
public:
    QuickThread(const std::function<void()>& f) :
        juce::Thread("lamda_thread"), func(f)
    {
        startThread();
    }

    void run() override
    {
        std::invoke(func);
    }

private:
    std::function<void()> func;
};

I haven’t tested this, and you’d have to think a bit harder about how the thread exists (see the juce::Thread docs). But something like this should be possible.

1 Like

Thanks. I really just need a single thread, and it will do work for a more substantial amount of time. So Thread class fits the bill. I guess I’m just saying that a lambda constructor would make it easier to create that thread as opposed to deriving a class just so I can put the execution in the run() method. Seems like an obvious constructor for Thread to have…but maybe it is more difficult than it looks for Juce to implement it.

Your wrapper is nice. I might use that as a workaround - thanks.

This code will not work even if there was a lambda constructor, since wait is a member function if juce::Thread. To make that possible, the lambda would need some reference to the thread instance as additional argument.

Maybe std::thread is an option for you?

juce::WaitableEvent e;
std::thread t ([&] { e.wait(); std::cout << "hello"; });
e.signal();
t.join();

Also you may consider to launch an “anonymous” background thread via the static function Thread::launch()

This solution comes with a caveat, stated in the docs, because the function returns void and you have no handle on the generated Thread object:

note that using an anonymous thread makes it very difficult to interrupt the function when you need to stop it, e.g. when your app quits. So it’s up to you to deal with situations where the function may fail to stop in time.

Good point…if the lambda constructor was officially supported by Juce, it seems it could drop in for the run() method and could have references to the Thread methods, maybe it would require capturing “this”. The fact that std::thread has something like this is what drove me to suggest it for juce::Thread. Regarding the other response…Thread::launch is where I end up and of course it has the major limitation where you can’t stop the thread. So, in summary, it seems like my original observation remains that Juce should consider this addition - as I have hit the limitation more than once and Thread is a fundamental building block.

1 Like

I would strongly recommend using the ThreadPool class for firing one-shot functions like this.

3 Likes