Boost::ASIO and std::packaged_task
Boost::ASIO and std::packaged_task
我有以下 C++14 代码
boost::asio::io_service service_;
我想将工作片段提交到io_service
中,使用以下代码,该代码接受任何函数,它是输入参数并返回返回值的std::future
。
template <typename F, typename... Args>
auto enqueue(F &&f, Args &&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
typedef typename std::result_of<F(Args...)>::type rType;
auto task = std::make_shared<std::packaged_task<rType()>>(std::bind(std::forward<F>(f),
std::forward<Args>(args)...));
std::future<rType> res = task->get_future();
service_.post(task);
return res;
}
然后这被称为使用
enqueue([] (int i) {
return i+1;
}, 100);
这似乎不起作用。我收到一个错误,说service_.post()
没有预料到这个输入。
xxxxxxxxxxxxxx:49:3: required from ‘std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> enqueue(F&&, Args&& ...) [with F = main()::<lambda()>::<lambda()>; Args = {int}; typename std::result_of<_Functor(_ArgTypes ...)>::type = int]’
xxxxxxxxxxxxxx:44:6: required from here
/usr/include/boost/asio/impl/io_service.hpp:102:3: error: static assertion failed: CompletionHandler type requirements not met
BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
^
/usr/include/boost/asio/impl/io_service.hpp:85:3: error: no match for call to ‘(std::shared_ptr<std::packaged_task<void()> >) ()’
BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
^
据我了解boost::asio
文档,这是可以做到的。有什么想法吗?
来自post()
的文档:
处理器
要调用的处理程序。io_service将根据需要创建处理程序对象的副本。处理程序的函数签名必须是:
void handler();
你正在通过一个std::shared_ptr<std::packaged_task<int()>>
.shared_ptr
没有定义operator()
。而且packaged_task
拆包是不可复制的。
因此,为了使这项工作,您必须制作一个shared_ptr<promise>
:
using R = std::result_of_t<F(Args&&...)>;
auto promise = std::make_shared<std::promise<R>>();
std::future<R> res = promise->get_future();
service.post([promise = std::move(promise),
f = std::forward<F>(f),
args = std::make_tuple(std::forward<Args>(args)...)]{
promise->set_value(std::experimental::apply(f, args));
});
return res;
我似乎记得自己也被这个咬过。这是因为std::packaged_task
不可复制(显式删除复制构造函数)。
这是因为它包含一个承诺,这个承诺也是不可复制的——只能移动。
asio::io_service
要求处理程序对象是可复制的。
您可能需要考虑构建自己的类似打包任务的函数对象,以保持对承诺shared_ptr。那将是可复制的。
非空返回类型是红鲱鱼 - 不要浪费时间。
打包任务的文档在这里:http://en.cppreference.com/w/cpp/thread/packaged_task/packaged_task
通过最近的提升,您可以在没有shared_ptr
的情况下执行此操作,如下所示。 您需要进行两项修改:
- 使用
boost::asio::post
而不是使用(已弃用的)io_service
或较新io_context
的(已弃用)post
函数- 由于我不知道的原因,
packaged_task
需要用std::bind
包裹。 否则,将在运行时引发异常。
template <typename F, typename... Args>
auto enqueue(boost::asio::io_service& service_, F &&f, Args &&... args)
-> std::future<typename std::result_of<F(Args...)>::type>
{
typedef typename std::result_of<F(Args...)>::type rType;
auto task = std::packaged_task<rType()>(std::bind(std::forward<F>(f),
std::forward<Args>(args)...));
std::future<rType> res = task.get_future();
// Note the std::bind. Without it the program would throw "future already received"
boost::asio::post(service_.get_executor(), std::bind(std::move(task)));
return res;
}
可以在此处找到一个自包含的示例:https://godbolt.org/z/zE4qWbh1d
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 使用"Task"函数指针队列定义作业管理器
- Visual Studio C++ Project File CustomBuild Task: Filter Outp
- 如何将C std ::未来返回值调整到C#System.Threading.tasks.task
- C# Task.Run() vs. C++ std::async()
- C++ FOR LOOP ONLY task
- inline void addTask(Task task) vs inline void addTask(const Task &task)
- 为什么我会收到"variable 'std::packaged_task<int> task' has initializer but incomplete type"错误
- C++ -<Task> 删除堆上分配的任务数组时,将列表 l(或任何 STL 容器)添加为数据成员会导致错误
- "task"指令的"final"条款是否正确?
- 如何在后台进程上处理来自Windows任务管理器的"End Task"?
- 视觉工作室 2013 "A task was cancelled"
- 正在CDH4中获取mapreduce.task.partition
- 创建Task Then函数(类似std::future.then)
- 为什么不在pop之后运行task并返回true呢?
- Task of getline
- Tantamount of while(cin>>something){some task ;} in java?
- "typedef void (*task) ()"做什么?
- Glowcode内存使用量与Window Task Manager不同