在 C++20 中,我们可以在原子变量上休眠,等待它们的值改变。我们通过使用方法来做到这一点std::atomic::wait
。
不幸的是,虽然wait
已经标准化,但wait_for
并wait_until
没有。这意味着我们不能在超时的原子变量上休眠。
无论如何,在 Windows 上使用WaitOnAddress和 Linux 上的futex系统调用在幕后实现了在原子变量上休眠。
解决上述问题(无法在超时的原子变量上休眠),我可以在 Windows 上传递一个std::atomic
to的内存地址,WaitOnAddress
它会(有点)在没有 UB 的情况下工作,因为函数void*
作为参数获取,并且强制转换std::atomic<type>
为有效void*
在 Linux 上,是否可以std::atomic
与futex
. futex
获取 auint32_t*
或 a int32_t*
(取决于您阅读的手册),并且转换std::atomic<u/int>
为u/int*
UB。另一方面,手册说
uaddr 参数指向 futex 字。 在所有平台上,futex 都是四字节整数,必须在四字节边界上对齐。对 futex 执行的操作在 futex_op 参数中指定;val 是一个值,其意义和目的取决于 futex_op。
提示alignas(4) std::atomic<int>
应该可行,只要类型的大小为 4 字节且对齐为 4,它是哪种整数类型都没有关系。
此外,我已经看到很多地方实现了这种结合 atomics 和 futexes 的技巧,包括boost和TBB。
那么以非 UB 方式在具有超时的原子变量上睡眠的最佳方法是什么?我们是否必须使用操作系统原语实现我们自己的原子类才能正确实现它?
(存在混合原子和条件变量等解决方案,但不是最佳的)