标签: packaged-task

这个语法是什么意思,“类模板 <class R, class ...Args> 类名 <R(Args...)>”

我一直在尝试更多关于 C++ 中的多线程编程,但我很难理解,std::promise所以我开始在这个网站上寻找答案,结果发现有人和我有同样的问题。但是阅读答案让我更加困惑,这是答案中的代码,大概是类似的实现std::packaged_task

template <typename> class my_task;

template <typename R, typename ...Args>
class my_task<R(Args...)>
{
    std::function<R(Args...)> fn;
    std::promise<R> pr;             // the promise of the result
public:
    template <typename ...Ts>
    explicit my_task(Ts &&... ts) : fn(std::forward<Ts>(ts)...) { }

    template <typename ...Ts>
    void operator()(Ts &&... ts)
    {
        pr.set_value(fn(std::forward<Ts>(ts)...));  // fulfill the promise
    }

    std::future<R> get_future() { return pr.get_future(); }

    // disable copy, default move
};
Run Code Online (Sandbox Code Playgroud)

在此代码中,

1-这个语法是什么意思template <typename R, typename ...Args> class my_task<R(Args...)>,更具体地说,目的是什么<R(Args...)>

2-为什么班级有前向减速?

谢谢

c++ multithreading promise packaged-task variadic-templates

6
推荐指数
1
解决办法
2414
查看次数

我应该如何正确地将 packaged_task 移至 lambda?

我一直在尝试将 packaged_task 捕获到 lambda 中,但失败了。
\n我完全理解动作语义,也读过一些现代文学,我想我没有错过任何东西。我还阅读了 Josuttis 的移动语义书,以及关于广义 lambda 捕获的 ISO 主题以及ISO C++ 14 语言扩展
中的类似案例\n我有下一个代码:

\n\n
#include <thread>\n#include <vector>\n#include <functional>\n#include <queue>\n#include <condition_variable>\n#include <mutex>\n#include <future>\n#include <type_traits>\n#include <iostream>\n\n// #include\'s for below code and other purposes\n\nint main() {\n    auto f = []() { return 1; }; \n    std::queue<std::function<void()>> q;\n    std::packaged_task<int()> pack(f);\n    q.emplace([p = std::move(pack)] () mutable { p(); });\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这里我创建了简单的函数队列,保存一些“void()”和packaged_task,传递“int”返回类型的“f”。
\n然后我尝试将 packaged_task 移动到 lambda 中以便稍后在其他线程中使用它(我需要在其他线程中使用它,这将在稍后执行它,当“pack”将被销毁时,这就是为什么我不能引用它)
\n看起来一切都很好,但是当我用“g++ main.cpp -o main -std=c++14”(甚至使用c++17)编译它时, g++ 告诉我这个:

\n\n
\n

/usr/include/c++/9/bits/std_function.h:176:6: 错误:使用已删除的函数 \xe2\x80\x98main()::::(const main()::&)\xe2\x80 …

c++ lambda move-semantics packaged-task

6
推荐指数
1
解决办法
1120
查看次数

将packaged_task移动到lambda

我想移动并在lambda中调用boost :: packaged_task.

但是,我无法找到一个优雅的解决方案.

这不会编译.

        template<typename Func>
        auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept
        {   
            typedef boost::packaged_task<decltype(func())> task_type;

            auto task = task_type(std::forward<Func>(func));
            auto future = task.get_future();

            execution_queue_.try_push([=]
            {
                try{task();}
                catch(boost::task_already_started&){}
            });

            return std::move(future);       
        }

    int _tmain(int argc, _TCHAR* argv[])
    {
        executor ex;
        ex.begin_invoke([]{std::cout << "Hello world!";});
       //error C3848: expression having type 'const boost::packaged_task<R>' would lose some const-volatile qualifiers in order to call 'void boost::packaged_task<R>::operator ()(void)'
//          with
//          [
//              R=void
//          ]
        return 0;
    }
Run Code Online (Sandbox Code Playgroud)

