c++ - 在等待 std::condition_variable 时如何处理系统时钟的变化?
问题描述
我正在尝试在 C++11 中实现一些跨平台代码。此代码的一部分使用std::condition_variable实现信号量对象。当我需要对信号量进行定时等待时,我使用wait_until或 wait_for。
我遇到的问题是,在基于 POSIX 的系统上,condition_variable 的标准实现似乎依赖于系统时钟,而不是单调时钟(另请参阅:this issue against the POSIX spec)
这意味着如果系统时钟更改为过去的某个时间,我的条件变量将阻塞的时间比我预期的要长得多。例如,如果我希望我的 condition_variable 在 1 秒后超时,如果有人在等待期间将时钟调回 10 分钟,则 condition_variable 会阻塞 10 分钟 + 1 秒。我已经确认这是 Ubuntu 14.04 LTS 系统上的行为。
我需要依靠这个超时至少有点准确(即,它可能在一定的误差范围内不准确,但如果系统时钟发生变化,仍然需要执行)。看来我需要做的是编写我自己的 condition_variable 版本,它使用 POSIX 函数并使用单调时钟实现相同的接口。
这听起来像是很多工作——而且有点乱。有没有其他方法可以解决这个问题?
解决方案
我遇到了同样的问题。我的一位同事给了我一个提示,让我可以使用某些 C 函数<pthread.h>
,这对我来说效果很好。
例如,我有:
std::mutex m_dataAccessMutex;
std::condition_variable m_dataAvailableCondition;
其标准用法:
std::unique_lock<std::mutex> _(m_dataAccessMutex);
// ...
m_dataAvailableCondition.notify_all();
// ...
m_dataAvailableCondition.wait_for(...);
以上可以用pthread_mutex_t
and代替pthread_cond_t
。优点是您可以将时钟指定为单调的。简要使用示例:
#include <pthread.h>
// Declare the necessary variables
pthread_mutex_t m_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_condattr_t m_attr;
pthread_cond_t m_cond;
// Set clock to monotonic
pthread_condattr_init(&m_attr);
pthread_condattr_setclock(&m_attr, CLOCK_MONOTONIC);
pthread_cond_init(&m_cond, &m_attr);
// Wait on data
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
ts.tv_sec += timout_in_seconds;
pthread_mutex_lock(&m_mutex);
int rc = pthread_cond_timedwait(&m_cond, &m_mutex, &ts);
if (rc != ETIMEDOUT)
; // do things with data
else
; // error: timeout
// ...
pthread_mutex_unlock(&m_mutex); // have to do it manually to unlock
// ...
// Notify the data is ready
pthread_cond_broadcast(&m_cond);
推荐阅读
- php - PHPUnit 我需要拆除“require_once”调用,因为它只为测试覆盖了一个辅助函数
- reactjs - 查询 firebase 节点以获取动态路径的计数
- spring - Spring boot - Application.properties 中的用户定义变量
- android-studio - Android Studio 错误:无法从 'file:/C:/Users/~/gradle/wrapper/' 安装 Gradle 发行版
- html - 图像模糊
- excel - 如何用特定的 Header 和 Number 填充数据?
- python - 遍历列表中的字典
- ios - 如何在 SwiftUI 中访问安全区域大小?
- java - Java - 如何正确获取和添加 cookie 以请求标头?
- geolocation - 如何通过服务器端的 IP 地址估计用户位置?