C++ 执行条件\u变量已正确计时\u等待
我正在阅读我的STL实现(标准版C++ 执行条件\u变量已正确计时\u等待,c++,multithreading,time,C++,Multithreading,Time,我正在阅读我的STL实现(标准版g++4.6.2),在condition\u变量中遇到了这一点竞争条件: template<typename _Rep, typename _Period> cv_status wait_for(unique_lock<mutex>& __lock, const chrono::duration<_Rep, _Period>& __rtime) { return wait_until(_
g++4.6.2
),在condition\u变量
中遇到了这一点竞争条件:
template<typename _Rep, typename _Period>
cv_status
wait_for(unique_lock<mutex>& __lock,
const chrono::duration<_Rep, _Period>& __rtime)
{
return wait_until(__lock, __clock_t::now() + __rtime);
}
事实上,底层pthreads实现似乎就是问题所在:
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
}
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
因为abstime
被指定为“系统时间”,而不是单调的时钟
所以我的问题是:如何正确地实现像std::condition\u variable::wait\u for
这样的东西?是否有一个现有的实现可以做到这一点?还是我遗漏了什么?诀窍是使用a告诉pthread\u condattr\t
使用CLOCK\u monotic
。执行此操作的C代码非常简单:
#include <time.h>
#include <pthread.h>
#include <errno.h>
#include <stdio.h>
int main()
{
// Set the clock to be CLOCK_MONOTONIC
pthread_condattr_t attr;
pthread_condattr_init(&attr);
if (int err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))
{
printf("Error setting clock: %d\n", err);
}
// Now we can initialize the pthreads objects with that condattr
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond;
pthread_cond_init(&cond, &attr);
// when getting the time, we must poll from CLOCK_MONOTONIC
struct timespec timeout;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
timeout.tv_sec = now.tv_sec + 5;
timeout.tv_nsec = now.tv_nsec;
// business as usual...
pthread_mutex_lock(&mutex);
int rc = pthread_cond_timedwait(&cond, &mutex, &timeout);
if (rc == ETIMEDOUT)
printf("Success!\n");
else
printf("Got return that wasn't timeout: %d\n", rc);
pthread_mutex_unlock(&mutex);
return 0;
}
#包括
#包括
#包括
#包括
int main()
{
//将时钟设置为时钟单调
pthread_condattr_t attr;
pthread_condattr_init(&attr);
if(int err=pthread\u condattr\u setclock(&attr,CLOCK\u单调))
{
printf(“设置时钟时出错:%d\n”,错误);
}
//现在我们可以用condattr初始化pthreads对象
pthread\u mutex\u t mutex=pthread\u mutex\u初始值设定项;
pthread_cond_t cond;
pthread_cond_init(&cond,&attr);
//当我们得到时间时,我们必须从时钟开始投票
结构timespec超时;
现在构造timespec;
时钟获得时间(时钟单调,&现在);
timeout.tv_sec=now.tv_sec+5;
timeout.tv\u nsec=now.tv\u nsec;
//一切照旧。。。
pthread_mutex_lock(&mutex);
int rc=pthread\u cond\u timedwait(&cond,&mutex,&timeout);
if(rc==ETIMEDOUT)
printf(“成功!\n”);
其他的
printf(“得到了非超时的返回:%d\n”,rc);
pthread_mutex_unlock(&mutex);
返回0;
}
我将暂时不讨论这个问题,因为有人可能会有一个更简单的答案。我不满意的是,这意味着用实时时钟很难实现
等待
(我的最佳解决方案是将时间点中提供的时钟
转换为稳定时钟
的时间,然后从那里开始……它仍然会受到时间更改竞争条件的影响,但如果你实时指定超时,你已经犯了一个可怕的错误).注意:在内部,pthread\u cond\u timedwait
使用gettimeofday
,如果您想在指定的时间内超时,这是假的:您可能被迫使用其他使用单调时钟的计时器线程,然后在服务生取消之前唤醒服务生。如果我不得不这么做的话(我非常希望我不会这样做),我宁愿在我的wait_for
函数中做一个旋转等待(看起来我的sleep_for
没有这个问题,因为nanosleep
没有同样的问题,因为它正确地使用了时钟单调的)。请注意。我怀疑是否有更简单的答案,因为这是POSIX API的一个限制。请注意,condition\u variable
不仅存在定时等待问题,而且mutex
也存在此问题。此外,对于mutex,情况更糟,因为没有pthread\u mutextatr\u setclock
这样的API: .