I'm learning about threading support in C++. I've got a basic understanding of thread-pools and why creating and destroying threads on some systems can be expensive. As far as I'm aware C++11 doesn't have any built in support for worker/background threads. std::thread is only designed to perform one task which you set in the constructor; it then destroys the thread after the task is complete.
At the moment I have no use for a fully fledged thread-pool but I would like to be able to reuse a thread for different tasks after I create it. I've created a simple class that will accept any function or method wrapped in a lambda and will then execute it exactly once. The reusable thread object should not destruct until the work function is fully complete.
This is the implementation:
class Reusable_Thread
{
public:
Reusable_Thread()
: m_thread_pause(true), m_thread_quit(false),
m_thread(&Reusable_Thread::thread_worker, this)
{ }
~Reusable_Thread()
{
m_thread_quit = true;
m_thread.join();
}
bool get_readiness() const { return m_thread_pause; }
bool set_work(const std::function<void()>& work_func)
{
if (get_readiness())
{
m_work_func = work_func;
return true;
}
else
{
return false;
}
}
private:
std::atomic<bool> m_thread_pause;
std::atomic<bool> m_thread_quit;
std::thread m_thread;
std::function<void()> m_work_func;
void thread_worker()
{
while (!m_thread_quit)
{
if (!m_thread_pause)
{
m_work_func();
m_thread_pause = true;
}
}
}
};
And this is some example usage:
int main()
{
Reusable_Thread thread;
auto f1 = [&] () { /* do some work */ };
thread.set_work(f1);
while (thread.get_readiness() == false)
{
// do some other stuff
}
// set some new work
auto f2 = [&] () { /* do some new work */ };
thread.set_work(f2);
// maybe call f1 again, depends if f2 has finished yet
if (!thread.set_work(f1))
{
// thread too busy to call f1, call it on the main thread
f1();
}
// thread won't destruct until work has finished
return 0;
}
Are there any problems with implementing a reusable thread this way?