我相当丑陋的解决方案:

    struct task_adaptor_t
    { …
Run Code Online (Sandbox Code Playgroud)

c++ lambda packaged-task c++11

5
推荐指数
1
解决办法
1605
查看次数

在C++ 11中实现一个简单的通用线程池

我想创建一个用于实验目的的线程池(以及有趣的因素).它应该能够处理各种各样的任务(所以我可以在以后的项目中使用它).


在我的线程池类中,我将需要某种任务队列.由于标准库std::packaged_task从C++ 11标准开始提供,我的队列看起来像std::deque<std::packaged_task<?()> > task_queue,所以客户端可以std::packaged_task通过某种公共接口函数将s 推入队列(然后池中的一个线程将通知一个条件变量来执行它,等等.


我的问题与std::packaged_task<?()>deque中s 的模板参数有关.

函数签名?()应该能够处理任何类型/数量的参数,因为客户端可以执行以下操作:

std::packaged_task<int()> t(std::bind(factorial, 342)); thread_pool.add_task(t);

所以我不必处理参数的类型/数量.

但是回报价值应该是多少?(因此问号)

  • 如果我将整个线程池类作为模板类,它的一个实例将只能处理具有特定签名的任务(如std::packaged_task<int()>).

    我希望一个线程池对象能够处理任何类型的任务.

  • 如果我使用std::packaged_task<void()>并且调用的函数返回一个整数,或者任何东西,那么这就是未定义的行为.

c++ multithreading packaged-task c++11 stdthread

5
推荐指数
1
解决办法
4868
查看次数

std :: packaged_task如何工作

我正在分析以下代码片段,并试图详细了解它:

template<typename FUNCTION, typename... ARGUMENTS>
auto ThreadPool::add( FUNCTION&& Function, ARGUMENTS&&... Arguments ) -> std::future<typename std::result_of<FUNCTION(ARGUMENTS...)>::type>
{
    using PackedTask = std::packaged_task<typename std::result_of<FUNCTION(ARGUMENTS...)>::type()>;

    auto task = std::make_shared<PackedTask>(std::bind(std::forward<FUNCTION>(Function), std::forward<ARGUMENTS>(Arguments)...));

    // get the future to return later
    auto ret = task->get_future();

    {
        std::lock_guard<std::mutex> lock{jobsMutex};
        jobs.emplace([task]() { (*task)(); });
    }

    // let a waiting thread know there is an available job
    jobsAvailable.notify_one();

    return ret;
}
Run Code Online (Sandbox Code Playgroud)

我对此几乎没有任何疑问std::packaged_task.

正如可以在看到add(...)方法体,实例std::packaged_task- task是范围与方法执行结束时结束局部变量.返回值retstd::future类型由复制返回.的值ret被给予了的task(这是本地).所以一旦方法执行完成,task超出范围,所以 …

c++ multithreading future packaged-task c++11

5
推荐指数
1
解决办法
627
查看次数

如何使用返回任意类型的函数创建一个包含boost :: packaged_task <>的队列?

我正在尝试构建一个需要由一个线程执行的函数的工作队列,并且可以由许多线程提供.为实现这一目标,我计划使用boost :: packaged_task和boost :: unique_future.这个想法是你会做的:

Foo value = queue.add(myFunc).get();

哪个会阻塞,直到执行该功能.所以queue.add(...)接受一个boost :: function,并返回一个boost :: unique_future.在内部,它然后使用boost :: function为其构造函数创建一个boost :: packaged_task.

我遇到的问题是boost :: function <...>每次都不一样.具体来说,它的返回值将会改变(但是,函数永远不会采用任何参数).因此,我必须有一个类似于以下内容的add函数:

template <typename ResultType>
boost::unique_future<ResultType> add(boost::function<ResultType ()> f) {
   boost::packaged_task<boost::function<ResultType ()> > task(f);
   queue.push_back(task);
   return task.get_future();
}
Run Code Online (Sandbox Code Playgroud)

好吧,这似乎并不太糟糕,但后来我遇到了如何定义'队列'的问题.我想我别无选择,只能使用boost :: any,因为类型不会是常量:

std::list<boost::any> queue; // note: I'm not concerned with thread-safety yet
Run Code Online (Sandbox Code Playgroud)

但是当我尝试实现我的executeSingle时,我遇到了一个问题(只从队列中取出一个项目来执行):

void executeSingle() {
    boost::any value = queue.back();
    boost::packaged_task<?> task = boost::packaged_task<?>(boost::move(value));
    // actually execute task
    task();
    queue.pop_back();
}
Run Code Online (Sandbox Code Playgroud)

'?' 表示我不确定的事情.我不能用模板调用executeSingle,因为它是从一个单独的线程调用的.我尝试使用boost :: any,但是我得到了错误:

  conversion from 'boost::any' to non-scalar type …
Run Code Online (Sandbox Code Playgroud)

c++ queue templates boost packaged-task

4
推荐指数
1
解决办法
4453
查看次数

匿名 std::packaged_task

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

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

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

std::packaged_task<typename std::result_of<Function(Args...)>::type()> task(f(args...));
return task.get_future();
Run Code Online (Sandbox Code Playgroud)

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

我的问题是:如何从一个创建std::packaged_task<R()>一个std::packaged_task<void()>在两个步骤,这样我可以从第一个任务返回它的未来,并把第二个进入队列std::queue<std::packaged_task<void()>>类型?

c++ thread-safety packaged-task

4
推荐指数
1
解决办法
1682
查看次数

直接初始化!=从不同类型转换时复制初始化?

我一直认为对于与类类型不匹配的类型 T 的直接初始化和复制初始化是绝对相等的。但我似乎误会了。如果我复制初始化(使用=),下面的代码不会编译,并且只有当我通过括号()直接初始化时才编译(在任何情况下,代码在终止时都不起作用,但这是一个不同的故事,与这个问题)。

演示

#include <future>
#include <cstdio>

int main()
{
    /* This doesn't compile */

    // std::packaged_task<int()> foo = []() -> int {
    //     return 10;
    // };

    /* This works */

    std::packaged_task<int()> foo([]() -> int {
        return 10;
    });

    auto fut = foo.get_future();
    foo();
    auto a = fut.get();
    printf("a == %d\n", a);
}
Run Code Online (Sandbox Code Playgroud)

错误:

<source>: In function 'int main()':
<source>:8:37: error: conversion from 'main()::<lambda()>' to non-scalar type 'std::packaged_task<int()>' requested
    8 |     std::packaged_task<int()> foo = []() -> …
Run Code Online (Sandbox Code Playgroud)

c++ copy-initialization packaged-task direct-initialization

2
推荐指数
1
解决办法
92
查看次数

只能移动的对象可以做成shared_ptr吗?

我正在阅读thread_pool的开源代码

它显示

// add new work item to the pool
template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args) 
    -> std::future<typename std::result_of<F(Args...)>::type>
{
    using return_type = typename std::result_of<F(Args...)>::type;

    auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
        );
        
    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);

        // don't allow enqueueing after stopping the pool
        if(stop)
            throw std::runtime_error("enqueue on stopped ThreadPool");

        tasks.emplace([task](){ (*task)(); });
    }
    condition.notify_one();
    return res;
}
Run Code Online (Sandbox Code Playgroud)

据我所知, std::packaged_task是唯一可移动的对象,那么shared_ptr 可以task由 组成吗std::packaged_task?因为std::packaged_task永远不可能shared。 …

c++ shared-ptr packaged-task

0
推荐指数
1
解决办法
70
查看次数