From ad27d09a7d58dbba193d36c4e0b6774d6a623f16 Mon Sep 17 00:00:00 2001
From: yuzubot <yuzu@yuzu-emu.org>
Date: Tue, 26 Nov 2019 13:01:18 +0000
Subject: "Merge Tagged PR 3159"

---
 src/audio_core/stream.cpp                    |  2 +-
 src/audio_core/stream.h                      | 25 +++++----
 src/core/core_timing.cpp                     | 53 ++++++++----------
 src/core/core_timing.h                       | 45 +++++++--------
 src/core/hardware_interrupt_manager.cpp      | 13 ++---
 src/core/hardware_interrupt_manager.h        |  4 +-
 src/core/hle/kernel/kernel.cpp               | 13 +++--
 src/core/hle/kernel/kernel.h                 |  2 +-
 src/core/hle/service/hid/hid.cpp             |  5 +-
 src/core/hle/service/hid/hid.h               |  2 +-
 src/core/hle/service/nvflinger/nvflinger.cpp |  4 +-
 src/core/hle/service/nvflinger/nvflinger.h   |  2 +-
 src/core/memory/cheat_engine.cpp             |  2 +-
 src/core/memory/cheat_engine.h               |  3 +-
 src/core/tools/freezer.cpp                   |  2 +-
 src/core/tools/freezer.h                     |  3 +-
 src/tests/core/core_timing.cpp               | 84 ++++++----------------------
 17 files changed, 103 insertions(+), 161 deletions(-)

(limited to 'src')

diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp
index 6a5f53a57b..4ca98f8ea7 100644
--- a/src/audio_core/stream.cpp
+++ b/src/audio_core/stream.cpp
@@ -37,7 +37,7 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo
     : sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)},
       sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
 
-    release_event = core_timing.RegisterEvent(
+    release_event = Core::Timing::CreateEvent(
         name, [this](u64 userdata, s64 cycles_late) { ReleaseActiveBuffer(); });
 }
 
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h
index 8106cea433..1708a4d989 100644
--- a/src/audio_core/stream.h
+++ b/src/audio_core/stream.h
@@ -98,18 +98,19 @@ private:
     /// Gets the number of core cycles when the specified buffer will be released
     s64 GetBufferReleaseCycles(const Buffer& buffer) const;
 
