尝试创建一个可以使用packaged_task执行任何作业的JobProcessor:
class JobProcessor
{
public:
JobProcessor(uint8_t numThreads = 8);
template<class Fn, class... Args>
auto add_task(JobPriority priority, Fn task, Args... args)
{
auto packaged_task = package_task(task, args...);
{
std::lock_guard<std::mutex> lk(_task_wait);
_job_list.emplace(priority, std::move(packaged_task.first));
}
_task_sem.notify_one();
return std::move(packaged_task.second);
}
virtual void run();
virtual void stop() { _stop = false; };
protected:
template<class Fn, class... Args> requires std::invocable<Fn, Args...>
auto package_task(Fn f, Args... args) const
{
using Ret = std::invoke_result_t<Fn, Args...>;
// Create the packaged_task
auto task = std::packaged_task<Ret()>(
[f = std::move(f), ... captured_args = std::forward<Args>(args)]() mutable
{
return std::invoke(std::move(f), std::move(captured_args)...);
}
);
// Get the future before wrapping the task to be able to use the return
auto future = task.get_future();
// Wrap it in a lambda to the task can return any type
auto task_wrapper = [task = std::move(task)]() mutable {
task();
};
return std::make_pair(std::move(task_wrapper), std::move(future));
}
private:
std::atomic_bool _stop;
uint8_t _numThreads;
std::list<std::thread> _threads;
std::mutex _task_wait;
std::condition_variable _task_sem;
std::priority_queue<Job> _job_list;
};
工作声明为:
class Job
{
public:
Job(JobPriority priority, std::packaged_task<void()> task)
: priority(priority), task(std::move(task))
{}
Job(const Job&) = delete;
Job(Job&& job)
{
this->task = std::move(job.task);
this->priority = job.priority;
}
int priority;
void execute()
{
task();
}
friend bool operator<(const Job& lhs, const Job& rhs)
{
return lhs.priority < rhs.priority;
}
private:
std::packaged_task<void()> task;
};
我希望这个处理器能够执行一个可以在未来返回某些内容的任务,因此我将 Job 打包到 lambda 中。 然而,当尝试像这样使用它时:
auto future1 = job_processor.add_task(JobPriority::LOW, [&]() {
task1_executed = true;
});
我收到以下错误:
note: no known conversion for argument 2 from 'JobProcessor::package_task<JobProcessorTest_BasicExecution_Test::TestBody()::<lambda()> >(JobProcessorTest_BasicExecution_Test::TestBody()::<lambda()>) const::<lambda()>' to 'std::packaged_task<void()>'
16 | Job(JobPriority priority, std::packaged_task<void()> task)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
lambda 签名应该是
void()
。这里的问题主要是由
std::packaged_task
内部使用 operator=
引起的。声明复制和移动运算符解决了这个问题。