summaryrefslogtreecommitdiff
path: root/src/core/core_timing.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2019-11-26 21:48:56 -0500
committerGravatar GitHub2019-11-26 21:48:56 -0500
commitec0ce96c568b2b610c5218efd7faa5d9a19350f8 (patch)
tree61b5133e3cc6a9edf3b45c5fe6604493689f6769 /src/core/core_timing.cpp
parentMerge pull request #3164 from ReinUsesLisp/half-cast-float (diff)
downloadyuzu-ec0ce96c568b2b610c5218efd7faa5d9a19350f8.tar.gz
yuzu-ec0ce96c568b2b610c5218efd7faa5d9a19350f8.tar.xz
yuzu-ec0ce96c568b2b610c5218efd7faa5d9a19350f8.zip
core_timing: Use better reference tracking for EventType. (#3159)
* core_timing: Use better reference tracking for EventType. - Moves ownership of the event to the caller, ensuring we don't fire events for destroyed objects. - Removes need for unique names - we won't be using this for save states anyways.
Diffstat (limited to 'src/core/core_timing.cpp')
-rw-r--r--src/core/core_timing.cpp53
1 files changed, 22 insertions, 31 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 0e9570685..aa09fa453 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -17,11 +17,15 @@ namespace Core::Timing {
17 17
18constexpr int MAX_SLICE_LENGTH = 10000; 18constexpr int MAX_SLICE_LENGTH = 10000;
19 19
20std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
21 return std::make_shared<EventType>(std::move(callback), std::move(name));
22}
23
20struct CoreTiming::Event { 24struct CoreTiming::Event {
21 s64 time; 25 s64 time;
22 u64 fifo_order; 26 u64 fifo_order;
23 u64 userdata; 27 u64 userdata;
24 const EventType* type; 28 std::weak_ptr<EventType> type;
25 29
26 // Sort by time, unless the times are the same, in which case sort by 30 // Sort by time, unless the times are the same, in which case sort by
27 // the order added to the queue 31 // the order added to the queue
@@ -54,36 +58,15 @@ void CoreTiming::Initialize() {
54 event_fifo_id = 0; 58 event_fifo_id = 0;
55 59
56 const auto empty_timed_callback = [](u64, s64) {}; 60 const auto empty_timed_callback = [](u64, s64) {};
57 ev_lost = RegisterEvent("_lost_event", empty_timed_callback); 61 ev_lost = CreateEvent("_lost_event", empty_timed_callback);
58} 62}
59 63
60void CoreTiming::Shutdown() { 64void CoreTiming::Shutdown() {
61 ClearPendingEvents(); 65 ClearPendingEvents();
62 UnregisterAllEvents();
63}
64
65EventType* CoreTiming::RegisterEvent(const std::string& name, TimedCallback callback) {
66 std::lock_guard guard{inner_mutex};
67 // check for existing type with same name.
68 // we want event type names to remain unique so that we can use them for serialization.
69 ASSERT_MSG(event_types.find(name) == event_types.end(),
70 "CoreTiming Event \"{}\" is already registered. Events should only be registered "
71 "during Init to avoid breaking save states.",
72 name.c_str());
73
74 auto info = event_types.emplace(name, EventType{callback, nullptr});
75 EventType* event_type = &info.first->second;
76 event_type->name = &info.first->first;
77 return event_type;
78}
79
80void CoreTiming::UnregisterAllEvents() {
81 ASSERT_MSG(event_queue.empty(), "Cannot unregister events with events pending");
82 event_types.clear();
83} 66}
84 67
85void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata) { 68void CoreTiming::ScheduleEvent(s64 cycles_into_future, const std::shared_ptr<EventType>& event_type,
86 ASSERT(event_type != nullptr); 69 u64 userdata) {
87 std::lock_guard guard{inner_mutex}; 70 std::lock_guard guard{inner_mutex};
88 const s64 timeout = GetTicks() + cycles_into_future; 71 const s64 timeout = GetTicks() + cycles_into_future;
89 72
@@ -93,13 +76,15 @@ void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_ty
93 } 76 }
94 77
95 event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); 78 event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
79
96 std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); 80 std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
97} 81}
98 82
99void CoreTiming::UnscheduleEvent(const EventType* event_type, u64 userdata) { 83void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata) {
100 std::lock_guard guard{inner_mutex}; 84 std::lock_guard guard{inner_mutex};
85
101 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { 86 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
102 return e.type == event_type && e.userdata == userdata; 87 return e.type.lock().get() == event_type.get() && e.userdata == userdata;
103 }); 88 });
104 89
105 // Removing random items breaks the invariant so we have to re-establish it. 90 // Removing random items breaks the invariant so we have to re-establish it.
@@ -130,10 +115,12 @@ void CoreTiming::ClearPendingEvents() {
130 event_queue.clear(); 115 event_queue.clear();
131} 116}
132 117
133void CoreTiming::RemoveEvent(const EventType* event_type) { 118void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
134 std::lock_guard guard{inner_mutex}; 119 std::lock_guard guard{inner_mutex};
135 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), 120
136 [&](const Event& e) { return e.type == event_type; }); 121 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
122 return e.type.lock().get() == event_type.get();
123 });
137 124
138 // Removing random items breaks the invariant so we have to re-establish it. 125 // Removing random items breaks the invariant so we have to re-establish it.
139 if (itr != event_queue.end()) { 126 if (itr != event_queue.end()) {
@@ -181,7 +168,11 @@ void CoreTiming::Advance() {
181 std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>()); 168 std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>());
182 event_queue.pop_back(); 169 event_queue.pop_back();
183 inner_mutex.unlock(); 170 inner_mutex.unlock();
184 evt.type->callback(evt.userdata, global_timer - evt.time); 171
172 if (auto event_type{evt.type.lock()}) {
173 event_type->callback(evt.userdata, global_timer - evt.time);
174 }
175
185 inner_mutex.lock(); 176 inner_mutex.lock();
186 } 177 }
187 178