From 49a7e0984a1210832b8be24433a95711c7ce029b Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 10 Feb 2020 15:02:04 -0400 Subject: [PATCH] Core/HostTiming: Allow events to be advanced manually. --- src/common/fiber.cpp | 2 +- src/common/wall_clock.cpp | 9 +++--- src/core/host_timing.cpp | 61 +++++++++++++++++++++++---------------- src/core/host_timing.h | 6 +++- 4 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index 1220eddf05..e9c0946b6a 100644 --- a/src/common/fiber.cpp +++ b/src/common/fiber.cpp @@ -110,7 +110,7 @@ Fiber::Fiber(std::function&& entry_point_func, void* start_paramete FiberStartFunc); } -Fiber::Fiber() : guard{}, entry_point{}, start_parameter{}, previous_fiber{} { +Fiber::Fiber() { impl = std::make_unique(); } diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp index e6161c72ce..d4d35f4e7a 100644 --- a/src/common/wall_clock.cpp +++ b/src/common/wall_clock.cpp @@ -42,14 +42,15 @@ public: u64 GetClockCycles() override { std::chrono::nanoseconds time_now = GetTimeNS(); - const u128 temporal = Common::Multiply64Into128(time_now.count(), emulated_clock_frequency); - return Common::Divide128On32(temporal, 1000000000).first; + const u128 temporary = + Common::Multiply64Into128(time_now.count(), emulated_clock_frequency); + return Common::Divide128On32(temporary, 1000000000).first; } u64 GetCPUCycles() override { std::chrono::nanoseconds time_now = GetTimeNS(); - const u128 temporal = Common::Multiply64Into128(time_now.count(), emulated_cpu_frequency); - return Common::Divide128On32(temporal, 1000000000).first; + const u128 temporary = Common::Multiply64Into128(time_now.count(), emulated_cpu_frequency); + return Common::Divide128On32(temporary, 1000000000).first; } private: diff --git a/src/core/host_timing.cpp b/src/core/host_timing.cpp index be80d9f8ed..5d35a96b14 100644 --- a/src/core/host_timing.cpp +++ b/src/core/host_timing.cpp @@ -42,7 +42,7 @@ CoreTiming::CoreTiming() { CoreTiming::~CoreTiming() = default; void CoreTiming::ThreadEntry(CoreTiming& instance) { - instance.Advance(); + instance.ThreadLoop(); } void CoreTiming::Initialize() { @@ -137,38 +137,49 @@ void CoreTiming::RemoveEvent(const std::shared_ptr& event_type) { basic_lock.unlock(); } -void CoreTiming::Advance() { +std::optional CoreTiming::Advance() { + advance_lock.lock(); + basic_lock.lock(); + global_timer = GetGlobalTimeNs().count(); + + while (!event_queue.empty() && event_queue.front().time <= global_timer) { + Event evt = std::move(event_queue.front()); + std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>()); + event_queue.pop_back(); + basic_lock.unlock(); + + if (auto event_type{evt.type.lock()}) { + event_type->callback(evt.userdata, global_timer - evt.time); + } + + basic_lock.lock(); + } + + if (!event_queue.empty()) { + const u64 next_time = event_queue.front().time - global_timer; + basic_lock.unlock(); + advance_lock.unlock(); + return next_time; + } else { + basic_lock.unlock(); + advance_lock.unlock(); + return std::nullopt; + } +} + +void CoreTiming::ThreadLoop() { has_started = true; while (!shutting_down) { while (!paused) { paused_set = false; - basic_lock.lock(); - global_timer = GetGlobalTimeNs().count(); - - while (!event_queue.empty() && event_queue.front().time <= global_timer) { - Event evt = std::move(event_queue.front()); - std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>()); - event_queue.pop_back(); - basic_lock.unlock(); - - if (auto event_type{evt.type.lock()}) { - event_type->callback(evt.userdata, global_timer - evt.time); - } - - basic_lock.lock(); - } - - if (!event_queue.empty()) { - std::chrono::nanoseconds next_time = - std::chrono::nanoseconds(event_queue.front().time - global_timer); - basic_lock.unlock(); - event.WaitFor(next_time); + const auto next_time = Advance(); + if (next_time) { + std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time); + event.WaitFor(next_time_ns); } else { - basic_lock.unlock(); wait_set = true; event.Wait(); } - wait_set = false; } paused_set = true; diff --git a/src/core/host_timing.h b/src/core/host_timing.h index 679fcf491a..cd44b308cb 100644 --- a/src/core/host_timing.h +++ b/src/core/host_timing.h @@ -103,6 +103,9 @@ public: /// Returns current time in nanoseconds. std::chrono::nanoseconds GetGlobalTimeNs() const; + /// Checks for events manually and returns time in nanoseconds for next event, threadsafe. + std::optional Advance(); + private: struct Event; @@ -110,7 +113,7 @@ private: void ClearPendingEvents(); static void ThreadEntry(CoreTiming& instance); - void Advance(); + void ThreadLoop(); std::unique_ptr clock; @@ -128,6 +131,7 @@ private: std::shared_ptr ev_lost; Common::Event event{}; Common::SpinLock basic_lock{}; + Common::SpinLock advance_lock{}; std::unique_ptr timer_thread; std::atomic paused{}; std::atomic paused_set{};