glwindow/win32: Don't use condition variables for message synchronization
authorNirbheek Chauhan <nirbheek@centricular.com>
Mon, 11 Mar 2019 11:29:36 +0000 (16:59 +0530)
committerMatthew Waters <matthew@centricular.com>
Tue, 12 Mar 2019 03:21:57 +0000 (03:21 +0000)
Using a single condition variable for synchronization across all GL
messages is very slow on Windows and uses up to 20% CPU usage in some
workloads due to lock contention and false broadcasts.

Using per-message event handles reduces the CPU usage to negligible
amounts despite having to allocate a new event handle for each
message.

gst-libs/gst/gl/win32/gstglwindow_win32.c

index 67fc0b6..96280f9 100644 (file)
@@ -61,6 +61,8 @@ static void gst_gl_window_win32_draw (GstGLWindow * window);
 gboolean gst_gl_window_win32_open (GstGLWindow * window, GError ** error);
 void gst_gl_window_win32_close (GstGLWindow * window);
 static void release_parent_win_id (GstGLWindowWin32 * window_win32);
+static void gst_gl_window_win32_send_message (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data);
 
 static void
 gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass)
@@ -77,6 +79,8 @@ gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass)
   window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_win32_show);
   window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_win32_open);
   window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_win32_close);
+  window_class->send_message =
+      GST_DEBUG_FUNCPTR (gst_gl_window_win32_send_message);
 }
 
 static void
@@ -500,3 +504,37 @@ sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
   return CallWindowProc (window_parent_proc, hWnd, uMsg, wParam, lParam);
 }
+
+typedef struct _GstGLWin32SyncMessage
+{
+  GstGLWindowCB callback;
+  gpointer data;
+
+  HANDLE *event;
+} GstGLWin32SyncMessage;
+
+static void
+_run_message_sync (GstGLWin32SyncMessage * message)
+{
+  if (message->callback)
+    message->callback (message->data);
+
+  SetEvent (message->event);
+}
+
+void
+gst_gl_window_win32_send_message (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data)
+{
+  GstGLWin32SyncMessage message;
+
+  message.callback = callback;
+  message.data = data;
+  message.event = CreateEvent (NULL, FALSE, FALSE, NULL);
+
+  gst_gl_window_send_message_async (window, (GstGLWindowCB) _run_message_sync,
+      &message, NULL);
+
+  WaitForSingleObject (message.event, INFINITE);
+  CloseHandle (message.event);
+}