ControllerInterface: Remove OSX window handle
also make it more thread safe (avoid rare deadlock) and fix it trying to add devices before the CI has init
This commit is contained in:
parent
2376aec135
commit
c238e49119
|
@ -64,9 +64,7 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi)
|
||||||
// nothing needed
|
// nothing needed
|
||||||
#endif
|
#endif
|
||||||
#ifdef CIFACE_USE_OSX
|
#ifdef CIFACE_USE_OSX
|
||||||
if (m_wsi.type == WindowSystemType::MacOS)
|
// nothing needed for OSX and Quartz
|
||||||
ciface::OSX::Init(wsi.render_window);
|
|
||||||
// nothing needed for Quartz
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CIFACE_USE_SDL
|
#ifdef CIFACE_USE_SDL
|
||||||
ciface::SDL::Init();
|
ciface::SDL::Init();
|
||||||
|
@ -118,6 +116,18 @@ void ControllerInterface::RefreshDevices(RefreshReason reason)
|
||||||
if (!m_is_init)
|
if (!m_is_init)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef CIFACE_USE_OSX
|
||||||
|
if (m_wsi.type == WindowSystemType::MacOS)
|
||||||
|
{
|
||||||
|
std::lock_guard lk_pre_population(m_pre_population_mutex);
|
||||||
|
// This is needed to stop its threads before locking our mutexes, to avoid deadlocks
|
||||||
|
// (in case it tried to add a device after we had locked m_devices_population_mutex).
|
||||||
|
// There doesn't seem to be an easy to way to repopulate OSX devices without restarting
|
||||||
|
// its hotplug thread. This will not release its devices, that's still done below.
|
||||||
|
ciface::OSX::DeInit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// This lock has two main functions:
|
// This lock has two main functions:
|
||||||
// -Avoid a deadlock between m_devices_mutex and ControllerEmu::s_state_mutex when
|
// -Avoid a deadlock between m_devices_mutex and ControllerEmu::s_state_mutex when
|
||||||
// InvokeDevicesChangedCallbacks() is called concurrently by two different threads.
|
// InvokeDevicesChangedCallbacks() is called concurrently by two different threads.
|
||||||
|
@ -152,7 +162,10 @@ void ControllerInterface::RefreshDevices(RefreshReason reason)
|
||||||
#ifdef CIFACE_USE_OSX
|
#ifdef CIFACE_USE_OSX
|
||||||
if (m_wsi.type == WindowSystemType::MacOS)
|
if (m_wsi.type == WindowSystemType::MacOS)
|
||||||
{
|
{
|
||||||
ciface::OSX::PopulateDevices(m_wsi.render_window);
|
{
|
||||||
|
std::lock_guard lk_pre_population(m_pre_population_mutex);
|
||||||
|
ciface::OSX::Init();
|
||||||
|
}
|
||||||
ciface::Quartz::PopulateDevices(m_wsi.render_window);
|
ciface::Quartz::PopulateDevices(m_wsi.render_window);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -116,6 +116,7 @@ private:
|
||||||
|
|
||||||
std::list<std::function<void()>> m_devices_changed_callbacks;
|
std::list<std::function<void()>> m_devices_changed_callbacks;
|
||||||
mutable std::recursive_mutex m_devices_population_mutex;
|
mutable std::recursive_mutex m_devices_population_mutex;
|
||||||
|
mutable std::mutex m_pre_population_mutex;
|
||||||
mutable std::mutex m_callbacks_mutex;
|
mutable std::mutex m_callbacks_mutex;
|
||||||
std::atomic<bool> m_is_init;
|
std::atomic<bool> m_is_init;
|
||||||
// This is now always protected by m_devices_population_mutex, so
|
// This is now always protected by m_devices_population_mutex, so
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
namespace ciface::OSX
|
namespace ciface::OSX
|
||||||
{
|
{
|
||||||
void Init(void* window);
|
void Init();
|
||||||
void PopulateDevices(void* window);
|
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
|
||||||
void DeviceElementDebugPrint(const void*, void*);
|
void DeviceElementDebugPrint(const void*, void*);
|
||||||
|
|
|
@ -135,8 +135,6 @@ static void DeviceDebugPrint(IOHIDDeviceRef device)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* g_window;
|
|
||||||
|
|
||||||
static std::string GetDeviceRefName(IOHIDDeviceRef inIOHIDDeviceRef)
|
static std::string GetDeviceRefName(IOHIDDeviceRef inIOHIDDeviceRef)
|
||||||
{
|
{
|
||||||
const NSString* name = reinterpret_cast<const NSString*>(
|
const NSString* name = reinterpret_cast<const NSString*>(
|
||||||
|
@ -172,10 +170,8 @@ static void DeviceMatchingCallback(void* inContext, IOReturn inResult, void* inS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(void* window)
|
void Init()
|
||||||
{
|
{
|
||||||
g_window = window;
|
|
||||||
|
|
||||||
HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||||
if (!HIDManager)
|
if (!HIDManager)
|
||||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "Failed to create HID Manager reference");
|
ERROR_LOG_FMT(CONTROLLERINTERFACE, "Failed to create HID Manager reference");
|
||||||
|
@ -210,19 +206,17 @@ void Init(void* window)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopulateDevices(void* window)
|
|
||||||
{
|
|
||||||
DeInit();
|
|
||||||
Init(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeInit()
|
void DeInit()
|
||||||
{
|
{
|
||||||
s_stopper.Signal();
|
if (HIDManager)
|
||||||
s_hotplug_thread.join();
|
{
|
||||||
|
s_stopper.Signal();
|
||||||
|
s_hotplug_thread.join();
|
||||||
|
|
||||||
// This closes all devices as well
|
// This closes all devices as well
|
||||||
IOHIDManagerClose(HIDManager, kIOHIDOptionsTypeNone);
|
IOHIDManagerClose(HIDManager, kIOHIDOptionsTypeNone);
|
||||||
CFRelease(HIDManager);
|
CFRelease(HIDManager);
|
||||||
|
HIDManager = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace ciface::OSX
|
} // namespace ciface::OSX
|
||||||
|
|
Loading…
Reference in New Issue