如何解决使用系统时间更改的wait_until的condition_variable解决方法
我有一个使用std::condition_variable
wait_until
的计时器类(我也尝试过wait_for
)。我正在使用std::chrono::steady_clock time
等到将来的某个特定时间。
这本来是单调的,但是长期存在一个问题,即它实际上使用系统时钟,并且在更改系统时间时无法正常工作。
它已在https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41861中在libc中修复。
问题在于,这仍然是相当新的〜2019,仅适用于gcc版本10。我有一些交叉编译器仅适用于gcc版本〜8。
我在徘徊是否有办法将此修补程序移植到我的gcc版本(我有很多交叉编译器)中? -但是如果每次更新交叉编译器之类的时候都必须重新构建交叉编译器,则可能难以维护。
一个更好的问题可能是,在我可以将所有工具升级到gcc v10之前,该问题的解决方案是什么? -如何使计时器抵抗系统时间的变化?
更新的笔记
- Rustyx提到所需的glibc版本是2.3.0+(对于我的引用来说,更多-使用
ldd --version
进行检查) - glibc更改日志,其中显示了Daniel Langr提供的修订的相关条目:https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/ChangeLog-2019#L2093
- 所需的glibc补丁程序(由rustyx提供):https://gcc.gnu.org/git/?p=gcc.git&a=commit;h=ad4d1d21ad5c515ba90355d13b14cbb74262edd2
解决方法
-
创建一个数据结构,其中包含条件变量列表,每个条件变量的使用计数受互斥量保护。
-
当线程将要阻塞条件变量时,首先获取互斥锁并将条件变量添加到列表中(或者如果已在列表中,则增加其使用计数)。
-
完成对条件变量的阻塞后,让线程再次获取保护列表的互斥锁,并减少被阻塞的条件变量的使用计数。如果条件变量的使用计数降至零,则将其从列表中删除。
-
具有专用线程来监视系统时钟。如果它检测到时钟跳变,请获取保护条件变量列表的互斥锁,并广播每个条件变量。
就是这样。这样就解决了问题。
如有必要,还可以向表中的每个条目添加一个布尔值,并在添加条目时将其设置为false。如果时钟观察程序线程尚未广播条件变量,请将其设置为true,以便唤醒的线程将知道为什么被唤醒。
如果愿意,您可以在创建条件变量时将其添加到列表中,并在销毁条件变量后将其从列表中删除。这将导致广播条件变量,如果时钟跳变,则不会阻塞任何线程,但这是无害的。
以下是一些实施建议:
使用专用线程观看时钟。容易看的是墙面时间与系统正常运行时间之间的偏差。
要做的一件简单的事情是对观察到的时间跳变次数进行计数,并在每次感觉到时间跳变时对其进行递增。等待条件时,可以使用以下逻辑:
- 注意时间跳跃的次数。
- 阻止该情况。
- 醒来后,请重新检查条件。
- 如果不满足条件,请检查跳跃次数。
- 如果1和4中的计数不匹配,请将其作为时间跳跃唤醒。
您可以将其全部包装起来,以使调用代码中没有丑陋的地方。它只是您的wait_for版本中的另一个可能的返回值。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。