mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-27 04:35:34 +08:00
[feat] add task queue module
This commit is contained in:
69
src/common/any_invocable.h
Normal file
69
src/common/any_invocable.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2025-03-14
|
||||
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _ANY_INVOCABLE_H_
|
||||
#define _ANY_INVOCABLE_H_
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
// 简化版的 AnyInvocable
|
||||
template <typename Signature>
|
||||
class AnyInvocable;
|
||||
|
||||
template <typename R, typename... Args>
|
||||
class AnyInvocable<R(Args...)> {
|
||||
public:
|
||||
// 默认构造函数
|
||||
AnyInvocable() = default;
|
||||
|
||||
// 构造函数:接受一个可以调用的对象
|
||||
template <typename Callable>
|
||||
AnyInvocable(Callable&& callable)
|
||||
: callable_(std::make_unique<CallableWrapper<Callable>>(
|
||||
std::forward<Callable>(callable))) {}
|
||||
|
||||
// 调用运算符
|
||||
R operator()(Args... args) {
|
||||
return callable_->Invoke(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// 移动构造函数
|
||||
AnyInvocable(AnyInvocable&&) = default;
|
||||
// 移动赋值运算符
|
||||
AnyInvocable& operator=(AnyInvocable&&) = default;
|
||||
|
||||
private:
|
||||
// 抽象基类,允许不同类型的可调用对象
|
||||
struct CallableBase {
|
||||
virtual ~CallableBase() = default;
|
||||
virtual R Invoke(Args&&... args) = 0;
|
||||
};
|
||||
|
||||
// 模板派生类:实际存储 callable 对象
|
||||
template <typename Callable>
|
||||
struct CallableWrapper : public CallableBase {
|
||||
CallableWrapper(Callable&& callable)
|
||||
: callable_(std::forward<Callable>(callable)) {}
|
||||
|
||||
R Invoke(Args&&... args) override {
|
||||
return callable_(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
Callable callable_;
|
||||
};
|
||||
|
||||
std::unique_ptr<CallableBase> callable_;
|
||||
};
|
||||
|
||||
// 简单的包装函数
|
||||
template <typename R, typename... Args>
|
||||
AnyInvocable<R(Args...)> MakeMoveOnlyFunction(std::function<R(Args...)>&& f) {
|
||||
return AnyInvocable<R(Args...)>(std::move(f));
|
||||
}
|
||||
|
||||
#endif
|
||||
107
src/common/task_queue.h
Normal file
107
src/common/task_queue.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2025-03-14
|
||||
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _TASK_QUEUE_H_
|
||||
#define _TASK_QUEUE_H_
|
||||
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "any_invocable.h"
|
||||
|
||||
class TaskQueue {
|
||||
public:
|
||||
TaskQueue(size_t numThreads = 1)
|
||||
: stop_(false), workers_(), taskQueue_(), mutex_(), cond_var_() {
|
||||
for (size_t i = 0; i < numThreads; i++) {
|
||||
workers_.emplace_back([this]() { this->WorkerThread(); });
|
||||
}
|
||||
}
|
||||
|
||||
~TaskQueue() {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
stop_ = true;
|
||||
}
|
||||
cond_var_.notify_all();
|
||||
for (std::thread &worker : workers_) {
|
||||
if (worker.joinable()) {
|
||||
worker.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 立即执行任务
|
||||
void PostTask(AnyInvocable<void()> task) {
|
||||
PostDelayedTask(std::move(task), 0);
|
||||
}
|
||||
|
||||
// 延迟执行任务
|
||||
void PostDelayedTask(AnyInvocable<void()> task, int delay_ms) {
|
||||
auto execute_time =
|
||||
std::chrono::steady_clock::now() + std::chrono::milliseconds(delay_ms);
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
taskQueue_.emplace(execute_time,
|
||||
std::move(task)); // 确保参数匹配 TaskItem 构造
|
||||
}
|
||||
cond_var_.notify_one();
|
||||
}
|
||||
|
||||
private:
|
||||
struct TaskItem {
|
||||
std::chrono::steady_clock::time_point execute_time;
|
||||
AnyInvocable<void()> task = nullptr;
|
||||
|
||||
TaskItem(std::chrono::steady_clock::time_point time,
|
||||
AnyInvocable<void()> func)
|
||||
: execute_time(time), task(std::move(func)) {}
|
||||
|
||||
bool operator>(const TaskItem &other) const {
|
||||
return execute_time > other.execute_time;
|
||||
}
|
||||
};
|
||||
|
||||
void WorkerThread() {
|
||||
while (true) {
|
||||
AnyInvocable<void()> task;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
cond_var_.wait(lock, [this]() { return !taskQueue_.empty() || stop_; });
|
||||
|
||||
if (stop_ && taskQueue_.empty()) return;
|
||||
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (taskQueue_.top().execute_time > now) {
|
||||
cond_var_.wait_until(lock, taskQueue_.top().execute_time,
|
||||
[this]() { return stop_; });
|
||||
}
|
||||
|
||||
if (stop_ && taskQueue_.empty()) return;
|
||||
|
||||
task = std::move(
|
||||
const_cast<AnyInvocable<void()> &>(taskQueue_.top().task));
|
||||
taskQueue_.pop();
|
||||
}
|
||||
task(); // 执行任务
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::thread> workers_;
|
||||
std::priority_queue<TaskItem, std::vector<TaskItem>, std::greater<>>
|
||||
taskQueue_;
|
||||
mutable std::mutex mutex_;
|
||||
std::condition_variable cond_var_;
|
||||
bool stop_;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user