[PATCH 1/3] xinput1_3: Create a new background update thread.

Rémi Bernon rbernon at codeweavers.com
Fri Aug 6 04:05:56 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/xinput1_3/hid.c            | 49 ++++++++++++++++++++++++++++++++-
 dlls/xinput1_3/xinput_main.c    |  2 +-
 dlls/xinput1_3/xinput_private.h |  2 +-
 3 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/dlls/xinput1_3/hid.c b/dlls/xinput1_3/hid.c
index 00907b54bed..176e18fd95c 100644
--- a/dlls/xinput1_3/hid.c
+++ b/dlls/xinput1_3/hid.c
@@ -70,6 +70,8 @@ struct hid_platform_private {
 };
 
 static DWORD last_check = 0;
+static HANDLE stop_event;
+static HANDLE done_event;
 
 static BOOL find_opened_device(SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, int *free_slot)
 {
@@ -85,6 +87,40 @@ static BOOL find_opened_device(SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail, int *f
     return FALSE;
 }
 
+static DWORD WINAPI hid_update_thread_proc(void *param)
+{
+    HANDLE events[1];
+    DWORD count, ret;
+
+    do
+    {
+        count = 0;
+        events[count++] = stop_event;
+    }
+    while ((ret = WaitForMultipleObjectsEx( count, events, FALSE, INFINITE, TRUE )) < count - 1);
+
+    if (ret != count - 1) ERR("update thread exited unexpectedly, ret %u\n", ret);
+    SetEvent(done_event);
+    return ret;
+}
+
+static BOOL WINAPI start_update_thread( INIT_ONCE *once, void *param, void **context )
+{
+    HANDLE thread;
+
+    stop_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+    if (!stop_event) ERR("failed to create stop event, error %u\n", GetLastError());
+
+    done_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+    if (!done_event) ERR("failed to create stop event, error %u\n", GetLastError());
+
+    thread = CreateThread(NULL, 0, hid_update_thread_proc, NULL, 0, NULL);
+    if (!thread) ERR("failed to create update thread, error %u\n", GetLastError());
+    CloseHandle(thread);
+
+    return TRUE;
+}
+
 static void MarkUsage(struct hid_platform_private *private, WORD usage, LONG min, LONG max, USHORT bits)
 {
     struct axis_info info = {min, max-min, bits};
@@ -223,6 +259,8 @@ failed:
 
 void HID_find_gamepads(void)
 {
+    static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
+
     char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)];
     SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)buffer;
     HDEVINFO device_info_set;
@@ -235,6 +273,8 @@ void HID_find_gamepads(void)
     DWORD idx;
     int i;
 
+    InitOnceExecuteOnce(&init_once, start_update_thread, NULL, NULL);
+
     idx = GetTickCount();
     if ((idx - last_check) < 2000)
         return;
@@ -317,9 +357,16 @@ static void remove_gamepad(xinput_controller *device)
     LeaveCriticalSection(&device->crit);
 }
 
-void HID_destroy_gamepads(void)
+void HID_stop_update_thread(void)
 {
     int i;
+
+    SetEvent(stop_event);
+    WaitForSingleObject(done_event, INFINITE);
+
+    CloseHandle(stop_event);
+    CloseHandle(done_event);
+
     for (i = 0; i < XUSER_MAX_COUNT; i++)
         remove_gamepad(&controllers[i]);
 }
diff --git a/dlls/xinput1_3/xinput_main.c b/dlls/xinput1_3/xinput_main.c
index 2d9f54c83f2..547247dc76e 100644
--- a/dlls/xinput1_3/xinput_main.c
+++ b/dlls/xinput1_3/xinput_main.c
@@ -104,7 +104,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
             break;
         case DLL_PROCESS_DETACH:
             if (reserved) break;
-            HID_destroy_gamepads();
+            HID_stop_update_thread();
             break;
     }
     return TRUE;
diff --git a/dlls/xinput1_3/xinput_private.h b/dlls/xinput1_3/xinput_private.h
index 2bf16c0ffce..79c3023c543 100644
--- a/dlls/xinput1_3/xinput_private.h
+++ b/dlls/xinput1_3/xinput_private.h
@@ -31,7 +31,7 @@ extern CRITICAL_SECTION xinput_crit;
 extern xinput_controller controllers[XUSER_MAX_COUNT];
 
 void HID_find_gamepads(void) DECLSPEC_HIDDEN;
-void HID_destroy_gamepads(void) DECLSPEC_HIDDEN;
+void HID_stop_update_thread(void) DECLSPEC_HIDDEN;
 void HID_update_state(xinput_controller* device, XINPUT_STATE *state) DECLSPEC_HIDDEN;
 DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state) DECLSPEC_HIDDEN;
 void HID_enable(xinput_controller* device, BOOL enable) DECLSPEC_HIDDEN;
-- 
2.32.0




More information about the wine-devel mailing list