diff options
| author | 2019-11-26 21:48:56 -0500 | |
|---|---|---|
| committer | 2019-11-26 21:48:56 -0500 | |
| commit | ec0ce96c568b2b610c5218efd7faa5d9a19350f8 (patch) | |
| tree | 61b5133e3cc6a9edf3b45c5fe6604493689f6769 /src/core/core_timing.cpp | |
| parent | Merge pull request #3164 from ReinUsesLisp/half-cast-float (diff) | |
| download | yuzu-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.cpp | 53 |
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 | ||
| 18 | constexpr int MAX_SLICE_LENGTH = 10000; | 18 | constexpr int MAX_SLICE_LENGTH = 10000; |
| 19 | 19 | ||
| 20 | std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) { | ||
| 21 | return std::make_shared<EventType>(std::move(callback), std::move(name)); | ||
| 22 | } | ||
| 23 | |||
| 20 | struct CoreTiming::Event { | 24 | struct 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 | ||
| 60 | void CoreTiming::Shutdown() { | 64 | void CoreTiming::Shutdown() { |
| 61 | ClearPendingEvents(); | 65 | ClearPendingEvents(); |
| 62 | UnregisterAllEvents(); | ||
| 63 | } | ||
| 64 | |||
| 65 | EventType* 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 | |||
| 80 | void CoreTiming::UnregisterAllEvents() { | ||
| 81 | ASSERT_MSG(event_queue.empty(), "Cannot unregister events with events pending"); | ||
| 82 | event_types.clear(); | ||
| 83 | } | 66 | } |
| 84 | 67 | ||
| 85 | void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata) { | 68 | void 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 | ||
| 99 | void CoreTiming::UnscheduleEvent(const EventType* event_type, u64 userdata) { | 83 | void 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 | ||
| 133 | void CoreTiming::RemoveEvent(const EventType* event_type) { | 118 | void 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 | ||