C++11 packaged_task

本文详细介绍了C++11标准中std::packaged_task类模板的使用方法及特性,包括定义、成员函数、如何获取future对象以及执行函数等核心内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 packaged_task
  • 前文 C++11 async 可知,异步操作的方式之一是:std::async + std::future 。
  • 前文 C++11 promise 可知,获取 std::thread 异步执行结果的方法之一是:std::promise + std::future。
  • 将任务异步执行 + 结果获取的方法之一则是本文的 std::packaged_task + std::future。
  • 类模板 std::packaged_task 包装任何可调用 (Callable) 目标(函数、 lambda 表达式、 bind 表达式或其他函数对象),使得能异步调用它。其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中。
二 定义
// 头文件 <future>
template< class > class packaged_task; (1)(C++11)
template< class R, class ...Args >
class packaged_task<R(Args...)>; (2)(C++11)
三 成员函数
  1. 构造

    packaged_task() noexcept; (1)	(C++11) 
    template <class F>
    explicit packaged_task( F&& f ); (2)(C++11)
    template <class F, class Allocator>
    explicit packaged_task( std::allocator_arg_t, const Allocator& a, F&& f ); (3)(C++11)(C++17)
    packaged_task( const packaged_task& ) = delete; (4)(C++11) 
    packaged_task( packaged_task&& rhs ) noexcept; (5)(C++11)
    
  • 复制构造函数被删除, std::packaged_task 仅可移动。
  1. 析构

    ~packaged_task();
    
  • 抛弃共享状态并销毁存储的任务对象。
  • 同 std::promise::~promise ,若在令共享状态就绪前抛弃它,则存储以 std::future_errc::broken_promise 为 error_code 的 std::future_error 异常。
  1. operator=

    packaged_task& operator=( const packaged_task& ) = delete; (1)(C++11)
    packaged_task& operator=( packaged_task&& rhs ) noexcept; (2)(C++11)
    
  • 不可复制赋值
  1. valid

    bool valid() const noexcept; (C++11)
    
  • 检查任务对象是否拥有合法函数。
  1. swap

    void swap( packaged_task& other ) noexcept; (C++11)
    
  • 交换 两个任务对象的共享状态和存储的任务。
四 get_future
std::future<R> get_future(); (C++11)

get_future 对每个 packaged_task 只能调用一次

五 执行函数
1. operator()
  • 设置结果为指定值, 并使状态就绪。
    void operator()( ArgTypes... args );(C++11)
    
  • 以 args 为参数调用存储的任务。任务返回值或任何抛出的异常被存储于共享状态。令共享状态就绪,并解除阻塞任何等待此操作的线程。
2. make_ready_at_thread_exit
void make_ready_at_thread_exit( ArgTypes... args ); (C++11)
  • 仅在当前线程退出,并销毁所有线程局域存储期对象后,才令共享状态就绪。
3. demo
#include <cmath>
#include <functional>
#include <future>
#include <iostream>
#include <thread>

int f(int x, int y) {
  return std::pow(x, y);
}

void task_lambda() {
  std::packaged_task<int(int, int)> task(
      [](int a, int b) { return std::pow(a, b); });
  std::future<int> result = task.get_future();

  task(2, 9);
  std::cout << "task_lambda:\t" << result.get() << '\n';
}

void task_bind() {
  std::packaged_task<int()> task(std::bind(f, 2, 11));
  std::future<int> result = task.get_future();

  task();
  std::cout << "task_bind:\t" << result.get() << '\n';
}

void task_thread() {
  std::packaged_task<int(int, int)> task(f);
  std::future<int> result = task.get_future();

  std::thread task_td(std::move(task), 2, 10); // thread中执行
  task_td.join();

  std::cout << "task_thread:\t" << result.get() << '\n';
}

int main() {
  {
    std::packaged_task<int(int, int)> task;
    std::cout << std::boolalpha << task.valid() << std::endl;
  }

  task_lambda();
  task_bind();
  task_thread();
}
  • 结果
false
task_lambda:    512
task_bind:      2048
task_thread:    1024
六 reset
void reset(); (C++11)
  • 重置状态,抛弃先前执行的结果。构造共享状态。
  • demo
std::packaged_task<int(int, int)> task(
    [](int a, int b) { return std::pow(a, b); });
std::future<int> result = task.get_future();
task(2, 9);
std::cout << "2^9 = " << result.get() << '\n';

task.reset();
result = task.get_future();
std::thread task_td(std::move(task), 2, 10);
task_td.join();
std::cout << "2^10 = " << result.get() << '\n';
  • 结果
2^9 = 512
2^10 = 1024
七 参考

cppreference-packaged_task

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值