命名空间
变体
操作

执行控制库 (自 C++26 起)

来自 cppreference.cn
< cpp
 
 
 

执行控制库提供了一个框架,用于管理通用执行资源上的异步执行。

该库旨在为异步操作提供词汇类型,并允许以简单、可组合的方式构建任务执行图。

目录

[编辑] 库范围定义

  • 发送器 (Sender):对要发送执行的异步工作的描述。产生一个操作状态(见下)。
  • 发送器异步地将其结果“发送”给称为“接收器”(见下)的监听器。
  • 发送器可以使用通用算法组合成任务图
  • 发送器工厂和适配器是通用算法,它们将常见的异步模式封装在满足 sender 概念的对象中。
  • 接收器 (Receiver):一种通用回调,用于消费或“接收”发送器产生的异步结果。
  • 接收器有三个不同的“通道”,发送器可以通过这些通道传播结果:成功、失败和取消,分别称为“值 (value)”、“错误 (error)”和“停止 (stopped)”。
  • 接收器提供了一个可扩展的执行环境:一组键/值对,消费者可以使用它们来参数化异步操作。
  • 操作状态 (Operation State):一个包含异步操作所需状态的对象。
  • 当发送器和接收器传递给 std::execution::connect 函数时,它们被连接起来。
  • 连接发送器和接收器的结果是一个操作状态。
  • 在操作状态上调用“start”之前,工作不会排队执行。
  • 一旦启动,操作状态的生命周期不能在异步操作完成之前结束,并且其地址必须是稳定的。
  • 调度器 (Scheduler):执行上下文的轻量级句柄。
  • 执行上下文是异步执行的来源,例如线程池或 GPU 流。
  • 调度器是发送器的工厂,该发送器从执行上下文拥有的执行线程完成其接收器。

[编辑] 库工具

[编辑] 概念

[编辑] 调度器

定义于头文件 <execution>
定义于命名空间 std::execution
指定一个类型是调度器
(概念) [编辑]

[编辑] 发送器

定义于头文件 <execution>
定义于命名空间 std::execution
指定一个类型是发送器
(概念) [编辑]
指定一个发送器,它可以为给定的关联环境类型创建异步操作
(概念) [编辑]
指定一个发送器,它可以与特定的接收器类型连接
(概念) [编辑]

[编辑] 接收器

定义于头文件 <execution>
定义于命名空间 std::execution
指定一个类型是接收器
(概念) [编辑]
指定一个类型是给定完成签名的接收器
(概念) [编辑]

[编辑] 操作状态

定义于头文件 <execution>
定义于命名空间 std::execution
指定一个类型是操作状态
(概念) [编辑]

[编辑] 实用组件

[编辑] 执行上下文

定义于头文件 <execution>
定义于命名空间 std::execution
持有线程安全 MPSC 任务队列和手动驱动事件循环的执行资源
(类) [编辑]

[编辑] 执行域

定义于头文件 <execution>
定义于命名空间 std::execution
默认执行域标签类型,从发送器标签分派转换
(类) [编辑]
在给定执行域标签下转换为新的发送器
(函数模板) [编辑]
在给定执行域标签下转换为新的可查询对象
(函数模板) [编辑]
使用给定发送器消费者标签和一组参数消费一个发送器,并在给定执行域标签下返回其结果
(函数模板) [编辑]

[编辑] 前进保证

定义于头文件 <execution>
定义于命名空间 std::execution
指定调度器关联执行资源创建的执行代理的前进保证
(枚举) [编辑]

[编辑] 环境

定义于头文件 <execution>
定义于命名空间 std::execution
(C++26)
从查询对象和值构建一个可查询对象
(类模板) [编辑]
(C++26)
将多个可查询对象聚合成一个可查询对象
(类模板) [编辑]
返回给定参数的关联可查询对象
(定制点对象)[编辑]

[编辑] 查询

定义于头文件 <execution>
询问查询对象是否应通过可查询适配器转发
(定制点对象)[编辑]
(C++26)
询问可查询对象其关联的分配器
(定制点对象)[编辑]
(C++26)
询问可查询对象其关联的停止令牌
(定制点对象)[编辑]
询问可查询对象其关联的执行域标签
(定制点对象)[编辑]
询问可查询对象其关联的调度器
(定制点对象)[编辑]
询问可查询对象一个调度器,该调度器可用于委托工作以实现前进委托
(定制点对象)[编辑]
从发送器的属性中获取与完成标签关联的完成调度器
(定制点对象)[编辑]
询问调度器关于其 execution::forward_progress_guarantee
(定制点对象)[编辑]

[编辑] 完成签名

定义于头文件 <execution>
定义于命名空间 std::execution
编码一组完成签名的类型
(类模板) [编辑]
获取发送器的完成签名
(定制点对象)[编辑]
将一组完成签名转换为另一组
(别名模板)[编辑]
转换发送器的完成签名
(别名模板)[编辑]
获取发送器的标签类型
(别名模板)[编辑]
获取发送器的值完成类型
(别名模板)[编辑]
获取发送器的错误完成类型
(别名模板)[编辑]
确定发送器是否支持停止完成
(变量模板)[编辑]

[编辑] 协程工具

