匿名std :: packaged_task

时间:2013-01-15 09:59:52

标签: c++ thread-safety packaged-task

我正在尝试围绕Glib :: Dispatcher构建一些包装器,以将任何功能类型分派到调度程序中。我想要一些函数调度,可以将函数传递到Glib主循环中:

template<class Function, class ...Args>
std::future<typename std::result_of<Function(Args...)>::type>
dispatch(Function &&f, Args &&...args);

此函数将从f(args)创建一个打包的任务并返回其未来:

std::packaged_task<typename std::result_of<Function(Args...)>::type()> task(f(args...));
return task.get_future();

我现在需要从这个任务创建一个std::packaged_task<void()>来将它们放到一个std :: queue中,这样连接到Glib :: Dispatcher的函数就可以执行它们。

我的问题是:如何通过两个步骤从std::packaged_task<R()> std::packaged_task<void()>创建,以便我可以从第一个任务返回它的未来,并将第二个任务放入{{{{{ 1}}输入?

1 个答案:

答案 0 :(得分:3)

首先,让std::packaged_task使用给定的参数集调用特定函数,然后(a)在将函数传递给std::packaged_task之前需要将函数绑定到参数,或者(b)您需要将参数传递给std::packaged_task对象的函数调用运算符。在您的代码中,您将f(args...)传递给std::packaged_task构造函数,它将在那里调用函数,然后将结果传递给构造函数,这可能不是您想要的,甚至可能无法编译。

其次,如果在构造时绑定参数,那么std::packaged_task实例是一个不带参数的可调用对象并返回void,因此可以直接移动 std::packaged_task<void()>

把这一切放在一起,我们得到:

std::queue<std::packaged_task<void()>> task_queue;

template<class Function, class ...Args>
std::future<typename std::result_of<Function(Args...)>::type>
dispatch(Function &&f, Args &&...args) {
    std::packaged_task<typename std::result_of<Function(Args...)>::type()> task(
        std::bind(f,args...));
    auto res=task.get_future();
    task_queue.push(std::packaged_task<void()>(std::move(task)));
    return res;
}