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

c++26新功能——std::execution

一、异步编程

不管什么语言的开发者,大家都知道,异步编程的难度是相当高的。那么到底有多高呢?对于一些天然支持异步操作的语文或库(框架等)来说,能够用好本身就是一个比较复杂的情况。在前面也分析过,异步编程涉及到编程的思想的变化和设计框架的不同。它不仅仅是一个简单的同步变异步的过程,这也是人们常说的思想不过关,早晚出问题的一个实例。
更何况C++这种天然不支持异步编程的语言,想到实现异步编程,就必须手动从头搞一搞。多线程尚且让大多数程序员在头痛,如果再加上异步,估计头就不会只是痛了,可能直接就要爆掉了。
虽然在C++11后提供了一些基础的异步编程的接口或库,但它太简单了,应用上也并不普及,对异步编程(如std::async)也只是涉及到了很浅显的部分。

二、std::execution

早就传说异步执行库要加入新的C++标准,但这个加入的过程可谓道阻且长,但在C++26中,基本定了下来。std::execution,执行控制库提供了在通用资源上执行异步任务的框架。
不过这个库目前应该是还没真正完善,只提供了一些简单、基础的方式来构建任务执行图。开发者基本都知道,异步大多数情况是用线程(复杂就是线程池甚至并行库)实现的,协程出现后可能会使用协程实现,所以稍微复杂的异步执行可以理解为任务的图构建执行的过程。
看一下具体的定义:
1、Sender: A description of asynchronous work to be sent for execution. Produces an operation state (below).
Senders asynchronously “send” their results to listeners called “receivers” (below).
Senders can be composed into task graphs using generic algorithms.
Sender factories and adaptors are generic algorithms that capture common async patterns in objects satisfying the sender concept.
2、Receiver: A generalized callback that consumes or “receives” the asynchronous results produced by a sender.
Receivers have three different “channels” through which a sender may propagate results: success, failure, and canceled, so-named “value”, “error”, and “stopped”.
Receivers provide an extensible execution environment: a set of key/value pairs that the consumer can use to parameterize the asynchronous operation.
3、Operation State: An object that contains the state needed by the asynchronous operation.
A sender and receiver are connected when passed to the std::execution::connect function.
The result of connecting a sender and a receiver is an operation state.
Work is not enqueued for execution until “start” is called on an operation state.
Once started, the operation state’s lifetime cannot end before the async operation is complete, and its address must be stable.
4、Scheduler: A lightweight handle to an execution context.
An execution context is a source of asynchronous execution such as a thread pool or a GPU stream.
A scheduler is a factory for a sender that completes its receiver from a thread of execution owned by the execution context.
其实学习过一些任务图编程或并行编程(如前面的TBB等),就会明白,所谓的线程任务图执行,其实涉及到任务的制定分配、任务的执行、当前的任务状态和任务的调度以及任务执行结果。而这其中任务的执行一般会被底层框架和机器(CPU或GPU执行),开发者能看到的基本就是任务的制定分配(上面的Sender),任务的执行结果(Receiver),任务的状态(Operation State)以及任务调度器(Scheduler)。
相信亲自手写过线程池的人都会非常熟悉这种编程方式(初次接触的需要认真思考一下)。那么此时再回头看上面的英文,应该就比较清楚了。
上面的英文描述也写得很清楚,利用到了回调函数、线程池和任务队列(图),还是那句话,如果有相关的线程池或异步编程的经验,理解和学习std::execution应该没有什么困难。

三、相关的支持

在C++26中,开发者可以看说明中是有点(Point和Node)这个名词的,但目前没有更详细的说明,可能最终的版本仍然未完全确定,所以还不敢写到文档中。有兴趣且英文不错的可以翻翻一下相关的技术草案(https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html)。
特别是execution::schedule隐约可以看到TBB中节点连接的味道,只要是异步大约就会和图搞到一起,而节点间的控制就是一个首要的问题。更具体的一些细节,参看上述的草案地址。

四、代码示例

看一下简单的代码说明:

#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;
}

还有一个草案上的代码:

using namespace std::execution;scheduler auto sch = thread_pool.scheduler();                                 // 1sender auto begin = schedule(sch);                                            // 2
sender auto hi = then(begin, []{                                              // 3std::cout << "Hello world! Have an int.";                                 // 3return 13;                                                                // 3
});                                                                           // 3
sender auto add_42 = then(hi, [](int arg) { return arg + 42; });              // 4auto [i] = this_thread::sync_wait(add_42).value();                            // 5

代码很简单,对照着上面的说明,会很容易理解代码本身及上面的英文说明。当然,这涉及到一些jthread的相关技术,如果没接触过的,可以看看,或者简单理解为安全线程即可。

五、总结

本文是对c++26中的std::execution库的一个入门的分析介绍,目前支持其的平台或编译器尚且在进行中,所以大家可以找到一些编译器尝鲜试试。在翻看一些国外的网站时,发现有的公司已经在生产中使用这个库了。国内的开发者,还要努力跟进啊。

http://www.xdnf.cn/news/247105.html

相关文章:

  • 加密算法(一)-对称加密(DES、AES、3DES、Blowfish、Twofish)一篇了解所有主流对称加密,轻松上手使用。
  • mysql-窗口函数一
  • 链表系列一>合并 k 个升序链表
  • 【CV数据集】DIOR遥感目标检测数据集(含处理好的YOLO、COCO、VOC格式和相关配置文件下载链接)
  • 响应式布局,在飞帆平台中如此简单
  • 文件包含漏洞学习
  • PostgreSQL:pgAdmin 4 使用教程
  • 手撕哈希表
  • Android 移动开发:ProgressBar (水平进度条)
  • 【LeetCode Hot100】回溯篇
  • cua: 为 AI 智能体提供高性能虚拟环境
  • GTA5(传承/增强) 13980+真车 超跑 大型载具MOD整合包+最新GTA6大型地图MOD 5月最新更新
  • PyTorch 2.0编译器技术深度解析:如何自动生成高性能CUDA代码
  • 【Bootstrap V4系列】学习入门教程之 页面内容排版
  • 图像加密算法概述
  • Elsevier latex报错Paragraph ended before \@citex was complete.<to be read again>
  • Vue3 + OpenLayers 企业级应用进阶
  • Linux 第六讲 --- 工具篇(一)yum/apt与vim
  • 哈希表笔记(四)Redis对比Java总结
  • YOLOv8模型训练过程
  • Python与MySQL高效集成指南:从基础到高级实践
  • Hibernate与MybatisPlus的混用问题(Invalid bound statement (not found))
  • (C题|社交媒体平台用户分析问题)2025年第二十二届五一数学建模竞赛(五一杯/五一赛)解题思路|完整代码论文集合
  • 恒流源电路
  • RAG工程-基于LangChain 实现 Advanced RAG(预检索-查询优化)(下)
  • 前端HTML基础知识
  • 【大模型面试每日一题】Day 5:GQA vs MHA效率对比
  • CV中常用Backbone-2:ConvNeXt模型详解
  • 微软推出数款Phi 4“开放式”人工智能模型
  • VB.net序列化和反序列化的使用方法和实用场景