[evolution-data-server] Bug 699223 - Emit view signals from context where view was started



commit 417164c733128072ea3e4ad685829f0c3270c1b7
Author: Matthew Barnes <mbarnes redhat com>
Date:   Fri May 3 13:14:53 2013 -0400

    Bug 699223 - Emit view signals from context where view was started
    
    This applies to both EBookClientView and ECalClientView.
    
    Incoming D-Bus signals were being propagated to the EClient's main loop
    context, but there may not be a running main loop on that thread, so the
    main loop sources were never being dispatched and the view signals never
    emitted.
    
    Instead use the main loop context which was the thread-default at the
    time the view was started, which is often the so-called "main" thread
    where a main loop is more likely to be running.

 addressbook/libebook/e-book-client-view.c |   60 ++++++++++++++++++++++++++--
 calendar/libecal/e-cal-client-view.c      |   60 ++++++++++++++++++++++++++--
 2 files changed, 110 insertions(+), 10 deletions(-)
---
diff --git a/addressbook/libebook/e-book-client-view.c b/addressbook/libebook/e-book-client-view.c
index f6ab999..86592a2 100644
--- a/addressbook/libebook/e-book-client-view.c
+++ b/addressbook/libebook/e-book-client-view.c
@@ -47,6 +47,9 @@ struct _EBookClientViewPrivate {
        guint running : 1;
        guint complete : 1;
 
+       GMainContext *main_context;
+       GMutex main_context_lock;
+
        EBookBackend *direct_backend;
 
        gulong objects_added_handler_id;
@@ -122,6 +125,38 @@ signal_closure_free (SignalClosure *signal_closure)
        g_slice_free (SignalClosure, signal_closure);
 }
 
