_M_load_when_equal_until(unsigned __val, memory_order __mo,
const chrono::time_point<_Clock, _Duration>& __atime)
{
- const typename _Clock::time_point __c_entry = _Clock::now();
- const __clock_t::time_point __s_entry = __clock_t::now();
- const auto __delta = __atime - __c_entry;
- const auto __s_atime = __s_entry + __delta;
- return _M_load_when_equal_until(__val, __mo, __s_atime);
+ typename _Clock::time_point __c_entry = _Clock::now();
+ do {
+ const __clock_t::time_point __s_entry = __clock_t::now();
+ const auto __delta = __atime - __c_entry;
+ const auto __s_atime = __s_entry + __delta;
+ if (_M_load_when_equal_until(__val, __mo, __s_atime))
+ return true;
+ __c_entry = _Clock::now();
+ } while (__c_entry < __atime);
+ return false;
}
// Returns false iff a timeout occurred.
VERIFY( status == std::future_status::ready );
}
+// This clock behaves exactly the same as steady_clock, but it is not
+// steady_clock which means that the generic clock overload of
+// future::wait_until is used.
+struct steady_clock_copy
+{
+ using rep = std::chrono::steady_clock::rep;
+ using period = std::chrono::steady_clock::period;
+ using duration = std::chrono::steady_clock::duration;
+ using time_point = std::chrono::time_point<steady_clock_copy, duration>;
+ static constexpr bool is_steady = true;
+
+ static time_point now()
+ {
+ const auto steady = std::chrono::steady_clock::now();
+ return time_point{steady.time_since_epoch()};
+ }
+};
+
// This test is prone to failures if run on a loaded machine where the
// kernel decides not to schedule us for several seconds. It also
// assumes that no-one will warp CLOCK whilst the test is
VERIFY( elapsed < std::chrono::seconds(5) );
}
+// This clock is supposed to run at a tenth of normal speed, but we
+// don't have to worry about rounding errors causing us to wake up
+// slightly too early below if we actually run it at an eleventh of
+// normal speed. It is used to exercise the
+// __atomic_futex_unsigned::_M_load_when_equal_until overload that
+// takes an arbitrary clock.
+struct slow_clock
+{
+ using rep = std::chrono::steady_clock::rep;
+ using period = std::chrono::steady_clock::period;
+ using duration = std::chrono::steady_clock::duration;
+ using time_point = std::chrono::time_point<slow_clock, duration>;
+ static constexpr bool is_steady = true;
+
+ static time_point now()
+ {
+ const auto steady = std::chrono::steady_clock::now();
+ return time_point{steady.time_since_epoch() / 11};
+ }
+};
+
+void test04()
+{
+ using namespace std::chrono;
+
+ auto const slow_start = slow_clock::now();
+ future<void> f1 = async(launch::async, []() {
+ std::this_thread::sleep_for(std::chrono::seconds(2));
+ });
+
+ // Wait for ~1s
+ {
+ auto const steady_begin = steady_clock::now();
+ auto const status = f1.wait_until(slow_start + milliseconds(100));
+ VERIFY(status == std::future_status::timeout);
+ auto const elapsed = steady_clock::now() - steady_begin;
+ VERIFY(elapsed >= seconds(1));
+ VERIFY(elapsed < seconds(2));
+ }
+
+ // Wait for up to ~2s more
+ {
+ auto const steady_begin = steady_clock::now();
+ auto const status = f1.wait_until(slow_start + milliseconds(300));
+ VERIFY(status == std::future_status::ready);
+ auto const elapsed = steady_clock::now() - steady_begin;
+ VERIFY(elapsed < seconds(2));
+ }
+}
+
int main()
{
test01();
test02();
test03<std::chrono::system_clock>();
test03<std::chrono::steady_clock>();
+ test03<steady_clock_copy>();
+ test04();
return 0;
}