Skip to content

C++ 完整 SPSC 实践:固定载荷、回绕与双线程测试 · SPSC示例怎样构建且区分预期与执行至一手资料与验证边界 ​

返回分篇目录

本系列以前置值语义、RAII、基本线程/函数接口为基础。示例未执行;本轮仅完成静态文本与模板核对,不将预期输出称为实际运行结果。

专题入口:C++ SPSC 模型:有界环、角色与槽位生存期 · C++ SPSC 内存序:发布消息与归还槽位 · C++ 完整 SPSC 实践:固定载荷、回绕与双线程测试 · C++ SPSC 排错:数据竞争、角色越界与退出协议

SPSC示例怎样构建且区分预期与执行 ​

SPSC示例怎样构建且区分预期与执行:README 给出 CMake 配置、构建、CTest 与演示命令,Windows 原生和 Linux/macOS 可执行文件后缀分别说明。本轮未执行配置、编译、测试、线程程序或竞态工具,只允许源文件与正文的静态核对。

读者后续应记录编译器/标准库是否支持 C++20 jthread、目标架构、原子运行库、构建类型以及每步退出码。若平台要求额外的原子支持库,需根据真实链接诊断处理;本例不把某工具链的 -latomic 或 -pthread 当三平台通用常量。Threads::Threads 的作用和索引原子是否无锁是两个问题。

使用 Release 时测试仍保留显式判断,没有 assert 被 NDEBUG 移除的假通过。TSan 必须用独立目录和支持的工具链同时启用编译/链接选项;本轮没有执行此操作或安装任何运行库。

SPSC测试怎样覆盖空满回绕和有序压力 ​

SPSC测试怎样覆盖空满回绕和有序压力:先用 SpscRing<2> 验证空时输出不变、单个可用槽、拒绝第二次push;再用4槽循环1000轮验证多次过零与每次拒绝满写;最后用17槽双线程传输100000值,逐项检查接收顺序并在 join 后确认排空。

前三类边界结果可确定,压力测试的调度不可确定;它是补充实现证据,不能替代内存序证明。17个物理槽用于排除“必须2次幂”的隐含假设。期限只用于终止异常等待,不是吞吐基准;超时需区分繁忙环境和代码缺陷。

测试共享 stop 是原子,received 与 ordered 只由消费者线程修改,主线程在 jthread 析构 join 后读取。生产者捕获的 queue/deadline/stop 在收拢前都存活;第二个线程创建失败时已启动生产者仍有期限退出路径。TEST-SPEC 单独列出预期、错误和未运行范围。

演示和测试的main都有异常处理器,线程创建抛错时先向处理器展开栈,销毁已经构造的jthread并join,再诊断并返回1。没有匹配处理器的未捕获异常会触发terminate,标准不保证此前展开栈;因此只写jthread却遗漏入口catch,不能承诺创建失败时完成收拢。参照异常终止规则和jthread规则;滚动草案仅用于核对这些既有规则,不引入新接口。本轮仅静态追踪,未制造线程创建失败。

练习与自检 ​

为什么压力测试不能只检查接收总数为100000?说明当前测试如何发现一个重复值替换了另一个值。

参考答案与判断依据

数量相同不保证内容与顺序,重复某值并漏掉另一值仍可达到相同计数。当前消费者对每个值与received期望序号比较,重复、丢失或乱序都会将ordered设为false;join后主线程汇总结果。测试仍是有限执行证据,内存模型正确性依赖前面的所有权与发布证明。

一手资料与验证边界 ​

2026-10-17核对 WG21 N4861草案、N4861 atomics.order可读镜像、N4861 intro.races可读镜像。固定草案用于说明C++20内存模型;未运行编译器、线程示例、CTest、TSan或性能基准。旧泛型与并发基础保留,与本次逐槽发布证明互补。

继续阅读