Added thread-safe initialization/cleanup support

Also went through and removed inappropriate uses of spinlocks.

Fixes https://github.com/libsdl-org/SDL/issues/10872
This commit is contained in:
Sam Lantinga
2024-09-16 22:45:37 -07:00
parent 7edd43c276
commit 9275c533ca
7 changed files with 208 additions and 132 deletions

View File

@@ -87,7 +87,7 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
#endif
};
static int SDL_HIDAPI_numdrivers = 0;
static SDL_SpinLock SDL_HIDAPI_spinlock;
static SDL_AtomicInt SDL_HIDAPI_updating_devices;
static bool SDL_HIDAPI_hints_changed = false;
static Uint32 SDL_HIDAPI_change_count = 0;
static SDL_HIDAPI_Device *SDL_HIDAPI_devices SDL_GUARDED_BY(SDL_joystick_lock);
@@ -1243,6 +1243,16 @@ static bool HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id, SDL
return false;
}
static bool HIDAPI_StartUpdatingDevices()
{
return SDL_AtomicCompareAndSwap(&SDL_HIDAPI_updating_devices, false, true);
}
static void HIDAPI_FinishUpdatingDevices()
{
SDL_AtomicSet(&SDL_HIDAPI_updating_devices, false);
}
bool HIDAPI_IsDeviceTypePresent(SDL_GamepadType type)
{
SDL_HIDAPI_Device *device;
@@ -1253,9 +1263,9 @@ bool HIDAPI_IsDeviceTypePresent(SDL_GamepadType type)
return false;
}
if (SDL_TryLockSpinlock(&SDL_HIDAPI_spinlock)) {
if (HIDAPI_StartUpdatingDevices()) {
HIDAPI_UpdateDeviceList();
SDL_UnlockSpinlock(&SDL_HIDAPI_spinlock);
HIDAPI_FinishUpdatingDevices();
}
SDL_LockJoysticks();
@@ -1298,9 +1308,9 @@ bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version,
}
#endif // SDL_JOYSTICK_HIDAPI_XBOX360 || SDL_JOYSTICK_HIDAPI_XBOXONE
if (supported) {
if (SDL_TryLockSpinlock(&SDL_HIDAPI_spinlock)) {
if (HIDAPI_StartUpdatingDevices()) {
HIDAPI_UpdateDeviceList();
SDL_UnlockSpinlock(&SDL_HIDAPI_spinlock);
HIDAPI_FinishUpdatingDevices();
}
}
@@ -1360,13 +1370,13 @@ SDL_GamepadType HIDAPI_GetGamepadTypeFromGUID(SDL_GUID guid)
static void HIDAPI_JoystickDetect(void)
{
if (SDL_TryLockSpinlock(&SDL_HIDAPI_spinlock)) {
if (HIDAPI_StartUpdatingDevices()) {
Uint32 count = SDL_hid_device_change_count();
if (SDL_HIDAPI_change_count != count) {
SDL_HIDAPI_change_count = count;
HIDAPI_UpdateDeviceList();
}
SDL_UnlockSpinlock(&SDL_HIDAPI_spinlock);
HIDAPI_FinishUpdatingDevices();
}
}
@@ -1379,7 +1389,7 @@ void HIDAPI_UpdateDevices(void)
// Update the devices, which may change connected joysticks and send events
// Prepare the existing device list
if (SDL_TryLockSpinlock(&SDL_HIDAPI_spinlock)) {
if (HIDAPI_StartUpdatingDevices()) {
for (device = SDL_HIDAPI_devices; device; device = device->next) {
if (device->parent) {
continue;
@@ -1393,7 +1403,7 @@ void HIDAPI_UpdateDevices(void)
}
}
}
SDL_UnlockSpinlock(&SDL_HIDAPI_spinlock);
HIDAPI_FinishUpdatingDevices();
}
}