繁体   English   中英

系统时间更改的 wait_until 的 condition_variable 解决方法

[英]condition_variable workaround for wait_until with system time change

我有一个计时器类,它使用std::condition_variable wait_until (我也尝试过wait_for )。 我正在使用std::chrono::steady_clock time来等待未来的特定时间。

这意味着是单调的,但长期以来存在一个问题,即它实际上使用系统时钟,并且在系统时间更改时无法正常工作。

它已按照此处的建议在 libc 中修复: https : //gcc.gnu.org/bugzilla/show_bug.cgi? id =41861

问题是这仍然是新的 ~2019 年,仅在 gcc 版本 10 中可用。我有一些交叉编译器只能达到 gcc 版本 ~8。

我在徘徊是否有办法将此修复程序添加到我的 gcc 版本(我有很多交叉编译器)中? - 但是如果每次更新交叉编译器时都必须重新构建交叉编译器,这可能很难维护。

所以一个更好的问题可能是,在我可以将所有工具升级到 gcc v10 之前,这个问题的解决方案是什么? - 如何让我的计时器抵抗系统时间变化?

更新笔记

  1. 创建一个数据结构,其中包含一个条件变量列表,每个条件变量都有一个受互斥锁保护的使用计数。

  2. 当线程将要阻塞条件变量时,首先获取互斥量并将条件变量添加到列表中(如果它已经在列表中,则增加它的使用计数)。

  3. 在条件变量上完成阻塞后,让线程再次获取保护列表的互斥锁并递减它被阻塞的条件变量的使用计数。 如果使用计数降至零,则从列表中删除条件变量。

  4. 有一个专门的线程来观察系统时钟。 如果检测到时钟跳转,则获取保护条件变量列表的互斥锁并广播每个条件变量。

就是这样。 这解决了问题。

如有必要,您还可以为表中的每个条目添加一个布尔值,并在添加条目时将其设置为 false。 如果时钟观察线程已经广播了条件变量,让它设置 bool 为 true,这样被唤醒的线程就会知道它们为什么被唤醒。

如果您愿意,您可以在创建时将条件变量添加到列表中,并在销毁时将其从列表中删除。 如果时钟跳跃,这将导致广播条件变量没有线程被阻塞,但这是无害的。

以下是一些实施建议:

使用专用线程观看时钟。 一个很容易看的事情是挂钟时间和系统正常运行时间之间的偏移。

要做的一件简单的事情是记录观察到的时间跳跃次数,并在每次感觉到时间跳跃时增加它。 当您等待某个条件时,您可以使用以下逻辑:

  1. 注意时间跳跃的次数。
  2. 在条件上阻止。
  3. 醒来后,重新检查病情。
  4. 如果条件不满足,检查时间跳跃的次数。
  5. 如果 1 和 4 的计数不匹配,则将其作为时间跳转唤醒处理。

你可以把这一切都包装起来,这样调用代码中就没有丑陋了。 它只是成为您的wait_for版本的另一个可能的返回值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM