"futexWaitUntil only knows std::chrono::{system_clock,steady_clock}");
assert((std::is_same<Clock, system_clock>::value) || Clock::is_steady);
- auto duration = absTime.time_since_epoch();
+ // We launder the clock type via a std::chrono::duration so that we
+ // can compile both the true and false branch. Tricky case is when
+ // steady_clock has a higher precision than system_clock (Xcode 6,
+ // for example), for which time_point<system_clock> construction
+ // refuses to do an implicit duration conversion. (duration is
+ // happy to implicitly convert its denominator causing overflow, but
+ // refuses conversion that might cause truncation.) We use explicit
+ // duration_cast to work around this. Truncation does not actually
+ // occur (unless Duration != Clock::duration) because the missing
+ // implicit conversion is in the untaken branch.
+ Duration absTimeDuration = absTime.time_since_epoch();
if (std::is_same<Clock, system_clock>::value) {
- time_point<system_clock> absSystemTime(duration);
+ time_point<system_clock> absSystemTime(
+ duration_cast<system_clock::duration>(absTimeDuration));
return futexWaitImpl(expected, &absSystemTime, nullptr, waitMask);
} else {
- time_point<steady_clock> absSteadyTime(duration);
+ time_point<steady_clock> absSteadyTime(
+ duration_cast<steady_clock::duration>(absTimeDuration));
return futexWaitImpl(expected, nullptr, &absSteadyTime, waitMask);
}
}
#include <chrono>
#include <functional>
+#include <ratio>
#include <thread>
#include <gflags/gflags.h>
using namespace folly::detail;
using namespace folly::test;
+using namespace std;
using namespace std::chrono;
typedef DeterministicSchedule DSched;
DSched::join(thr);
}
-template <template<typename> class Atom, typename Clock>
+template <template<typename> class Atom, typename Clock, typename Duration>
void liveClockWaitUntilTests() {
Futex<Atom> f(0);
auto fp = &f; // workaround for t5336595
auto thrA = DSched::thread([fp,stress]{
while (true) {
- auto deadline = Clock::now() + microseconds(1 << (stress % 20));
+ auto deadline = time_point_cast<Duration>(
+ Clock::now() + microseconds(1 << (stress % 20)));
auto res = fp->futexWaitUntil(0, deadline);
EXPECT_TRUE(res == FutexResult::TIMEDOUT || res == FutexResult::AWOKEN);
if (res == FutexResult::AWOKEN) {
template<template<typename> class Atom>
void run_wait_until_tests() {
- liveClockWaitUntilTests<Atom, system_clock>();
- liveClockWaitUntilTests<Atom, steady_clock>();
+ liveClockWaitUntilTests<Atom, system_clock, system_clock::duration>();
+ liveClockWaitUntilTests<Atom, steady_clock, steady_clock::duration>();
+
+ typedef duration<int64_t, pico> picoseconds;
+ liveClockWaitUntilTests<Atom, system_clock, picoseconds>();
}
template <>