Implementing condition_variable timed_wait correctly
The trick is to use a pthread_condattr_setclock
to tell the pthread_condattr_t
to use CLOCK_MONOTONIC
. The C code for doing this is pretty simple:
#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;}
I'm going to leave this open for a while because somebody might have an easier answer. The thing I'm not happy about here is that it means a wait_until
is rather difficult to implement with a real-time clock (my best solution to that is to convert the provided Clock
in the time_point
into the steady_clock
's time and go from there...it is still subject to time-change race conditions, but if you're specifying a timeout in real time, you're already making a terrible mistake).