From 2376aec135d957ee74bd2be1d587539dea4d5dab Mon Sep 17 00:00:00 2001 From: Filoppi Date: Sat, 15 May 2021 12:06:12 +0300 Subject: ControllerInterface: Refactor -Fix Add/Remove/Refresh device safety, devices could be added and removed at the same time, causing missing or duplicated devices (rare but possible) -Fix other devices population race conditions in ControllerInterface -Avoid re-creating all devices when dolphin is being shut down -Avoid re-creating devices when the render window handle has changed (just the relevantr ones now) -Avoid sending Devices Changed events if devices haven't actually changed -Made most devices populations will be made async, to increase performance and avoid hanging the host or CPU thread on manual devices refresh --- .../ControllerInterface/ControllerInterface.h | 38 +++++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'Source/Core/InputCommon/ControllerInterface/ControllerInterface.h') diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h index 024548b713..826659941d 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h @@ -60,13 +60,35 @@ class ControllerInterface : public ciface::Core::DeviceContainer public: using HotplugCallbackHandle = std::list>::iterator; + enum class WindowChangeReason + { + // Application is shutting down + Exit, + Other + }; + + enum class RefreshReason + { + // Only the window changed. + WindowChangeOnly, + // User requested, or any other internal reason (e.g. init). + // The window might have changed anyway. + Other + }; + ControllerInterface() : m_is_init(false) {} void Initialize(const WindowSystemInfo& wsi); - void ChangeWindow(void* hwnd); - void RefreshDevices(); + // Only call from one thread at a time. + void ChangeWindow(void* hwnd, WindowChangeReason reason = WindowChangeReason::Other); + // Can be called by any thread at any time (when initialized). + void RefreshDevices(RefreshReason reason = RefreshReason::Other); void Shutdown(); - void AddDevice(std::shared_ptr device); - void RemoveDevice(std::function callback); + bool AddDevice(std::shared_ptr device); + // Removes all the devices the function returns true to. + // If all the devices shared ptrs need to be destroyed immediately, + // set force_devices_release to true. + void RemoveDevice(std::function callback, + bool force_devices_release = false); // This is mandatory to use on device populations functions that can be called concurrently by // more than one thread, or that are called by a single other thread. // Without this, our devices list might end up in a mixed state. @@ -90,10 +112,16 @@ public: static ciface::InputChannel GetCurrentInputChannel(); private: + void ClearDevices(); + std::list> m_devices_changed_callbacks; + mutable std::recursive_mutex m_devices_population_mutex; mutable std::mutex m_callbacks_mutex; std::atomic m_is_init; - std::atomic m_is_populating_devices{false}; + // This is now always protected by m_devices_population_mutex, so + // it doesn't really need to be a counter or atomic anymore (it could be a raw bool), + // but we keep it so for simplicity, in case we changed the design. + std::atomic m_populating_devices_counter; WindowSystemInfo m_wsi; std::atomic m_aspect_ratio_adjustment = 1; }; -- cgit v1.2.3