+static GMainContext *
+book_client_view_ref_main_context (EBookClientView *client_view)
+{
+       GMainContext *main_context;
+
+       /* Intentionally not checking for NULL so we get a console
+        * warning if we try to reference a NULL main context, but
+        * that should never happen. */
+
+       g_mutex_lock (&client_view->priv->main_context_lock);
+
+       main_context = g_main_context_ref (client_view->priv->main_context);
+
+       g_mutex_unlock (&client_view->priv->main_context_lock);
+
+       return main_context;
+}
+
+static void
+book_client_view_set_main_context (EBookClientView *client_view,
+                                   GMainContext *main_context)
+{
+       g_mutex_lock (&client_view->priv->main_context_lock);
+
+       if (client_view->priv->main_context != NULL)
+               g_main_context_unref (client_view->priv->main_context);
+
+       client_view->priv->main_context = g_main_context_ref (main_context);
+
+       g_mutex_unlock (&client_view->priv->main_context_lock);
+}
+
 static gboolean
 book_client_view_emit_objects_added_idle_cb (gpointer user_data)
 {
@@ -238,7 +273,7 @@ book_client_view_emit_objects_added (EBookClientView *client_view,
        g_weak_ref_set (&signal_closure->client_view, client_view);
        signal_closure->object_list = object_list;  /* takes ownership */
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = book_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -274,7 +309,7 @@ book_client_view_emit_objects_modified (EBookClientView *client_view,
        g_weak_ref_set (&signal_closure->client_view, client_view);
        signal_closure->object_list = object_list;  /* takes ownership */
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = book_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -518,7 +553,7 @@ book_client_view_objects_removed_cb (EGdbusBookView *object,
        g_weak_ref_set (&signal_closure->client_view, client_view);
        signal_closure->string_list = g_slist_reverse (list);
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = book_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -560,7 +595,7 @@ book_client_view_progress_cb (EGdbusBookView *object,
        signal_closure->message = g_strdup (message);
        signal_closure->percent = percent;
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = book_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -600,7 +635,7 @@ book_client_view_complete_cb (EGdbusBookView *object,
        g_weak_ref_set (&signal_closure->client_view, client_view);
        e_gdbus_templates_decode_error (in_error_strv, &signal_closure->error);
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = book_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -758,6 +793,11 @@ book_client_view_dispose (GObject *object)
                priv->connection = NULL;
        }
 
+       if (priv->main_context != NULL) {
+               g_main_context_unref (priv->main_context);
+               priv->main_context = NULL;
+       }
+
        if (priv->direct_backend != NULL) {
                g_object_unref (priv->direct_backend);
                priv->direct_backend = NULL;
@@ -802,6 +842,8 @@ book_client_view_finalize (GObject *object)
 
        g_free (priv->object_path);
 
+       g_mutex_clear (&priv->main_context_lock);
+
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_book_client_view_parent_class)->finalize (object);
 }
@@ -985,6 +1027,8 @@ static void
 e_book_client_view_init (EBookClientView *client_view)
 {
        client_view->priv = E_BOOK_CLIENT_VIEW_GET_PRIVATE (client_view);
+
+       g_mutex_init (&client_view->priv->main_context_lock);
 }
 
 /**
@@ -1083,10 +1127,16 @@ void
 e_book_client_view_start (EBookClientView *client_view,
                           GError **error)
 {
+       GMainContext *main_context;
        GError *local_error = NULL;
 
        g_return_if_fail (E_IS_BOOK_CLIENT_VIEW (client_view));
 
+       /* Emit signals from the current thread-default main context. */
+       main_context = g_main_context_ref_thread_default ();
+       book_client_view_set_main_context (client_view, main_context);
+       g_main_context_unref (main_context);
+
        client_view->priv->running = TRUE;
 
        e_gdbus_book_view_call_start_sync (
diff --git a/calendar/libecal/e-cal-client-view.c b/calendar/libecal/e-cal-client-view.c
index 4f56a33..c31e9fc 100644
--- a/calendar/libecal/e-cal-client-view.c
+++ b/calendar/libecal/e-cal-client-view.c
@@ -46,6 +46,9 @@ struct _ECalClientViewPrivate {
        gchar *object_path;
        gboolean running;
 
+       GMainContext *main_context;
+       GMutex main_context_lock;
+
        gulong objects_added_handler_id;
        gulong objects_modified_handler_id;
        gulong objects_removed_handler_id;
@@ -112,6 +115,38 @@ signal_closure_free (SignalClosure *signal_closure)
        g_slice_free (SignalClosure, signal_closure);
 }
 
+static GMainContext *
+cal_client_view_ref_main_context (ECalClientView *client_view)
+{
+       GMainContext *main_context;
+
+       /* Intentionally not checking for NULL so we get a console
+        * warning if we try to reference a NULL main context, but
+        * that should never happen. */
+
+       g_mutex_lock (&client_view->priv->main_context_lock);
+
+       main_context = g_main_context_ref (client_view->priv->main_context);
+
+       g_mutex_unlock (&client_view->priv->main_context_lock);
+
+       return main_context;
+}
+
+static void
+cal_client_view_set_main_context (ECalClientView *client_view,
+                                  GMainContext *main_context)
+{
+       g_mutex_lock (&client_view->priv->main_context_lock);
+
+       if (client_view->priv->main_context != NULL)
+               g_main_context_unref (client_view->priv->main_context);
+
+       client_view->priv->main_context = g_main_context_ref (main_context);
+
+       g_mutex_unlock (&client_view->priv->main_context_lock);
+}
+
 static GSList *
 build_object_list (const gchar * const *seq)
 {
@@ -281,7 +316,7 @@ cal_client_view_objects_added_cb (EGdbusCalView *dbus_proxy,
        g_weak_ref_set (&signal_closure->client_view, client_view);
        signal_closure->component_list = build_object_list (objects);
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = cal_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -321,7 +356,7 @@ cal_client_view_objects_modified_cb (EGdbusCalView *dbus_proxy,
        g_weak_ref_set (&signal_closure->client_view, client_view);
        signal_closure->component_list = build_object_list (objects);
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = cal_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -361,7 +396,7 @@ cal_client_view_objects_removed_cb (EGdbusCalView *dbus_proxy,
        g_weak_ref_set (&signal_closure->client_view, client_view);
        signal_closure->component_id_list = build_id_list (uids);
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = cal_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -403,7 +438,7 @@ cal_client_view_progress_cb (EGdbusCalView *dbus_proxy,
        signal_closure->message = g_strdup (message);
        signal_closure->percent = percent;
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = cal_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -443,7 +478,7 @@ cal_client_view_complete_cb (EGdbusCalView *dbus_proxy,
        g_weak_ref_set (&signal_closure->client_view, client_view);
        e_gdbus_templates_decode_error (arg_error, &signal_closure->error);
 
-       main_context = e_client_ref_main_context (E_CLIENT (client));
+       main_context = cal_client_view_ref_main_context (client_view);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -580,6 +615,11 @@ cal_client_view_dispose (GObject *object)
                priv->connection = NULL;
        }
 
+       if (priv->main_context != NULL) {
+               g_main_context_unref (priv->main_context);
+               priv->main_context = NULL;
+       }
+
        if (priv->dbus_proxy != NULL) {
                g_signal_handler_disconnect (
                        priv->dbus_proxy,
@@ -619,6 +659,8 @@ cal_client_view_finalize (GObject *object)
 
        g_free (priv->object_path);
 
+       g_mutex_clear (&priv->main_context_lock);
+
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_cal_client_view_parent_class)->finalize (object);
 }
@@ -797,6 +839,8 @@ static void
 e_cal_client_view_init (ECalClientView *client_view)
 {
        client_view->priv = E_CAL_CLIENT_VIEW_GET_PRIVATE (client_view);
+
+       g_mutex_init (&client_view->priv->main_context_lock);
 }
 
 /**
@@ -916,10 +960,16 @@ void
 e_cal_client_view_start (ECalClientView *client_view,
                          GError **error)
 {
+       GMainContext *main_context;
        GError *local_error = NULL;
 
        g_return_if_fail (E_IS_CAL_CLIENT_VIEW (client_view));
 
+       /* Emit signals from the current thread-default main context. */
+       main_context = g_main_context_ref_thread_default ();
+       cal_client_view_set_main_context (client_view, main_context);
+       g_main_context_unref (main_context);
+
        client_view->priv->running = TRUE;
 
        e_gdbus_cal_view_call_start_sync (


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]