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

标签 c++ linux gcc condition-variable

我有一个使用 std::condition_variable 的计时器类wait_until (我也试过 wait_for )。我正在使用 std::chrono::steady_clock time等到 future 的特定时间。
这意味着是单调的,但这是一个长期存在的问题,它实际上使用系统时钟并且在系统时间更改时无法正常工作。
它已按照此处的建议在 libc 中修复:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41861 .
问题是这仍然很新~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
  • 最佳答案

  • 创建一个数据结构,其中包含一个条件变量列表,每个条件变量都有一个受互斥体保护的使用计数。
  • 当线程即将阻塞条件变量时,首先获取互斥锁并将条件变量添加到列表中(如果它已经在列表中,则增加其使用计数)。
  • 在条件变量上完成阻塞后,让线程再次获取保护列表的互斥锁并减少它被阻塞的条件变量的使用计数。如果条件变量的使用计数降至零,则从列表中删除条件变量。
  • 有一个专门的线程来观察系统时钟。如果它检测到时钟跳跃,则获取保护条件变量列表的互斥锁并广播每个条件变量。

  • 就是这样。这样就解决了问题。
    如有必要,您还可以为表中的每个条目添加一个 bool 值,并在添加条目时将其设置为 false。如果时钟观察线程已经广播了条件变量,让它将 bool 设置为 true,这样被唤醒的线程就会知道它们被唤醒的原因。
    如果您愿意,您可以在创建条件变量时将其添加到列表中,并在销毁时将其从列表中删除。如果时钟跳跃,这将导致广播条件变量没有线程被阻塞,但这是无害的。
    以下是一些实现建议:
    使用专用线程查看时钟。一个容易看的事情是墙上时间和系统正常运行时间之间的偏移量。
    要做的一件简单的事情是记录观察到的时间跳跃次数,并在每次感觉到时间跳跃时增加它。等待条件时,可以使用以下逻辑:
  • 注意时间跳跃的次数。
  • 封锁条件。
  • 当你醒来时,重新检查情况。
  • 如果条件不满足,检查时间跳跃的次数。
  • 如果 1 和 4 的计数不匹配,则将其作为时间跳转唤醒处理。

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

    关于c++ - 系统时间更改时 wait_until 的 condition_variable 解决方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63631963/

    相关文章:

    c++ - 是否有可能以编程方式确定哪个更快;使用余数运算符或条件?

    c# - 以 root 身份运行时以用户身份启动外部进程

    Linux 内核 'make rpm-pkg' 抛出错误

    编译器认为 struct 是指向 struct 的指针

    c++ - 为什么必须为存储在堆中的函数的局部变量调用 delete?

    c++ - 一起使用 C++ 和脚本

    c++ - Windows 上的 Boost::Asio 不能异步工作

    linux - 如何使用 awk 工具对齐 csv 文件中的列

    c++ - Eclipse - 启动命令 : gdb --version 时出错

    gcc - 使用 GCC 进行循环版本控制