From a85fc2504048165da68931e098248ca98e00c4e1 Mon Sep 17 00:00:00 2001 From: Joel Linn Date: Sat, 5 Mar 2022 11:41:19 +0100 Subject: [PATCH] [Base] Add more tests for HighResolutionTimer --- src/xenia/base/testing/threading_test.cc | 59 +++++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/xenia/base/testing/threading_test.cc b/src/xenia/base/testing/threading_test.cc index 3a8b119c1..2643e2148 100644 --- a/src/xenia/base/testing/threading_test.cc +++ b/src/xenia/base/testing/threading_test.cc @@ -241,8 +241,63 @@ TEST_CASE("HighResolutionTimer") { REQUIRE(counter2 <= ratio2 + 1); } - // TODO(bwrsandman): Check on which thread callbacks are executed when - // spawned from differing threads + // Test many timers + { + const auto interval = 50ms; + const size_t timer_count = 128; + std::atomic counter(0); + auto cb = [&counter, &timer_thread] { + ++counter; + REQUIRE(Thread::GetCurrentThread() == timer_thread); + }; + std::vector> timers; + auto start = std::chrono::steady_clock::now(); + for (size_t i = 0; i < timer_count; i++) { + timers.emplace_back(HighResolutionTimer::CreateRepeating(interval, cb)); + } + Sleep(wait_time); + timers.clear(); + auto duration = std::chrono::steady_clock::now() - start; + + REQUIRE(duration.count() >= wait_time.count()); + auto ratio = static_cast(timer_count * duration / interval); + REQUIRE(counter >= ratio - timer_count); + REQUIRE(counter <= ratio + timer_count); + } + + // Check timer order + { + constexpr size_t timer_count = 16; + using pair_t = std::pair, + std::chrono::high_resolution_clock::time_point>; + std::array time_points{}; + auto start = std::chrono::steady_clock::now(); + auto gen_callback = [&timer_thread, &time_points](size_t i) { + return [&timer_thread, &time_points, i]() { + auto& pair = time_points[i]; + if (pair.first.fetch_add(1) == 1) { + pair.second = std::chrono::high_resolution_clock::now(); + pair.first++; + } + REQUIRE(Thread::GetCurrentThread() == timer_thread); + }; + }; + std::vector> timers; + for (size_t i = 0; i < timer_count; i++) { + timers.emplace_back(HighResolutionTimer::CreateRepeating( + 10ms * (timer_count - i), gen_callback(timer_count - i - 1))); + } + REQUIRE(spin_wait_for(2s, [&] { + return std::all_of(time_points.cbegin(), time_points.cend(), + [](auto& pair) { return pair.first >= 3; }); + })); + + timers.clear(); + + REQUIRE(std::is_sorted( + time_points.cbegin(), time_points.cend(), + [](auto& left, auto& right) { return left.second < right.second; })); + } } TEST_CASE("Wait on Multiple Handles", "[wait]") {