-    u32 sample_rate;                          ///< Sample rate of the stream
-    Format format;                            ///< Format of the stream
-    float game_volume = 1.0f;                 ///< The volume the game currently has set
-    ReleaseCallback release_callback;         ///< Buffer release callback for the stream
-    State state{State::Stopped};              ///< Playback state of the stream
-    Core::Timing::EventType* release_event{}; ///< Core timing release event for the stream
-    BufferPtr active_buffer;                  ///< Actively playing buffer in the stream
-    std::queue<BufferPtr> queued_buffers;     ///< Buffers queued to be played in the stream
-    std::queue<BufferPtr> released_buffers;   ///< Buffers recently released from the stream
-    SinkStream& sink_stream;                  ///< Output sink for the stream
-    Core::Timing::CoreTiming& core_timing;    ///< Core timing instance.
-    std::string name;                         ///< Name of the stream, must be unique
+    u32 sample_rate;                  ///< Sample rate of the stream
+    Format format;                    ///< Format of the stream
+    float game_volume = 1.0f;         ///< The volume the game currently has set
+    ReleaseCallback release_callback; ///< Buffer release callback for the stream
+    State state{State::Stopped};      ///< Playback state of the stream
+    std::shared_ptr<Core::Timing::EventType>
+        release_event;                      ///< Core timing release event for the stream
+    BufferPtr active_buffer;                ///< Actively playing buffer in the stream
+    std::queue<BufferPtr> queued_buffers;   ///< Buffers queued to be played in the stream
+    std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream
+    SinkStream& sink_stream;                ///< Output sink for the stream
+    Core::Timing::CoreTiming& core_timing;  ///< Core timing instance.
+    std::string name;                       ///< Name of the stream, must be unique
 };
 
 using StreamPtr = std::shared_ptr<Stream>;
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 0e95706856..aa09fa4538 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -17,11 +17,15 @@ namespace Core::Timing {
 
 constexpr int MAX_SLICE_LENGTH = 10000;
 
+std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
+    return std::make_shared<EventType>(std::move(callback), std::move(name));
+}
+
 struct CoreTiming::Event {
     s64 time;
     u64 fifo_order;
     u64 userdata;
-    const EventType* type;
+    std::weak_ptr<EventType> type;
 
     // Sort by time, unless the times are the same, in which case sort by
     // the order added to the queue
@@ -54,36 +58,15 @@ void CoreTiming::Initialize() {
     event_fifo_id = 0;
 
     const auto empty_timed_callback = [](u64, s64) {};
-    ev_lost = RegisterEvent("_lost_event", empty_timed_callback);
+    ev_lost = CreateEvent("_lost_event", empty_timed_callback);
 }
 
 void CoreTiming::Shutdown() {
     ClearPendingEvents();
-    UnregisterAllEvents();
-}
-
-EventType* CoreTiming::RegisterEvent(const std::string& name, TimedCallback callback) {
-    std::lock_guard guard{inner_mutex};
-    // check for existing type with same name.
-    // we want event type names to remain unique so that we can use them for serialization.
-    ASSERT_MSG(event_types.find(name) == event_types.end(),
-               "CoreTiming Event \"{}\" is already registered. Events should only be registered "
-               "during Init to avoid breaking save states.",
-               name.c_str());
-
-    auto info = event_types.emplace(name, EventType{callback, nullptr});
-    EventType* event_type = &info.first->second;
-    event_type->name = &info.first->first;
-    return event_type;
-}
-
-void CoreTiming::UnregisterAllEvents() {
-    ASSERT_MSG(event_queue.empty(), "Cannot unregister events with events pending");
-    event_types.clear();
 }
 
-void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata) {
-    ASSERT(event_type != nullptr);
+void CoreTiming::ScheduleEvent(s64 cycles_into_future, const std::shared_ptr<EventType>& event_type,
+                               u64 userdata) {
     std::lock_guard guard{inner_mutex};
     const s64 timeout = GetTicks() + cycles_into_future;
 
@@ -93,13 +76,15 @@ void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_ty
     }
 
     event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
+
     std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
 }
 
-void CoreTiming::UnscheduleEvent(const EventType* event_type, u64 userdata) {
+void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata) {
     std::lock_guard guard{inner_mutex};
+
     const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
-        return e.type == event_type && e.userdata == userdata;
+        return e.type.lock().get() == event_type.get() && e.userdata == userdata;
     });
 
     // Removing random items breaks the invariant so we have to re-establish it.
@@ -130,10 +115,12 @@ void CoreTiming::ClearPendingEvents() {
     event_queue.clear();
 }
 
-void CoreTiming::RemoveEvent(const EventType* event_type) {
+void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
     std::lock_guard guard{inner_mutex};
-    const auto itr = std::remove_if(event_queue.begin(), event_queue.end(),
-                                    [&](const Event& e) { return e.type == event_type; });
+
+    const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
+        return e.type.lock().get() == event_type.get();
+    });
 
     // Removing random items breaks the invariant so we have to re-establish it.
     if (itr != event_queue.end()) {
@@ -181,7 +168,11 @@ void CoreTiming::Advance() {
         std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>());
         event_queue.pop_back();
         inner_mutex.unlock();
-        evt.type->callback(evt.userdata, global_timer - evt.time);
+
+        if (auto event_type{evt.type.lock()}) {
+            event_type->callback(evt.userdata, global_timer - evt.time);
+        }
+
         inner_mutex.lock();
     }
 
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 3bb88c810e..d50f4eb8a7 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -6,11 +6,12 @@
 
 #include <chrono>
 #include <functional>
+#include <memory>
 #include <mutex>
 #include <optional>
 #include <string>
-#include <unordered_map>
 #include <vector>