定义于头文件 <execution>
定义于命名空间 std::execution
将表达式转换为特定协程中的可等待对象
(定制点对象)[编辑]
当用作协程承诺类型的基类时,使发送器在该协程类型中可等待
(类模板) [编辑]

[编辑] 核心操作

[编辑] 操作状态

定义于头文件 <execution>
定义于命名空间 std::execution
连接 senderreceiver
(定制点对象)[编辑]
启动与 operation_state 对象关联的异步操作
(定制点对象)[编辑]

[编辑] 完成函数

这些函数由发送器调用,以通知其接收器工作完成。

定义于头文件 <execution>
定义于命名空间 std::execution
值完成函数,表示成功完成
(定制点对象)[编辑]
错误完成函数,表示在计算或调度过程中发生错误
(定制点对象)[编辑]
停止完成函数,表示操作在未能成功或失败之前结束
(定制点对象)[编辑]

[编辑] 发送器算法

[编辑] 发送器工厂

发送器工厂是一个返回发送器,并且其参数类型不满足 sender 概念的函数。

以下是发送器工厂

定义于头文件 <execution>
定义于命名空间 std::execution
(C++26)
接受可变数量的参数,并返回一个发送器,该发送器在连接和启动时,通过将参数传递给接收器的值完成函数而同步完成
(定制点对象)[编辑]
接受单个参数,并返回一个发送器,该发送器在连接和启动时,通过将参数传递给接收器的错误完成函数而同步完成
(定制点对象)[编辑]
创建一个发送器,该发送器通过调用其接收器的 set_stopped 立即完成
(定制点对象)[编辑]
创建一个发送器,该发送器查询其接收器关联的环境
(定制点对象)[编辑]
准备任务图以在给定调度器上执行
(定制点对象)[编辑]

[编辑] 可管道化发送器适配器

定义于头文件 <execution>
定义于命名空间 std::execution
用于定义可管道化发送器适配器闭包对象的辅助基类模板
(类模板) [编辑]

[编辑] 发送器适配器

发送器适配器是一个函数,它返回一个发送器,其参数至少包含一个满足 sender 概念的类型,并且返回的发送器是适配器函数发送器参数的父发送器。

以下是发送器适配器

定义于头文件 <execution>
定义于命名空间 std::execution
将提供的发送器适配成一个将在提供的调度器的执行资源上开始执行的发送器
(定制点对象)[编辑]
将提供的发送器适配成一个将在提供的调度器的执行资源上完成的发送器
(定制点对象)[编辑]
(C++26)
将提供的发送器适配为将执行转移到提供的调度器的执行资源上,发送器或后续操作在此资源上运行,然后将执行转移回原始资源
(定制点对象)[编辑]
调度依赖于所提供的发送器完成的工作到所提供的调度器的执行资源上
(定制点对象)[编辑]
(C++26)
通过输入发送器将任务图与一个节点链接起来,该节点表示使用输入发送器发送的值作为参数调用提供的函数
(定制点对象)[编辑]
通过输入发送器将任务图与一个节点链接起来,该节点表示如果发生错误,则使用输入发送器发送的错误调用提供的函数
(定制点对象)[编辑]
通过输入发送器将任务图与一个节点链接起来,该节点表示如果发送“stopped”信号,则使用输入发送器提供的停止行为调用提供的函数
(定制点对象)[编辑]
返回一个发送器,它表示一个链接到输入发送器的节点,当启动时,它将使用输入发送器发送的值作为参数调用提供的函数
(定制点对象)[编辑]
返回一个发送器,它表示一个链接到输入发送器的节点,如果发生错误,它将使用输入发送器的错误调用提供的函数
(定制点对象)[编辑]
返回一个发送器,它表示一个链接到输入发送器的节点,如果发送“stopped”信号,它将使用输入发送器的停止令牌调用提供的函数
(定制点对象)[编辑]
创建一个多发发送器,它使用提供的形状中的每个索引以及输入发送器发送的值来调用函数。一旦所有调用完成或发生错误,发送器完成
(定制点对象)[编辑]
如果提供的发送器是多发发送器,则返回该发送器;否则,返回一个发送与提供的发送器等效的值的多发发送器
(定制点对象)[编辑]
将多个输入发送器适配成一个发送器,当所有输入发送器都完成时,该发送器完成
(定制点对象)[编辑]
将多个输入发送器(每个可能具有多个完成签名)适配成一个发送器,当所有输入发送器都完成时,该发送器完成
(定制点对象)[编辑]
返回一个发送器,该发送器发送一个由输入发送器可能发送的所有类型集合组成的元组变体
(定制点对象)[编辑]
返回一个发送器,它将值通道映射到 std::optional<std::decay_t<T>>,将停止通道映射到 std::nullopt
(定制点对象)[编辑]
返回一个发送器,它将停止通道映射到错误
(定制点对象)[编辑]

[编辑] 发送器消费者

发送器消费者是一个算法,它接受一个或多个发送器作为参数,并且不返回发送器。

定义于头文件 <execution>
定义于命名空间 std::this_thread
阻塞当前线程直到指定的发送器完成并返回其异步结果
(定制点对象)[编辑]
阻塞当前线程直到指定的发送器(可能具有多个完成签名)完成并返回其异步结果
(定制点对象)[编辑]

[编辑] 示例

此示例的一个版本可在 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
(函数模板) [编辑]