timing_event.h (2603B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #pragma once 5 6 #include "types.h" 7 8 #include <string_view> 9 10 class StateWrapper; 11 12 // Event callback type. Second parameter is the number of cycles the event was executed "late". 13 using TimingEventCallback = void (*)(void* param, TickCount ticks, TickCount ticks_late); 14 15 class TimingEvent 16 { 17 public: 18 TimingEvent(const std::string_view name, TickCount period, TickCount interval, TimingEventCallback callback, 19 void* callback_param); 20 ~TimingEvent(); 21 22 ALWAYS_INLINE const std::string_view GetName() const { return m_name; } 23 ALWAYS_INLINE bool IsActive() const { return m_active; } 24 25 // Returns the number of ticks between each event. 26 ALWAYS_INLINE TickCount GetPeriod() const { return m_period; } 27 ALWAYS_INLINE TickCount GetInterval() const { return m_interval; } 28 29 // Includes pending time. 30 TickCount GetTicksSinceLastExecution() const; 31 TickCount GetTicksUntilNextExecution() const; 32 33 // Adds ticks to current execution. 34 void Delay(TickCount ticks); 35 36 void Schedule(TickCount ticks); 37 void SetIntervalAndSchedule(TickCount ticks); 38 void SetPeriodAndSchedule(TickCount ticks); 39 40 // Services the event with the current accmulated time. If force is set, when not enough time is pending to 41 // simulate a single cycle, the callback will still be invoked, otherwise it won't be. 42 void InvokeEarly(bool force = false); 43 44 // Deactivates the event, preventing it from firing again. 45 // Do not call within a callback, return Deactivate instead. 46 void Activate(); 47 void Deactivate(); 48 49 ALWAYS_INLINE void SetState(bool active) 50 { 51 if (active) 52 Activate(); 53 else 54 Deactivate(); 55 } 56 57 // Directly alters the interval of the event. 58 void SetInterval(TickCount interval) { m_interval = interval; } 59 void SetPeriod(TickCount period) { m_period = period; } 60 61 TimingEvent* prev = nullptr; 62 TimingEvent* next = nullptr; 63 64 TimingEventCallback m_callback; 65 void* m_callback_param; 66 67 GlobalTicks m_next_run_time = 0; 68 GlobalTicks m_last_run_time = 0; 69 70 TickCount m_period; 71 TickCount m_interval; 72 bool m_active = false; 73 74 std::string_view m_name; 75 }; 76 77 namespace TimingEvents { 78 79 GlobalTicks GetGlobalTickCounter(); 80 GlobalTicks GetEventRunTickCounter(); 81 82 void Initialize(); 83 void Reset(); 84 void Shutdown(); 85 86 bool DoState(StateWrapper& sw); 87 88 bool IsRunningEvents(); 89 void CancelRunningEvent(); 90 void RunEvents(); 91 void CommitLeftoverTicks(); 92 93 void UpdateCPUDowncount(); 94 95 TimingEvent** GetHeadEventPtr(); 96 97 } // namespace TimingEvents