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



commit 6993e7be49170b3c7a3ce5e6cde912cd6b858247
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.
    
    (cherry picked from commit 417164c733128072ea3e4ad685829f0c3270c1b7)
    
    Conflicts:
        addressbook/libebook/e-book-client-view.c
        calendar/libecal/e-cal-client-view.c

 addressbook/libebook/e-book-client-view.c |   70 ++++++++++++++++++++++------
 calendar/libecal/e-cal-client-view.c      |   70 ++++++++++++++++++++++------
 2 files changed, 110 insertions(+), 30 deletions(-)
---
diff --git a/addressbook/libebook/e-book-client-view.c b/addressbook/libebook/e-book-client-view.c
index a66bade..25f47c9 100644
--- a/addressbook/libebook/e-book-client-view.c
+++ b/addressbook/libebook/e-book-client-view.c
@@ -48,6 +48,9 @@ struct _EBookClientViewPrivate {
        guint running : 1;
        guint complete : 1;
 
+       GMainContext *main_context;
+       GMutex main_context_lock;
+
        EDataBook *direct_book;
 
        gulong objects_added_handler_id;
@@ -123,6 +126,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)
 {
@@ -223,7 +258,6 @@ static void
 book_client_view_emit_objects_added (EBookClientView *client_view,
                                      GSList *object_list)
 {
-       EBookClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -232,8 +266,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 */
 
-       client = e_book_client_view_get_client (client_view);
-       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 (
@@ -251,7 +284,6 @@ static void
 book_client_view_emit_objects_modified (EBookClientView *client_view,
                                         GSList *object_list)
 {
-       EBookClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -260,8 +292,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 */
 
-       client = e_book_client_view_get_client (client_view);
-       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 (
@@ -460,7 +491,6 @@ book_client_view_objects_removed_cb (EGdbusBookView *object,
                                      const gchar * const *ids,
                                      EBookClientView *client_view)
 {
-       EBookClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -477,8 +507,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);
 
-       client = e_book_client_view_get_client (client_view);
-       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 (
@@ -498,7 +527,6 @@ book_client_view_progress_cb (EGdbusBookView *object,
                               const gchar *message,
                               EBookClientView *client_view)
 {
-       EBookClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -511,8 +539,7 @@ book_client_view_progress_cb (EGdbusBookView *object,
        signal_closure->message = g_strdup (message);
        signal_closure->percent = percent;
 
-       client = e_book_client_view_get_client (client_view);
-       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 (
@@ -531,7 +558,6 @@ book_client_view_complete_cb (EGdbusBookView *object,
                               const gchar * const *in_error_strv,
                               EBookClientView *client_view)
 {
-       EBookClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -543,8 +569,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);
 
-       client = e_book_client_view_get_client (client_view);
-       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 (
@@ -702,6 +727,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_book != NULL) {
                g_object_unref (priv->direct_book);
                priv->direct_book = NULL;
@@ -746,6 +776,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);
 }
@@ -935,6 +967,8 @@ static void
 e_book_client_view_init (EBookClientView *view)
 {
        view->priv = E_BOOK_CLIENT_VIEW_GET_PRIVATE (view);
+
+       g_mutex_init (&view->priv->main_context_lock);
 }
 
 /**
@@ -1000,10 +1034,16 @@ void
 e_book_client_view_start (EBookClientView *view,
                           GError **error)
 {
+       GMainContext *main_context;
        GError *local_error = NULL;
 
        g_return_if_fail (E_IS_BOOK_CLIENT_VIEW (view));
 
+       /* Emit signals from the current thread-default main context. */
+       main_context = g_main_context_ref_thread_default ();
+       book_client_view_set_main_context (view, main_context);
+       g_main_context_unref (main_context);
+
        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 5dd4270..8db2b05 100644
--- a/calendar/libecal/e-cal-client-view.c
+++ b/calendar/libecal/e-cal-client-view.c
@@ -48,6 +48,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;
@@ -114,6 +117,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)
 {
@@ -264,7 +299,6 @@ cal_client_view_objects_added_cb (EGdbusCalView *dbus_proxy,
                                   const gchar * const *objects,
                                   ECalClientView *client_view)
 {
-       ECalClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -276,8 +310,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);
 
-       client = e_cal_client_view_get_client (client_view);
-       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 (
@@ -296,7 +329,6 @@ cal_client_view_objects_modified_cb (EGdbusCalView *dbus_proxy,
                                      const gchar * const *objects,
                                      ECalClientView *client_view)
 {
-       ECalClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -308,8 +340,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);
 
-       client = e_cal_client_view_get_client (client_view);
-       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 (
@@ -328,7 +359,6 @@ cal_client_view_objects_removed_cb (EGdbusCalView *dbus_proxy,
                                     const gchar * const *uids,
                                     ECalClientView *client_view)
 {
-       ECalClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -340,8 +370,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);
 
-       client = e_cal_client_view_get_client (client_view);
-       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 +390,6 @@ cal_client_view_progress_cb (EGdbusCalView *dbus_proxy,
                              const gchar *message,
                              ECalClientView *client_view)
 {
-       ECalClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -374,8 +402,7 @@ cal_client_view_progress_cb (EGdbusCalView *dbus_proxy,
        signal_closure->message = g_strdup (message);
        signal_closure->percent = percent;
 
-       client = e_cal_client_view_get_client (client_view);
-       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 (
@@ -394,7 +421,6 @@ cal_client_view_complete_cb (EGdbusCalView *dbus_proxy,
                              const gchar * const *arg_error,
                              ECalClientView *client_view)
 {
-       ECalClient *client;
        GSource *idle_source;
        GMainContext *main_context;
        SignalClosure *signal_closure;
@@ -406,8 +432,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);
 
-       client = e_cal_client_view_get_client (client_view);
-       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 (
@@ -546,6 +571,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,
@@ -585,6 +615,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);
 }
@@ -768,6 +800,8 @@ static void
 e_cal_client_view_init (ECalClientView *view)
 {
        view->priv = E_CAL_CLIENT_VIEW_GET_PRIVATE (view);
+
+       g_mutex_init (&view->priv->main_context_lock);
 }
 
 /**
@@ -854,10 +888,16 @@ void
 e_cal_client_view_start (ECalClientView *view,
                          GError **error)
 {
+       GMainContext *main_context;
        GError *local_error = NULL;
 
        g_return_if_fail (E_IS_CAL_CLIENT_VIEW (view));
 
+       /* Emit signals from the current thread-default main context. */
+       main_context = g_main_context_ref_thread_default ();
+       cal_client_view_set_main_context (view, main_context);
+       g_main_context_unref (main_context);
+
        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]