+
 #include "common/common_types.h"
 #include "common/threadsafe_queue.h"
 
@@ -21,10 +22,13 @@ using TimedCallback = std::function<void(u64 userdata, s64 cycles_late)>;
 
 /// Contains the characteristics of a particular event.
 struct EventType {
+    EventType(TimedCallback&& callback, std::string&& name)
+        : callback{std::move(callback)}, name{std::move(name)} {}
+
     /// The event's callback function.
     TimedCallback callback;
     /// A pointer to the name of the event.
-    const std::string* name;
+    const std::string name;
 };
 
 /**
@@ -57,31 +61,17 @@ public:
     /// Tears down all timing related functionality.
     void Shutdown();
 
-    /// Registers a core timing event with the given name and callback.
-    ///
-    /// @param name     The name of the core timing event to register.
-    /// @param callback The callback to execute for the event.
-    ///
-    /// @returns An EventType instance representing the registered event.
-    ///
-    /// @pre The name of the event being registered must be unique among all
-    ///      registered events.
-    ///
-    EventType* RegisterEvent(const std::string& name, TimedCallback callback);
-
-    /// Unregisters all registered events thus far. Note: not thread unsafe
-    void UnregisterAllEvents();
-
     /// After the first Advance, the slice lengths and the downcount will be reduced whenever an
     /// event is scheduled earlier than the current values.
     ///
     /// Scheduling from a callback will not update the downcount until the Advance() completes.
-    void ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata = 0);
+    void ScheduleEvent(s64 cycles_into_future, const std::shared_ptr<EventType>& event_type,
+                       u64 userdata = 0);
 
-    void UnscheduleEvent(const EventType* event_type, u64 userdata);
+    void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata);
 
     /// We only permit one event of each type in the queue at a time.
-    void RemoveEvent(const EventType* event_type);
+    void RemoveEvent(const std::shared_ptr<EventType>& event_type);
 
     void ForceExceptionCheck(s64 cycles);
 
@@ -148,13 +138,18 @@ private:
     std::vector<Event> event_queue;
     u64 event_fifo_id = 0;
 
-    // Stores each element separately as a linked list node so pointers to elements
-    // remain stable regardless of rehashes/resizing.
-    std::unordered_map<std::string, EventType> event_types;
-
-    EventType* ev_lost = nullptr;
+    std::shared_ptr<EventType> ev_lost;
 
     std::mutex inner_mutex;
 };
 
+/// Creates a core timing event with the given name and callback.
+///
+/// @param name     The name of the core timing event to create.
+/// @param callback The callback to execute for the event.
+///
+/// @returns An EventType instance representing the created event.
+///
+std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback);
+
 } // namespace Core::Timing
diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp
index c2115db2de..c629d9fa10 100644
--- a/src/core/hardware_interrupt_manager.cpp
+++ b/src/core/hardware_interrupt_manager.cpp
@@ -11,13 +11,12 @@
 namespace Core::Hardware {
 
 InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) {
-    gpu_interrupt_event =
-        system.CoreTiming().RegisterEvent("GPUInterrupt", [this](u64 message, s64) {
-            auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
-            const u32 syncpt = static_cast<u32>(message >> 32);
-            const u32 value = static_cast<u32>(message);
-            nvdrv->SignalGPUInterruptSyncpt(syncpt, value);
-        });
+    gpu_interrupt_event = Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, s64) {
+        auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
+        const u32 syncpt = static_cast<u32>(message >> 32);
+        const u32 value = static_cast<u32>(message);
+        nvdrv->SignalGPUInterruptSyncpt(syncpt, value);
+    });
 }
 
 InterruptManager::~InterruptManager() = default;
diff --git a/src/core/hardware_interrupt_manager.h b/src/core/hardware_interrupt_manager.h
index 494db883ad..5fa306ae0a 100644
--- a/src/core/hardware_interrupt_manager.h
+++ b/src/core/hardware_interrupt_manager.h
@@ -4,6 +4,8 @@
 
 #pragma once
 
+#include <memory>
+
 #include "common/common_types.h"
 
 namespace Core {
@@ -25,7 +27,7 @@ public:
 
 private:
     Core::System& system;
-    Core::Timing::EventType* gpu_interrupt_event{};
+    std::shared_ptr<Core::Timing::EventType> gpu_interrupt_event;
 };
 
 } // namespace Core::Hardware
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 63ad079505..a9851113a9 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -139,12 +139,12 @@ struct KernelCore::Impl {
 
     void InitializeThreads() {
         thread_wakeup_event_type =
-            system.CoreTiming().RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
+            Core::Timing::CreateEvent("ThreadWakeupCallback", ThreadWakeupCallback);
     }
 
     void InitializePreemption() {
-        preemption_event = system.CoreTiming().RegisterEvent(
-            "PreemptionCallback", [this](u64 userdata, s64 cycles_late) {
+        preemption_event =
+            Core::Timing::CreateEvent("PreemptionCallback", [this](u64 userdata, s64 cycles_late) {
                 global_scheduler.PreemptThreads();
                 s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10));
                 system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
@@ -166,8 +166,9 @@ struct KernelCore::Impl {
 
     std::shared_ptr<ResourceLimit> system_resource_limit;
 
-    Core::Timing::EventType* thread_wakeup_event_type = nullptr;
-    Core::Timing::EventType* preemption_event = nullptr;
+    std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type;
+    std::shared_ptr<Core::Timing::EventType> preemption_event;
+
     // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future,
     // allowing us to simply use a pool index or similar.
     Kernel::HandleTable thread_wakeup_callback_handle_table;
@@ -269,7 +270,7 @@ u64 KernelCore::CreateNewUserProcessID() {
     return impl->next_user_process_id++;
 }
 
-Core::Timing::EventType* KernelCore::ThreadWakeupCallbackEventType() const {
+const std::shared_ptr<Core::Timing::EventType>& KernelCore::ThreadWakeupCallbackEventType() const {
     return impl->thread_wakeup_event_type;
 }
 
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index c74b9078fe..babb531c64 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -113,7 +113,7 @@ private:
     u64 CreateNewThreadID();
 
     /// Retrieves the event type used for thread wakeup callbacks.
-    Core::Timing::EventType* ThreadWakeupCallbackEventType() const;
+    const std::shared_ptr<Core::Timing::EventType>& ThreadWakeupCallbackEventType() const;
 
     /// Provides a reference to the thread wakeup callback handle table.
     Kernel::HandleTable& ThreadWakeupCallbackHandleTable();
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 8ef029e0f1..89bf8b815b 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -77,15 +77,14 @@ IAppletResource::IAppletResource(Core::System& system)
     GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000);
 
     // Register update callbacks
-    auto& core_timing = system.CoreTiming();
     pad_update_event =
-        core_timing.RegisterEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 cycles_late) {
+        Core::Timing::CreateEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 cycles_late) {
             UpdateControllers(userdata, cycles_late);
         });
 
     // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
 
-    core_timing.ScheduleEvent(pad_update_ticks, pad_update_event);
+    system.CoreTiming().ScheduleEvent(pad_update_ticks, pad_update_event);
 
     ReloadInputDevices();
 }
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 923762fff8..ad20f147ce 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -69,7 +69,7 @@ private:
 
     std::shared_ptr<Kernel::SharedMemory> shared_mem;
 
-    Core::Timing::EventType* pad_update_event;
+    std::shared_ptr<Core::Timing::EventType> pad_update_event;
     Core::System& system;
 
     std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index cd07ab3622..52623cf897 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -37,8 +37,8 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
     displays.emplace_back(4, "Null", system);
 
     // Schedule the screen composition events
-    composition_event = system.CoreTiming().RegisterEvent(
-        "ScreenComposition", [this](u64 userdata, s64 cycles_late) {
+    composition_event =
+        Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 cycles_late) {
             Compose();
             const auto ticks =
                 Settings::values.force_30fps_mode ? frame_ticks_30fps : GetNextTicks();
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 9cc41f2e6f..e3cc14bdca 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -103,7 +103,7 @@ private:
     u32 swap_interval = 1;
 
     /// Event that handles screen composition.
-    Core::Timing::EventType* composition_event;
+    std::shared_ptr<Core::Timing::EventType> composition_event;
 
     Core::System& system;
 };
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index 10821d4527..b73cc9fbd9 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -186,7 +186,7 @@ CheatEngine::~CheatEngine() {
 }
 
 void CheatEngine::Initialize() {
-    event = core_timing.RegisterEvent(
+    event = Core::Timing::CreateEvent(
         "CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
         [this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
     core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event);
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h
index 0f012e9b5c..e3db90dacc 100644
--- a/src/core/memory/cheat_engine.h
+++ b/src/core/memory/cheat_engine.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <atomic>
+#include <memory>
 #include <vector>
 #include "common/common_types.h"
 #include "core/memory/dmnt_cheat_types.h"
@@ -78,7 +79,7 @@ private:
     std::vector<CheatEntry> cheats;
     std::atomic_bool is_pending_reload{false};
 
-    Core::Timing::EventType* event{};
+    std::shared_ptr<Core::Timing::EventType> event;
     Core::Timing::CoreTiming& core_timing;
     Core::System& system;
 };
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp
index 17f050068a..19b531ecb0 100644
--- a/src/core/tools/freezer.cpp
+++ b/src/core/tools/freezer.cpp
@@ -54,7 +54,7 @@ void MemoryWriteWidth(u32 width, VAddr addr, u64 value) {
 } // Anonymous namespace
 
 Freezer::Freezer(Core::Timing::CoreTiming& core_timing) : core_timing(core_timing) {
-    event = core_timing.RegisterEvent(
+    event = Core::Timing::CreateEvent(
         "MemoryFreezer::FrameCallback",
         [this](u64 userdata, s64 cycles_late) { FrameCallback(userdata, cycles_late); });
     core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event);
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h
index b58de5472c..90b1a885c1 100644
--- a/src/core/tools/freezer.h
+++ b/src/core/tools/freezer.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <atomic>
+#include <memory>
 #include <mutex>
 #include <optional>
 #include <vector>
@@ -75,7 +76,7 @@ private:
     mutable std::mutex entries_mutex;
     std::vector<Entry> entries;
 
-    Core::Timing::EventType* event;
+    std::shared_ptr<Core::Timing::EventType> event;
     Core::Timing::CoreTiming& core_timing;
 };
 
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp
index 3443bf05e9..1e39408011 100644
--- a/src/tests/core/core_timing.cpp
+++ b/src/tests/core/core_timing.cpp
@@ -7,7 +7,9 @@
 #include <array>
 #include <bitset>
 #include <cstdlib>
+#include <memory>
 #include <string>
+
 #include "common/file_util.h"
 #include "core/core.h"
 #include "core/core_timing.h"
@@ -65,11 +67,16 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
     ScopeInit guard;
     auto& core_timing = guard.core_timing;
 
-    Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>);
-    Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>);
-    Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", CallbackTemplate<2>);
-    Core::Timing::EventType* cb_d = core_timing.RegisterEvent("callbackD", CallbackTemplate<3>);
-    Core::Timing::EventType* cb_e = core_timing.RegisterEvent("callbackE", CallbackTemplate<4>);
+    std::shared_ptr<Core::Timing::EventType> cb_a =
+        Core::Timing::CreateEvent("callbackA", CallbackTemplate<0>);
+    std::shared_ptr<Core::Timing::EventType> cb_b =
+        Core::Timing::CreateEvent("callbackB", CallbackTemplate<1>);
+    std::shared_ptr<Core::Timing::EventType> cb_c =
+        Core::Timing::CreateEvent("callbackC", CallbackTemplate<2>);
+    std::shared_ptr<Core::Timing::EventType> cb_d =
+        Core::Timing::CreateEvent("callbackD", CallbackTemplate<3>);
+    std::shared_ptr<Core::Timing::EventType> cb_e =
+        Core::Timing::CreateEvent("callbackE", CallbackTemplate<4>);
 
     // Enter slice 0
     core_timing.ResetRun();
@@ -99,8 +106,8 @@ TEST_CASE("CoreTiming[FairSharing]", "[core]") {
     ScopeInit guard;
     auto& core_timing = guard.core_timing;
 
-    Core::Timing::EventType* empty_callback =
-        core_timing.RegisterEvent("empty_callback", EmptyCallback);
+    std::shared_ptr<Core::Timing::EventType> empty_callback =
+        Core::Timing::CreateEvent("empty_callback", EmptyCallback);
 
     callbacks_done = 0;
     u64 MAX_CALLBACKS = 10;
@@ -133,8 +140,10 @@ TEST_CASE("Core::Timing[PredictableLateness]", "[core]") {
     ScopeInit guard;
     auto& core_timing = guard.core_timing;
 
-    Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>);
-    Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>);
+    std::shared_ptr<Core::Timing::EventType> cb_a =
+        Core::Timing::CreateEvent("callbackA", CallbackTemplate<0>);
+    std::shared_ptr<Core::Timing::EventType> cb_b =
+        Core::Timing::CreateEvent("callbackB", CallbackTemplate<1>);
 
     // Enter slice 0
     core_timing.ResetRun();
@@ -145,60 +154,3 @@ TEST_CASE("Core::Timing[PredictableLateness]", "[core]") {
     AdvanceAndCheck(core_timing, 0, 0, 10, -10); // (100 - 10)
     AdvanceAndCheck(core_timing, 1, 1, 50, -50);
 }
-
-namespace ChainSchedulingTest {
-static int reschedules = 0;
-
-static void RescheduleCallback(Core::Timing::CoreTiming& core_timing, u64 userdata,
-                               s64 cycles_late) {
-    --reschedules;
-    REQUIRE(reschedules >= 0);
-    REQUIRE(lateness == cycles_late);
-
-    if (reschedules > 0) {
-        core_timing.ScheduleEvent(1000, reinterpret_cast<Core::Timing::EventType*>(userdata),
-                                  userdata);
-    }
-}
-} // namespace ChainSchedulingTest
-
-TEST_CASE("CoreTiming[ChainScheduling]", "[core]") {
-    using namespace ChainSchedulingTest;
-
-    ScopeInit guard;
-    auto& core_timing = guard.core_timing;
-
-    Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>);
-    Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>);
-    Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", CallbackTemplate<2>);
-    Core::Timing::EventType* cb_rs = core_timing.RegisterEvent(
-        "callbackReschedule", [&core_timing](u64 userdata, s64 cycles_late) {
-            RescheduleCallback(core_timing, userdata, cycles_late);
-        });
-
-    // Enter slice 0
-    core_timing.ResetRun();
-
-    core_timing.ScheduleEvent(800, cb_a, CB_IDS[0]);
-    core_timing.ScheduleEvent(1000, cb_b, CB_IDS[1]);
-    core_timing.ScheduleEvent(2200, cb_c, CB_IDS[2]);
-    core_timing.ScheduleEvent(1000, cb_rs, reinterpret_cast<u64>(cb_rs));
-    REQUIRE(800 == core_timing.GetDowncount());
-
-    reschedules = 3;
-    AdvanceAndCheck(core_timing, 0, 0); // cb_a
-    AdvanceAndCheck(core_timing, 1, 1); // cb_b, cb_rs
-    REQUIRE(2 == reschedules);
-
-    core_timing.AddTicks(core_timing.GetDowncount());
-    core_timing.Advance(); // cb_rs
-    core_timing.SwitchContext(3);
-    REQUIRE(1 == reschedules);
-    REQUIRE(200 == core_timing.GetDowncount());
-
-    AdvanceAndCheck(core_timing, 2, 3); // cb_c
-
-    core_timing.AddTicks(core_timing.GetDowncount());
-    core_timing.Advance(); // cb_rs
-    REQUIRE(0 == reschedules);
-}
-- 
cgit v1.2.3-70-g09d2