glwindow: Use g_thread_join() instead of a custom condition variable for waiting for the navigation thread to finish

Also hide some internal functions and fields while we're at it and fix
a race condition with the startup condition variable.
This commit is contained in:
Sebastian Dröge 2015-12-21 10:46:52 +01:00
parent 62d79ae326
commit 0952b3f986
2 changed files with 52 additions and 90 deletions

View file

@ -85,10 +85,6 @@ static void gst_gl_window_default_send_message (GstGLWindow * window,
static void gst_gl_window_default_send_message_async (GstGLWindow * window, static void gst_gl_window_default_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
static gpointer gst_gl_window_navigation_thread (GstGLWindow * window); static gpointer gst_gl_window_navigation_thread (GstGLWindow * window);
void gst_gl_window_run_navigation (GstGLWindow * window);
void gst_gl_window_open_navigation (GstGLWindow * window);
void gst_gl_window_close_navigation (GstGLWindow * window);
void gst_gl_window_quit_navigation (GstGLWindow * window);
struct _GstGLWindowPrivate struct _GstGLWindowPrivate
{ {
@ -100,6 +96,10 @@ struct _GstGLWindowPrivate
guint surface_height; guint surface_height;
gboolean alive; gboolean alive;
GMutex nav_lock;
GCond nav_create_cond;
gboolean nav_alive;
}; };
static void gst_gl_window_finalize (GObject * object); static void gst_gl_window_finalize (GObject * object);
@ -187,13 +187,12 @@ gst_gl_window_init (GstGLWindow * window)
window->priv = priv; window->priv = priv;
g_mutex_init (&window->lock); g_mutex_init (&window->lock);
g_mutex_init (&window->nav_lock);
g_cond_init (&window->nav_create_cond);
g_cond_init (&window->nav_destroy_cond);
window->nav_created = FALSE;
window->nav_alive = FALSE;
window->is_drawing = FALSE; window->is_drawing = FALSE;
g_mutex_init (&window->priv->nav_lock);
g_cond_init (&window->priv->nav_create_cond);
window->priv->nav_alive = FALSE;
g_weak_ref_init (&window->context_ref, NULL); g_weak_ref_init (&window->context_ref, NULL);
priv->main_context = g_main_context_new (); priv->main_context = g_main_context_new ();
@ -310,16 +309,13 @@ gst_gl_window_new (GstGLDisplay * display)
window->display = gst_object_ref (display); window->display = gst_object_ref (display);
g_mutex_lock (&window->nav_lock); g_mutex_lock (&window->priv->nav_lock);
window->priv->navigation_thread = g_thread_new ("gstglnavigation",
(GThreadFunc) gst_gl_window_navigation_thread, window);
if (!window->nav_created) { while (!window->priv->nav_alive)
window->priv->navigation_thread = g_thread_new ("gstglnavigation", g_cond_wait (&window->priv->nav_create_cond, &window->priv->nav_lock);
(GThreadFunc) gst_gl_window_navigation_thread, window); g_mutex_unlock (&window->priv->nav_lock);
g_cond_wait (&window->nav_create_cond, &window->nav_lock);
window->nav_created = TRUE;
}
g_mutex_unlock (&window->nav_lock);
return window; return window;
} }
@ -330,18 +326,11 @@ gst_gl_window_finalize (GObject * object)
GstGLWindow *window = GST_GL_WINDOW (object); GstGLWindow *window = GST_GL_WINDOW (object);
GstGLWindowPrivate *priv = window->priv; GstGLWindowPrivate *priv = window->priv;
if (window->nav_alive) { GST_INFO ("quit navigation loop");
g_mutex_lock (&window->nav_lock); g_main_loop_quit (window->navigation_loop);
GST_INFO ("send quit navigation loop"); /* wait until navigation thread finished */
gst_gl_window_quit_navigation (window); g_thread_join (window->priv->navigation_thread);
while (window->nav_alive) { window->priv->navigation_thread = NULL;
g_cond_wait (&window->nav_destroy_cond, &window->nav_lock);
}
/* release resource hold by navigation thread */
g_thread_join(window->priv->navigation_thread);
window->priv->navigation_thread = NULL;
g_mutex_unlock (&window->nav_lock);
}
if (priv->loop) if (priv->loop)
g_main_loop_unref (priv->loop); g_main_loop_unref (priv->loop);
@ -352,9 +341,8 @@ gst_gl_window_finalize (GObject * object)
g_weak_ref_clear (&window->context_ref); g_weak_ref_clear (&window->context_ref);
g_mutex_clear (&window->lock); g_mutex_clear (&window->lock);
g_mutex_clear (&window->nav_lock); g_mutex_clear (&window->priv->nav_lock);
g_cond_clear (&window->nav_create_cond); g_cond_clear (&window->priv->nav_create_cond);
g_cond_clear (&window->nav_destroy_cond);
gst_object_unref (window->display); gst_object_unref (window->display);
G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object); G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object);
@ -561,23 +549,6 @@ gst_gl_window_run (GstGLWindow * window)
window_class->run (window); window_class->run (window);
} }
/**
* gst_gl_window_run_navigation:
* @window: a #GstGLWindow
*
* Start the execution of the navigation runloop.
*
* Since: 1.6
*/
void
gst_gl_window_run_navigation (GstGLWindow * window)
{
g_return_if_fail (GST_IS_GL_WINDOW (window));
g_return_if_fail (window->navigation_context != NULL);
g_return_if_fail (window->navigation_loop != NULL);
g_main_loop_run (window->navigation_loop);
}
static void static void
gst_gl_window_default_quit (GstGLWindow * window) gst_gl_window_default_quit (GstGLWindow * window)
{ {
@ -929,50 +900,46 @@ GType gst_gl_dummy_window_get_type (void);
G_DEFINE_TYPE (GstGLDummyWindow, gst_gl_dummy_window, GST_GL_TYPE_WINDOW); G_DEFINE_TYPE (GstGLDummyWindow, gst_gl_dummy_window, GST_GL_TYPE_WINDOW);
void static gboolean
gst_gl_window_open_navigation (GstGLWindow * window) gst_gl_window_navigation_started (gpointer data)
{ {
g_return_if_fail (GST_IS_GL_WINDOW (window)); GstGLWindow *window = data;
g_mutex_lock (&window->nav_lock);
window->navigation_context = g_main_context_new ();
window->navigation_loop = g_main_loop_new (window->navigation_context, FALSE);
g_main_context_push_thread_default (window->navigation_context);
window->nav_alive = TRUE;
g_cond_signal (&window->nav_create_cond);
g_mutex_unlock (&window->nav_lock);
}
void g_mutex_lock (&window->priv->nav_lock);
gst_gl_window_close_navigation (GstGLWindow * window) window->priv->nav_alive = TRUE;
{ g_cond_signal (&window->priv->nav_create_cond);
g_return_if_fail (GST_IS_GL_WINDOW (window)); g_mutex_unlock (&window->priv->nav_lock);
g_return_if_fail (window->navigation_context != NULL);
g_return_if_fail (window->navigation_loop != NULL);
g_mutex_lock (&window->nav_lock); return G_SOURCE_REMOVE;
window->nav_alive = FALSE;
g_main_context_pop_thread_default (window->navigation_context);
g_main_loop_unref (window->navigation_loop);
g_main_context_unref (window->navigation_context);
g_cond_signal (&window->nav_destroy_cond);
g_mutex_unlock (&window->nav_lock);
}
void
gst_gl_window_quit_navigation (GstGLWindow * window)
{
g_return_if_fail (GST_IS_GL_WINDOW (window));
g_main_loop_quit (window->navigation_loop);
} }
static gpointer static gpointer
gst_gl_window_navigation_thread (GstGLWindow * window) gst_gl_window_navigation_thread (GstGLWindow * window)
{ {
gst_gl_window_open_navigation (window); GSource *source;
gst_gl_window_run_navigation (window);
g_return_val_if_fail (GST_IS_GL_WINDOW (window), NULL);
window->navigation_context = g_main_context_new ();
window->navigation_loop = g_main_loop_new (window->navigation_context, FALSE);
g_main_context_push_thread_default (window->navigation_context);
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) gst_gl_window_navigation_started,
window, NULL);
g_source_attach (source, window->navigation_context);
g_source_unref (source);
g_main_loop_run (window->navigation_loop);
g_main_context_pop_thread_default (window->navigation_context);
g_main_loop_unref (window->navigation_loop);
g_main_context_unref (window->navigation_context);
window->navigation_loop = NULL;
window->navigation_context = NULL;
GST_INFO ("navigation loop exited\n"); GST_INFO ("navigation loop exited\n");
gst_gl_window_close_navigation (window);
return NULL; return NULL;
} }

View file

@ -67,11 +67,6 @@ struct _GstGLWindow {
GstObject parent; GstObject parent;
GMutex lock; GMutex lock;
GMutex nav_lock;
GCond nav_create_cond;
GCond nav_destroy_cond;
gboolean nav_created;
gboolean nav_alive;
GstGLDisplay *display; GstGLDisplay *display;
GWeakRef context_ref; GWeakRef context_ref;