Rémi Bernon : xinput1_3: Create a new background update thread.

Alexandre Julliard julliard at winehq.org
Wed Aug 11 16:42:16 CDT 2021


Module: wine
Branch: master
Commit: 40cb5510aea7f829b34daf66aee9bb8ec3f2620c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=40cb5510aea7f829b34daf66aee9bb8ec3f2620c

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Tue Aug 10 13:27:22 2021 +0200

xinput1_3: Create a new background update thread.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/xinput1_3/main.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c
index ae2670ba306..63f125ae528 100644
--- a/dlls/xinput1_3/main.c
+++ b/dlls/xinput1_3/main.c
@@ -119,6 +119,8 @@ static struct xinput_controller controllers[XUSER_MAX_COUNT] =
 };
 
 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)
 {
@@ -294,8 +296,12 @@ failed:
     return FALSE;
 }
 
+static BOOL WINAPI start_update_thread_once( INIT_ONCE *once, void *param, void **context );
+
 static 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;
     SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
@@ -308,6 +314,8 @@ static void HID_find_gamepads(void)
     GUID guid;
     int i;
 
+    InitOnceExecuteOnce(&init_once, start_update_thread_once, NULL, NULL);
+
     idx = GetTickCount();
     if ((idx - last_check) < 2000) return;
 
@@ -383,9 +391,16 @@ static void controller_destroy(struct xinput_controller *controller)
     LeaveCriticalSection(&controller->crit);
 }
 
-static void HID_destroy_gamepads(void)
+static void 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++) controller_destroy(&controllers[i]);
 }
 
@@ -523,6 +538,40 @@ static void HID_update_state(struct xinput_controller *controller, XINPUT_STATE
     memcpy(state, &controller->state, sizeof(*state));
 }
 
+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_once( 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 BOOL controller_lock(struct xinput_controller *controller)
 {
     if (!controller->device) return FALSE;
@@ -552,7 +601,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
         break;
     case DLL_PROCESS_DETACH:
         if (reserved) break;
-        HID_destroy_gamepads();
+        stop_update_thread();
         break;
     }
     return TRUE;




More information about the wine-cvs mailing list