Ответ 1
Хитрость заключается в использовании pthread_condattr_setclock
, чтобы сообщить pthread_condattr_t
использовать CLOCK_MONOTONIC
. Код 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;
}
Я оставлю это открытым какое-то время, потому что у кого-то может быть более легкий ответ. То, что мне не нравится, это то, что wait_until
довольно сложно реализовать с помощью часов реального времени (лучшим решением для этого является преобразование предоставленного Clock
в time_point
в steady_clock
время и перейти оттуда... он по-прежнему зависит от условий гонки с изменением времени, но если вы задаете тайм-аут в реальном времени, вы уже совершаете ужасную ошибку).