A condition variable is useful when you want to conditionally stop another thread or not. That way, you can always have a worker thread that waits for it to notice that it has nothing to do to work.
The atomic solution requires your interaction with the user interface to synchronize with the workflow or very complex logic to do this asynchronously.
Typically, your UI response flow should never be blocked in an unavailable state from workflows.
struct worker_thread { worker_thread( std::function<void()> t, bool play = true ): task(std::move(t)), execute(play) { thread = std::async( std::launch::async, [this]{ work(); }); } // move is not safe. If you need this movable, // use unique_ptr<worker_thread>. worker_thread(worker_thread&& )=delete; ~worker_thread() { if (!exit) finalize(); wait(); } void finalize() { auto l = lock(); exit = true; cv.notify_one(); } void pause() { auto l = lock(); execute = false; } void play() { auto l = lock(); execute = true; cv.notify_one(); } void wait() { Assert(exit); if (thread) thread.get(); } private: void work() { while(true) { bool done = false; { auto l = lock(); cv.wait( l, [&]{ return exit || execute; }); done = exit; // have lock here } if (done) break; task(); } } std::unique_lock<std::mutex> lock() { return std::unique_lock<std::mutex>(m); } std::mutex m; std::condition_variable cv; bool exit = false; bool execute = true; std::function<void()> task; std::future<void> thread; };
or somesuch.
It belongs to the stream. The thread starts the task many times while it is in play() mode. If you pause() the next time you finish task() , the workflow stops. If you play() before completing the call to task() do not notice pause() .
The only expectation is the destruction of worker_thread , where it automatically informs the worker thread that should exit and waits for it to complete.
You can manually select .wait() or .finalize() . .finalize() is asynchronous, but if your application shuts down, you can call it earlier and give the worker thread more time to clean up, while the main thread cleans things up elsewhere.
.finalize() cannot be undone.
Code not verified.
source share