pthread_cond_timedwait用于定期任务和挂钟更改

dbr*_*nk0 4 c pthreads

据我了解,pthread_cond_timedwait将通过获取当前时间来使用,然后计算pthread_cond_timedwait应该在没有信号的情况下退出的绝对时间.

有一种简单的方法可以使用此函数可靠地执行周期性任务(问题是在当前时间点和调用pthread_cond_timedwait之间的时间变化)?

我有一个应该每秒运行一次的周期性任务.

do {
    pthread_mutex_lock(mutex);
    tx = gettimeofday + 1 second;
    do_some_simple_periodic_task();
    pthread_cond_timedwait(condition, mutex, tx);
    pthread_mutex_unlock(mutex);
} while (!some_exit_condition);
Run Code Online (Sandbox Code Playgroud)

如果更新了上下文(包括some_exit_condition),则发出条件信号.

有没有办法使用单调计时器或类似的东西?如果没有,pthread_cond_timedwait的用例是什么?仅适用于您不关心延迟一小时的情况?

我已经看到了一个解决方案,其中另一个线程周期性地发出信号(如何使pthread_cond_timedwait()对系统时钟操作有效?),但它看起来像是一个黑客.

是否有一种不同的更好的方法让线程睡眠一段时间(不容易发生挂钟变化)但是立即对外部条件做出反应?

Erk*_*i A 8

您可以通过在初始化条件变量时设置属性来设置pthread_cond_timedwait()使用的时钟类型:

pthread_condattr_t cond_attr;
pthread_cond_t cond;

errno = pthread_condattr_init (&cond_attr);
if (errno) {
    perror ("pthread_condattr_init");
    return -1;
}

errno = pthread_condattr_setclock (&cond_attr, CLOCK_MONOTONIC);
if (errno) {
    perror ("pthread_condattr_setclock");
    return -1;
}

errno = pthread_cond_init (&cond, &cond_attr);
if (errno) {
    perror ("pthread_cond_init");
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

然后使用CLOCK_MONOTONIC的时间进行超时:

struct timespec timeout;
clock_gettime (CLOCK_MONOTONIC, &timeout);
timeout.tv_sec += 1;

// pthread_cond_timedwait (..., timeout);
Run Code Online (Sandbox Code Playgroud)