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