Files
yacreader/common/worker_thread.h
luisangelsm 3709b6e737
Some checks failed
Build / Initialization (push) Has been cancelled
Build / Code Format Validation (push) Has been cancelled
Build / Linux (Qt6) (push) Has been cancelled
Build / Linux (Qt6 + 7zip) (push) Has been cancelled
Build / macOS (Qt6 Universal) (push) Has been cancelled
Build / Windows x64 (Qt6) (push) Has been cancelled
Build / Windows ARM64 (Qt6) (push) Has been cancelled
Build / Docker amd64 Image (push) Has been cancelled
Build / Docker arm64 Image (push) Has been cancelled
Build / Publish Dev Builds (push) Has been cancelled
Build / Publish Release (push) Has been cancelled
Build / Publish YACReader10 Pre-release Builds (push) Has been cancelled
Format includes using clang-format
2026-03-13 18:21:38 +01:00

93 lines
2.0 KiB
C++

#ifndef WORKER_THREAD_H
#define WORKER_THREAD_H
#include "release_acquire_atomic.h"
#include <cassert>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>
#include <utility>
//! Usage:
//! 1. call performTask();
//! 2. wait until busy() returns false;
//! 3. (optionally) call extractResult();
//! 4. return to step 1 (assign another task).
//! You may invoke busy() and the destructor at any moment.
template<typename Result>
class WorkerThread
{
public:
WorkerThread() = default;
~WorkerThread();
using Task = std::function<Result()>;
void performTask(Task newTask);
//! @return true if the last assigned task is not done yet.
bool busy() const { return working; }
Result extractResult() { return std::move(result); }
private:
void run();
Task task;
Result result;
ReleaseAcquireAtomic<bool> working { false };
bool abort { false };
std::mutex mutex;
std::condition_variable condition;
std::thread thread;
};
template<typename Result>
WorkerThread<Result>::~WorkerThread()
{
{
std::lock_guard<std::mutex> lock(mutex);
abort = true;
}
condition.notify_one();
if (thread.joinable()) {
thread.join();
}
}
template<typename Result>
void WorkerThread<Result>::performTask(Task newTask)
{
assert(!working && "Don't interrupt my work!");
assert(newTask && "The task may not be empty.");
task = std::move(newTask);
if (thread.joinable()) {
{
std::lock_guard<std::mutex> lock(mutex);
working = true;
}
condition.notify_one();
} else {
working = true;
thread = std::thread(&WorkerThread::run, this);
}
}
template<typename Result>
void WorkerThread<Result>::run()
{
while (true) {
result = task();
working = false;
std::unique_lock<std::mutex> lock(mutex);
condition.wait(lock, [this] { return working || abort; });
if (abort)
break;
}
}
#endif // WORKER_THREAD_H