Namespaces
Variants

Execution control library (since C++26)

From cppreference.net

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

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

目录

库级定义

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

库工具

概念

调度器

定义于头文件 <execution>
定义于命名空间 std::execution
指定类型为调度器
(概念)

Senders

定义于头文件 <execution>
定义于命名空间 std::execution
规定类型为发送器
(概念)
规定可为给定关联环境类型创建异步操作的发送器
(概念)
规定可与特定接收器类型连接的发送器
(概念)

接收器

定义于头文件 <execution>
定义于命名空间 std::execution
规定类型为接收器
(概念)
规定类型为给定完成签名对应的接收器
(概念)

操作状态

定义于头文件 <execution>
定义于命名空间 std::execution
规定类型为操作状态
(概念)

实用工具组件

执行上下文

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

执行域

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

前向进度保证

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

执行环境

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

查询

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

完成签名

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

协程工具

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

核心操作

操作状态

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

完成函数

这些函数由发送方调用,用于向接收方宣告工作已完成。

定义于头文件 <execution>
定义于命名空间 std::execution
指示成功完成的值完成函数
(定制点对象)
指示在计算或调度期间发生错误的错误完成函数
(定制点对象)
指示操作在达成成功或失败前已结束的停止完成函数
(定制点对象)

发送器算法

发送器工厂

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

以下是发送器工厂:

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

可管道化发送器适配器

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

发送器适配器

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

以下是发送方适配器:

定义于头文件 <execution>
定义于命名空间 std::execution
将提供的发送器适配为将在指定调度器的执行资源上启动执行的发送器
(定制点对象)
将提供的发送器适配为在指定调度器的执行资源上完成的发送器
(定制点对象)
将提供的发送器适配为在指定调度器的执行资源上运行发送器或延续,然后将执行转回原始资源
(定制点对象)
将依赖于指定发送器完成的工作调度到指定调度器的执行资源上
(定制点对象)
通过输入发送器链接任务图,其中节点表示使用输入发送器发送的值作为参数调用提供的函数
(定制点对象)
通过输入发送器链接任务图,其中节点表示在发生错误时使用输入发送器发送的错误调用提供的函数
(定制点对象)
通过输入发送器链接任务图,其中节点表示在发送"停止"信号时使用输入发送器的停止行为调用提供的函数
(定制点对象)
返回一个表示链接到输入发送器的节点的发送器,启动时使用输入发送器发送的值作为参数调用提供的函数
(定制点对象)
返回一个表示链接到输入发送器的节点的发送器,在发生错误时使用输入发送器的错误调用提供的函数
(定制点对象)
返回一个表示链接到输入发送器的节点的发送器,在发送"停止"信号时使用输入发送器的停止令牌调用提供的函数
(定制点对象)
创建一个多次触发的发送器,使用指定形状中的每个索引以及输入发送器发送的值调用函数。当所有调用完成或发生错误时,发送器完成
(定制点对象)
如果提供的发送器是多次触发的发送器,则返回该发送器,否则返回一个多次触发的发送器,其发送的值等同于提供的发送器发送的值
(定制点对象)
将多个输入发送器适配为一个在所有输入发送器都完成后完成的发送器
(定制点对象)
将多个可能具有多个完成签名的输入发送器适配为一个在所有输入发送器都完成后完成的发送器
(定制点对象)
返回一个发送器,其发送输入发送器所有可能类型集合的元组变体
(定制点对象)
返回一个将值通道映射到 std:: optional < std:: decay_t < T >> 并将停止通道映射到 std:: nullopt 的发送器
(定制点对象)
<div class="t-d

发送器消费者

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

定义于头文件 <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
(函数模板)