执行库 (自 C++26 起)
来自 cppreference.com
< cpp
执行库提供了一个框架,用于管理异步执行在通用执行资源上的执行。
该库旨在为异步操作提供词汇类型,并允许以简单且可组合的方式构建任务执行图。
内容 |
[编辑] 库范围定义
- 发送器:异步工作的描述,要发送到执行。生成操作状态(如下)。
- 发送器异步地“发送”他们的结果给监听器,称为“接收器”(如下)。
- 发送器可以使用通用算法组合成任务图。
- 发送器工厂和适配器是通用算法,它们捕获满足发送器概念的对象中的常见异步模式。
- 接收器:一个广义的回调,它消费或“接收”由发送器生成的异步结果。
- 接收器有三个不同的“通道”,发送器可以通过它们传播结果:成功、失败和取消,分别称为“值”、“错误”和“停止”。
- 接收器提供了一个可扩展的执行环境:一组键值对,消费者可以使用它来参数化异步操作。
- 操作状态:一个包含异步操作所需的运行时状态的对象。
- 当发送器和接收器传递给std::execution::connect 函数时,它们就被连接了。
- 连接发送器和接收器的结果是一个操作状态。
- 在对操作状态调用“
开始
”之前,工作不会排队执行。 - 一旦开始,操作状态的生命周期就不能在异步操作完成之前结束,并且它的地址必须是稳定的。
- 调度器:一个轻量级句柄,指向一个执行上下文。
- 执行上下文是一个异步执行的来源,例如一个线程池或一个 GPU 流。
- 调度器是发送器的工厂,它从执行上下文拥有的执行线程完成其接收器。
[编辑] 库实用程序
[编辑] 概念
[编辑] 调度器
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
指定一个类型是一个调度器 (概念) |
[编辑] 发送器
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
指定一个类型是一个发送器 (概念) |
(C++26) |
指定一个发送器,它可以为给定的关联环境类型创建异步操作 (概念) |
(C++26) |
指定一个发送器,它可以与特定的接收器类型连接 (概念) |
[编辑] 接收器
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
指定一个类型是一个接收器 (概念) |
(C++26) |
指定一个类型是给定完成签名的接收器 (概念) |
[编辑] 操作状态
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
指定一个类型是一个操作状态 (概念) |
[编辑] 实用程序组件
[编辑] 执行上下文
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
执行资源,它保存一个线程安全的 MPSC 任务队列和一个手动驱动的事件循环 (类) |
[编辑] 执行域
本节不完整 原因:正在进行中更新到当前标准 |
[编辑] 向前进度保证
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
指定调度器的关联执行资源创建的执行代理的向前进度保证 (枚举) |
[编辑] 环境
本节不完整 原因:正在进行中更新到当前标准 |
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
默认环境类型,其中没有查询对象可以询问其值 (类) |
(C++26) |
返回其给定参数的关联可查询对象 (定制点对象) |
[编辑] 查询
定义在头文件
<execution> 中 | |
(C++26) |
询问查询对象是否应该通过可查询适配器转发 (定制点对象) |
(C++26) |
询问可查询对象与其关联的分配器 (定制点对象) |
(C++26) |
询问可查询对象与其关联的停止令牌 (定制点对象) |
(C++26) |
询问可查询对象与其关联的执行域标签 (定制点对象) |
(C++26) |
询问可查询对象与其关联的调度器 (定制点对象) |
询问可查询对象一个调度器,该调度器可用于委托工作以进行转发进度委托 (定制点对象) | |
从发送者的属性中获取与完成标记关联的完成调度器 (定制点对象) | |
询问调度器关于其 execution::forward_progress_guarantee (定制点对象) |
[编辑] 完成签名
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
编码一组完成签名的类型 (类模板) | |
获取发送者的完成签名 (定制点对象) | |
将一组完成签名转换为另一组 (别名模板) | |
转换发送者的完成签名 (别名模板) | |
(C++26) |
获取发送者的标签类型 (别名模板) |
(C++26) |
获取发送者的值完成类型 (别名模板) |
(C++26) |
获取发送者的错误完成类型 (别名模板) |
(C++26) |
确定发送者是否支持停止完成 (变量模板) |
[编辑] 协程实用程序
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
将表达式转换为特定协程中的可等待对象 (定制点对象) |
当用作协程承诺类型基类时,使发送者在该协程类型中可等待 (类模板) |
[编辑] 核心操作
[编辑] 操作状态
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
将 sender 与 receiver 连接起来(定制点对象) |
(C++26) |
启动与 operation_state 对象关联的异步操作(定制点对象) |
[编辑] 完成函数
这些函数由发送者调用,以向接收者宣布工作的完成。
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
值完成函数,指示成功完成 (定制点对象) |
(C++26) |
错误完成函数,指示计算或调度期间发生错误 (定制点对象) |
(C++26) |
停止完成函数,指示操作在能够实现成功或失败之前结束 (定制点对象) |
[编辑] 发送者算法
本节不完整 原因:正在进行中更新到当前标准 |
[编辑] 发送者工厂
发送者工厂是一个返回发送者的函数,其参数具有类型,这些类型对于 sender
概念 false.
以下是发送者工厂
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
接受可变数量的参数,并返回一个发送者,当连接并启动时,通过将参数传递给接收者的值完成函数来同步完成 (定制点对象) |
(C++26) |
接受一个参数,并返回一个发送者,当连接并启动时,通过将参数传递给接收者的错误完成函数来同步完成 (定制点对象) |
(C++26) |
创建一个发送者,通过调用其接收者的 set_stopped 立即完成(定制点对象) |
(C++26) |
创建一个发送者,查询其接收者关联的环境 (定制点对象) |
(C++26) |
准备一个任务图,以便在给定的调度器上执行 (定制点对象) |
[编辑] 可管道发送者适配器
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
定义可管道发送者适配器闭包对象的辅助基本类模板 (类模板) |
[编辑] 发送者适配器
发送者适配器是一个返回发送者的函数,其参数包括至少一个类型满足 sender
概念的参数,并且对于返回的发送者,它是适配器函数的发送者参数的父发送者。
以下是发送者适配器
定义在头文件
<execution> 中 | |
定义在命名空间
std::execution 中 | |
(C++26) |
TODO (定制点对象) |
(C++26) |
TODO (定制点对象) |
(C++26) |
在与提供的调度器关联的执行资源所属的执行代理上启动提供的发送器 (定制点对象) |
(C++26) |
TODO (定制点对象) |
(C++26) |
通过输入发送器将任务图链接起来,其中一个节点表示使用输入发送器发送的值作为参数调用提供的函数 (定制点对象) |
(C++26) |
通过输入发送器将任务图链接起来,其中一个节点表示如果发生错误,使用输入发送器发送的错误调用提供的函数 (定制点对象) |
(C++26) |
通过输入发送器将任务图链接起来,其中一个节点表示如果发送“停止”信号,使用输入发送器发送的停止行为调用提供的函数 (定制点对象) |
(C++26) |
返回一个发送器,它表示链接到输入发送器的节点,该节点在启动时使用输入发送器发送的值作为参数调用提供的函数 (定制点对象) |
(C++26) |
返回一个发送器,它表示链接到输入发送器的节点,该节点使用来自输入发送器的错误(如果发生)调用提供的函数 (定制点对象) |
(C++26) |
返回一个发送器,它表示链接到输入发送器的节点,该节点使用来自输入发送器的停止令牌(如果发送了“停止”信号)调用提供的函数 (定制点对象) |
(C++26) |
创建一个多发发送器,使用提供的形状中的每个索引以及输入发送器发送的值来调用该函数。一旦所有调用完成或发生错误,发送器就完成 (定制点对象) |
(C++26) |
如果提供的发送器是多发发送器,则返回该发送器,否则返回一个多发发送器,该发送器发送的值等同于提供的发送器发送的值 (定制点对象) |
(C++26) |
一旦所有输入发送器都完成,就完成 (定制点对象) |
TODO (定制点对象) | |
(C++26) |
返回一个发送器,它发送所有可能的类型集的元组的变体,这些类型集由输入发送器发送 (定制点对象) |
返回一个发送器,它将值通道映射到 std::optional<std::decay_t<T>>,将停止通道映射到 std::nullopt (定制点对象) | |
(C++26) |
返回一个发送器,它将停止通道映射到错误 (定制点对象) |
[编辑] 发送器消费者
发送器消费者是一种算法,它接受一个或多个发送器作为参数,并且不返回发送器。
定义在头文件
<execution> 中 | |
在命名空间
std::this_thread 中定义 | |
(C++26) |
阻塞当前线程,直到指定的发送器完成并返回其异步结果 (定制点对象) |
阻塞当前线程,直到指定的发送器(可能具有多个完成签名)完成并返回其异步结果 (定制点对象) |
[编辑] 例子
该例子的一个版本可在 godbolt.org 上获得,它使用 stdexec,一个实验性的 std::execution 参考实现。
运行此代码
#include <cstdio> #include <execution> #include <string> #include <thread> #include <utility> using namespace std::literals; int main() { std::execution::run_loop loop; std::jthread worker([&](std::stop_token st) { std::stop_callback cb{st, [&]{ loop.finish(); }}; loop.run(); }); std::execution::sender auto hello = std::execution::just("hello world"s); std::execution::sender auto print = std::move(hello) | std::execution::then([](std::string msg) { return std::puts(msg.c_str()); }); std::execution::scheduler auto io_thread = loop.get_scheduler(); std::execution::sender auto work = std::execution::on(io_thread, std::move(print)); auto [result] = std::this_thread::sync_wait(std::move(work)).value(); return result; }
输出
hello world
[编辑] 另请参阅
(C++11) |
异步运行一个函数(可能在新线程中),并返回一个将保存结果的 std::future (函数模板) |