You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
1.9 KiB
C

1 month ago
#include <functional>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <future>
#include <queue>
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̨<EFBFBD>߳<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŷ<EFBFBD>ִ<EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
class AsyncWorker
{
public:
AsyncWorker()
: done(false)
{
worker_thread = std::thread(&AsyncWorker::workerLoop, this);
}
~AsyncWorker()
{
{
std::lock_guard<std::mutex> lock(queue_mutex);
done = true;
}
cond_var.notify_all();
if (worker_thread.joinable())
{
worker_thread.join();
}
}
template <typename Func>
auto postTask(Func task) -> std::future<decltype(task())>
{
using result_type = decltype(task());
auto packaged_task = std::make_shared<std::packaged_task<result_type()>>(task);
std::future<result_type> result = packaged_task->get_future();
{
std::lock_guard<std::mutex> lock(queue_mutex);
task_queue.push([packaged_task] { (*packaged_task)(); });
}
cond_var.notify_one();
return result;
}
private:
void workerLoop()
{
while (true)
{
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(queue_mutex);
cond_var.wait(lock, [this] { return !task_queue.empty() || done; });
if (done && task_queue.empty())
{
return;
}
task = std::move(task_queue.front());
task_queue.pop();
}
task();
}
}
std::thread worker_thread;
std::queue<std::function<void()>> task_queue;
std::mutex queue_mutex;
/*
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> cppreference <EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>std::condition_variable ֻ<EFBFBD><EFBFBD> std::unique_lock <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> std::condition_variable_any
* The condition_variable_any class is a generalization of std::condition_variable.
* Whereas std::condition_variable works only on std::unique_lock<std::mutex>,
* condition_variable_any can operate on any lock that meets the BasicLockable requirements.
*/
std::condition_variable_any cond_var;
std::atomic<bool> done;
};