当前位置: 首页 > news >正文

C++ 异步编程中:future与promise、packaged_task、async

原文链接:C++ 异步编程之future与promise、async、packaged_task_std::promise和std::future异步发送-CSDN博客

1、std::future
std::future类模板来关联线程运行的函数和函数的返回结果,这种获取结果的方式是异步的

std::future 通常由某个 Provider 创建,你可以把 Provider 想象成一个异步任务的提供者,
Provider 在某个线程中设置共享状态的值,与该共享状态相关联的 std::future 对象调用 get(通常在另外一个线程中) 获取该值,
如果共享状态的标志不为 ready,则调用 std::future::get 会阻塞当前的调用者,直到 Provider 设置了共享状态的值(此时共享状态的标志变为 ready),
std::future::get 返回异步任务的值或异常(如果发生了异常)。

2、std::promise
std::promise类型模板提供“设置异步结果”的方法,
这样其他线程就可以通过std::future实例来“读取”该结果。
std::promise和std::future合作共同实现了多线程间通信。

通过调用std::promise的get_future函数,可以将该共享状态与std::future对象关联。
调用get_future之后,两个对象共享相同的共享状态:
std::promise对象是异步提供程序(asynchronous provider),应在某个时刻为共享状态设置一个值。
std::future对象是个异步返回对象,可以检索共享状态的值,并在必要时等待其准备就绪。
 需要注意的是:set_value只能被调用一次,多次调用会抛出std::future_error异常。
事实上std::promise::set_xxx函数会改变std::promise的状态为ready,
再次调用时发现状态已是reday了,则抛出异常。


3、std::packaged_task
std::packaged_task是一个模板类,它允许传入一个函数或其他可调用对象,
并将函数计算的结果作为异步结果传递给std::future,包括函数运行时产生的异常。

4、c++11提供了异步接口std::async
c++11提供了异步接口std::async,通过这个异步接口可以很方便的获取线程函数的执行结果。
std::async会自动创建一个线程去调用线程函数,它返回一个std::future,这个future中存储了线程函数返回的结果

当有线程调用了这个future对象的wait()和get()成员函数,则该任务会同步运行;

std::async是一个函数而非类模板,其函数执行完后的返回值绑定给std::futrue对象;
async(launch policy, Callable&& func, Args&& ... args);
std::launch policy是启动策略,它控制std::async的异步行为,
我们可以用“3种不同的启动策略”来创建std::async:
    std::launch::async参数:保证异步行为,即传递函数将在单独的线程中执行;
    std::launch::deferred参数:当其他线程调用get()/wait()来访问共享状态时,将调用非异步行为;
    std::launch::async | std::launch::deferred参数:是默认行为(可省略)。有了这个启动策略,它可以异步运行或不运行,这取决于系统的负载。

std::async允许通过添加额外的调用参数,向函数传递额外的参数。
第一个参数是指向成员函数的指针,
第二个参数提供这个函数成员类的具体对象(是通过指针,也可以包装在std::ref中),剩余的参数可作为函数的参数传入。
    否则,第二个和随后的参数将作为函数的参数,或作为指定可调用对象的第一个参数。
auto f1= std::async(&X::foo,&x, 42, "hello");  // 调用p->foo(42, "hello"),p是指向x的指针
auto f2= std::async(&X::bar, x, "goodbye");  // 调用tmpx.bar("goodbye"), tmpx是x的拷贝副本
std::async 的返回值(std::future)在析构函数里会等待任务完成;
    
std::async意义:
    在已经有了td::future、std::promise和std::packaged_task的情况下,实现异步或多线程间通信,
可能觉得已经足够了,真的还要一个std::async来凑热闹吗??
=》
是std::async是为了让用户的少费点脑子的,它让这三个对象默契的工作。
大概的工作过程是这样的:std::async先将异步操作用std::packaged_task包装起来,
然后将异步操作的结果放到std::promise中,这个过程就是创造未来的过程。
外面再通过future.get/wait来获取这个未来的结果。
=》std::async真的是来帮忙的,你不用再想到底该怎么用std::future、std::promise和 std::packaged_task了,
std::async已经帮你搞定一切了!这就是我们前面说的,std::async类似封装了thread和packged_task的功能。
使得我们使用起来更加方便简单。


http://www.mrgr.cn/news/34276.html

相关文章:

  • 二叉树(C 语言)
  • 导游基础知识丨各民族民俗知识节选
  • 【月之暗面kimi-注册/登录安全分析报告】
  • Javaweb—Ajax与jQuery请求
  • 【计算机网络】TCP网络程序
  • LabVIEW大数据处理
  • Android对象池的深入理解和使用
  • gif怎么压缩变小一点?6种方法你快速压缩gif
  • 一文读懂HPA弹性扩展自定义指标和缩放策略
  • 【数据结构-栈】力扣844. 比较含退格的字符串
  • 更新gitignore后如何使其生效
  • 如何高效绘制ER图?
  • 2024.09.14 校招 实习 内推 面经
  • 稳定为恒定功率负载供电的 DC/DC 转换器
  • 海外博主大力推荐 Navicat Premium Lite 免费版
  • 【每天学个新注解】Day 3 Lombok注解简解(二)—@Log
  • Redis简单介绍与安装应用
  • NEMESIS: NORMALIZING THE SOFT-PROMPT VECTORS OF VISION-LANGUAGE MODELS
  • 如何在CentOS 7上升级KVM内核?
  • Fragment两种切换方式
  • 1. IP地址介绍
  • 2024年信息安全企业CRM选型与应用研究报告
  • 辛普森积分公式
  • CCPQT:2024年10月珠海学术会议
  • C#常用数据结构栈的介绍
  • 编译uboot出现 multiple definition of `yylloc‘ 问题