5

As I understand it, pthread_cond_timedwait is to be used by taking current time, then calculating absolute time when pthread_cond_timedwait should exit if condition is not signalled.

Is there a simple way to use this function to reliably perform a periodic task (the problem being changes in time between the point where current time is taken and call to pthread_cond_timedwait)?

I have a periodic task that should run ~every second.

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);

Condition is signalled if context (including some_exit_condition) is updated.

Is there a way to use monotonic timer or something similar with this? If not, what is the use case for pthread_cond_timedwait at all? Only for cases, where you don't care about additional hour of delay?

I have seen a solution where another thread signals this one periodically (How to make pthread_cond_timedwait() robust against system clock manipulations?), but it seems like a hack.

Is there a different & better way to make thread sleep for some interval (not prone to wall clock changes) but respond immediately to external condition?

dbrank0
  • 9,026
  • 2
  • 37
  • 55

1 Answers1

11

You can set the clock type used by pthread_cond_timedwait() by setting attributes when initializing the condition variable:

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;
}

And then use time from CLOCK_MONOTONIC for timeout:

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

// pthread_cond_timedwait (..., timeout);
Erki Aring
  • 2,032
  • 13
  • 15