• c++ 11 多线程支持 (std::packaged_task)


    定义于头文件 
    1. template< class > class packaged_task; // 不定义 (1) (C++11 起)
    2. template< class R, class ...Args >
    3. class packaged_task<R(Args...)>; (2) (C++11 起)

    类模板 std::packaged_task 包装任何可调用 (Callable) 目标(函数、 lambda 表达式、 bind 表达式或其他函数对象),使得能异步调用它。其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。

    正如 std::function , std::packaged_task 是多态、具分配器的容器:可在堆上或以提供的分配器分配存储的可调用对象。

    构造函数

    std::packaged_task<R(Args...)>::packaged_task
    1. packaged_task() noexcept; (1) (C++11 起)
    2. template <class F>
    3. explicit packaged_task( F&& f ); (2) (C++11 起)
    4. template <class F, class Allocator>
    5. explicit packaged_task( std::allocator_arg_t, const Allocator& a, F&& f );
    6. (3) (C++11 起) (C++17 前)
    7. packaged_task( const packaged_task& ) = delete; (4) (C++11 起)
    8. packaged_task( packaged_task&& rhs ) noexcept; (5) (C++11 起)

    构造新的 std::packaged_task 对象。

    1) 构造无任务且无共享状态的 std::packaged_task 对象。

    2) 构造拥有共享状态和任务副本的 std::packaged_task 对象,以 std::forward(f) 初始化副本。若 std::decay::type 与 std::packaged_task 是同一类型,则此构造函数不参与重载决议。

    3) 构造拥有共享状态和任务副本的 std::packaged_task 对象,以 std::forward(f) 初始化副本。用提供的分配器分配存储任务所需的内存。 若 std::decay::type 与 std::packaged_task 是同一类型,则此构造函数不参与重载决议。

    4) 复制构造函数被删除, std::packaged_task 仅可移动。

    5) 以 rhs 之前所占有的共享状态和任务构造 std::packaged_task ,令 rhs 留在无共享状态且拥有被移动后的任务的状态。

    参数

    f-要执行的可调用目标(函数、成员函数、 lambda 表达式、函数对象)
    a-存储任务时所用的分配器
    rhs-要移动的 std::packaged_task

    异常

    2) f 的复制/移动构造函数所抛的任何异常,而若内存分配失败则可能为 std::bad_alloc 。

    3) f 的复制/移动构造函数,而若内存分配失败则有分配器的 allocate 函数所抛的任何异常。

    4) (无)

    析构函数

    std::packaged_task<R(Args...)>::~packaged_task
    ~packaged_task();

    抛弃共享状态并销毁存储的任务对象。

    同 std::promise::~promise ,若在令共享状态就绪前抛弃它,则存储以 std::future_errc::broken_promise 为 error_code 的 std::future_error 异常。

    参数

    (无)

    移动任务对象

    std::packaged_task<R(Args...)>::operator=
    1. packaged_task& operator=( const packaged_task& ) = delete; (1) (C++11 起)
    2. packaged_task& operator=( packaged_task&& rhs ) noexcept; (2) (C++11 起)

    1) 复制赋值运算符被删除, std::packaged_task 仅可移动。

    2) 若存在则释放共享状态,销毁先前保有的任务,并将 rhs 所占有的共享状态和任务移动到 *this 。令 rhs 无共享状态,并拥有被移动后的任务。

    参数

    rhs-移动来源的 std::packaged_task

    检查任务对象是否拥有合法函数

    std::packaged_task<R(Args...)>::valid
    bool valid() const noexcept;  (C++11 起) 

    检查 *this 是否拥有共享状态。

    参数

    (无)

    返回值

    若 *this 拥有共享状态则为 true ,否则为 false 。

    交换二个任务对象

    std::packaged_task<R(Args...)>::swap
    void swap( packaged_task& other ) noexcept;   (C++11 起) 

    交换 *this 与 other 的共享状态和存储的任务。

    参数

    other-要交换状态的 packaged_task

    返回值

    (无)

    返回与承诺的结果关联的 std::future

    std::packaged_task<R(Args...)>::get_future
    std::future<R> get_future();    (C++11 起) 

    返回与 *this 共享同一共享状态的 future

    get_future 只能对每个 packaged_task 调用一次。

    参数

    (无)

    返回值

    与 *this 共享同一共享状态的 future

    异常

    遇到下列条件时为 std::future_error 。

    • 已通过调用 get_future 取得共享状态。设置 error_category 为 future_already_retrieved 。
    • *this 无共享状态。设置 error_category 为 no_state 。


    执行函数

    std::packaged_task<R(Args...)>::operator()
    void operator()( ArgTypes... args );   (C++11 起) 

    args 为参数调用存储的任务。任务返回值或任何抛出的异常被存储于共享状态。令共享状态就绪,并解除阻塞任何等待此操作的线程。

    参数

    args-调用时传递给存储任务的参数

    返回值

    (无)

    异常

    遇到下列条件时为 std::future_error :

    • 已调用存储的任务。设置 error_category 为 promise_already_satisfied 。
    • *this 无共享状态。设置 error_category 为 no_state 。

    注意

    operator() 的成功调用同步于对任何与 *this 共享其共享状态的 std::future 或 std::shared_future 的任何成员函数调用。

    (C++14 前)

    在共享状态已提供的同步保证外,无另外的同步保证。

    (C++14 起)

     

    重置状态,抛弃任何先前执行的存储结果

     std::packaged_task<R(Args...)>::reset
    void reset();              (C++11 起) 

    重置状态,抛弃先前执行的结果。构造共享状态。

    等价于 *this = packaged_task(std::move(f)) ,其中 f 是存储的任务。

    参数

    (无)

    返回值

    (无)

    异常

    • 若 *this 无共享状态则为 std::future_error 。设置 error_condition 为 no_state 。
    • 若无足够内存以分配新的共享状态则为 std::bad_alloc 。
    • packaged_task 的移动构造函数所抛的任何异常

    执行函数,并确保结果仅在一旦当前线程退出时就绪

    std::packaged_task<R(Args...)>::make_ready_at_thread_exit
    void make_ready_at_thread_exit( ArgTypes... args );   (C++11 起) 

    void make_ready_at_thread_exit( ArgTypes... args );

    (C++11 起)

    以转发的 args 为参数调用存储的任务。任务返回值或任何抛出的异常被存储于 *this 的共享状态。

    仅在当前线程退出,并销毁所有线程局域存储期对象后,才令共享状态就绪。

    参数

    args-调用时传递给存储任务的参数

    返回值

    (无)

    异常

    遇到下列条件时为 std::future_error :

    • 已调用存储的任务。设置 error_category 为 promise_already_satisfied 。
    • *this 无共享状态。设置 error_category 为 no_state 。

    调用示例

    1. #include <future>
    2. #include <iostream>
    3. #include <chrono>
    4. #include <thread>
    5. #include <functional>
    6. #include <utility>
    7. void worker(std::future<void>& output)
    8. {
    9. std::packaged_task<void(bool&)> my_task{ [](bool & done)
    10. {
    11. done = true;
    12. } };
    13. auto result = my_task.get_future();
    14. bool done = false;
    15. my_task.make_ready_at_thread_exit(done); // 立即执行任务
    16. std::cout << "worker: done = " << std::boolalpha << done << std::endl;
    17. auto status = result.wait_for(std::chrono::seconds(0));
    18. if (status == std::future_status::timeout)
    19. {
    20. std::cout << "worker: result is not ready yet" << std::endl;
    21. }
    22. output = std::move(result);
    23. }
    24. int main()
    25. {
    26. std::future<void> result;
    27. std::thread{worker, std::ref(result)}.join();
    28. auto status = result.wait_for(std::chrono::seconds(0));
    29. if (status == std::future_status::ready)
    30. {
    31. std::cout << "main: result is ready" << std::endl;
    32. }
    33. }

    输出

    特化 std::swap 算法

    std::swap(std::packaged_task)
    1. template< class Function, class... Args >
    2. void swap( packaged_task<Function(Args...)> &lhs,
    3. packaged_task<Function(Args...)> &rhs ) noexcept; (C++11 起)

               packaged_task &rhs ) noexcept;

    (C++11 起)

    为 std::packaged_task 特化 std::swap 算法。交换 lhsrhs 的状态。等效地调用 lhs.swap(rhs) 。

    参数

    lhs, rhs-要交换状态的 packaged_task

    返回值

    (无)

    调用示例

    1. #include <iostream>
    2. #include <cmath>
    3. #include <thread>
    4. #include <future>
    5. #include <functional>
    6. // 避免对 std::pow 重载集消歧义的独有函数
    7. int f(int x, int y)
    8. {
    9. return std::pow(x, y);
    10. }
    11. void task_lambda()
    12. {
    13. std::packaged_task<int(int, int)> task([](int a, int b)
    14. {
    15. return std::pow(a, b);
    16. });
    17. std::future<int> result = task.get_future();
    18. task(2, 9);
    19. std::cout << "task_lambda:\t" << result.get() << '\n';
    20. }
    21. void task_bind()
    22. {
    23. std::packaged_task<int()> task(std::bind(f, 2, 11));
    24. std::future<int> result = task.get_future();
    25. task();
    26. std::cout << "task_bind:\t" << result.get() << '\n';
    27. }
    28. void task_thread()
    29. {
    30. std::packaged_task<int(int, int)> task(f);
    31. std::future<int> result = task.get_future();
    32. std::thread task_td(std::move(task), 2, 10);
    33. task_td.join();
    34. std::cout << "task_thread:\t" << result.get() << '\n';
    35. }
    36. int main()
    37. {
    38. task_lambda();
    39. task_bind();
    40. task_thread();
    41. }

    输出

     

  • 相关阅读:
    【vue3】01. 跟着官网学习vue3
    命名空间和作用域
    云服务器配置Code-Server环境并运行Python和C++
    (2021,中文,双向生成,端到端,双向稀疏注意力)ERNIE-ViLG:双向视觉语言生成的统一生成预训练
    RAW图像详解及使用Python读取raw格式图像并显示
    Apache Paimon系列之:Append Table和Append Queue
    FlashMeeting(基于FFmpeg+openCV)视频语音通讯系统
    学生HTML静态网页基础水平制作DIV+CSS+JavaScript技术制作美食网页——美食城6页面
    SpringAOP的概述与实现
    C++基础与深度解析 | 输入与输出 | 文件与内存操作 | 流的状态、定位与同步
  • 原文地址:https://blog.csdn.net/qq_40788199/article/details/126670996