jld*_*eon 14 c++ time condition-variable system-clock c++11
我正在尝试在C++ 11中实现一些跨平台代码.此代码的一部分使用std :: condition_variable实现信号量对象.当我需要在信号量上进行定时等待时,我使用wait_until或wait_for.
我遇到的问题是,似乎基于POSIX的系统上的 condition_variable的标准实现依赖于系统时钟,而不是单调时钟(另请参阅:针对POSIX规范的此问题)
这意味着如果系统时钟在过去的某个时间发生变化,我的条件变量将阻塞的时间比我预期的要长得多.例如,如果我希望我的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;
Run Code Online (Sandbox Code Playgroud)
及其标准用法:
std::unique_lock<std::mutex> _(m_dataAccessMutex);
// ...
m_dataAvailableCondition.notify_all();
// ...
m_dataAvailableCondition.wait_for(...);
Run Code Online (Sandbox Code Playgroud)
上面的内容可以用pthread_mutex_t和来代替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);
Run Code Online (Sandbox Code Playgroud)
在考虑了该问题的可能解决方案之后,似乎最有意义的解决方案是禁止使用std::condition_variable(或者至少明确说明它始终会使用系统时钟)。condition_variable然后我必须以尊重时钟选择的方式自己重新实现标准库。
由于我必须支持多个平台(Bionic、POSIX、Windows,最终还有 MacOS),这意味着我将维护此代码的多个版本。
虽然这很糟糕,但其他选择似乎更糟糕。
| 归档时间: |
|
| 查看次数: |
1255 次 |
| 最近记录: |