EClient: Add a read-only "main-context" property.
authorMatthew Barnes <mbarnes@redhat.com>
Sat, 23 Feb 2013 15:16:56 +0000 (10:16 -0500)
committerMatthew Barnes <mbarnes@redhat.com>
Sat, 23 Feb 2013 15:30:49 +0000 (10:30 -0500)
This is the GMainContext on which to attach client event sources.

New functions:

    e_client_ref_main_context()

addressbook/libebook/e-book-client.c
calendar/libecal/e-cal-client.c
docs/reference/libedataserver/libedataserver-sections.txt
libedataserver/e-client.c
libedataserver/e-client.h

index 3560456..6d8bef7 100644 (file)
@@ -53,7 +53,6 @@ typedef struct _ConnectClosure ConnectClosure;
 typedef struct _RunInThreadClosure RunInThreadClosure;
 
 struct _EBookClientPrivate {
-       GMainContext *main_context;
        EDBusAddressBook *dbus_proxy;
        EDataBook *direct_book;
        guint name_watcher_id;
@@ -457,29 +456,34 @@ book_client_emit_backend_property_changed_idle_cb (gpointer user_data)
 static void
 book_client_dbus_proxy_error_cb (EDBusAddressBook *dbus_proxy,
                                  const gchar *error_message,
-                                 EBookClient *book_client)
+                                 EClient *client)
 {
        GSource *idle_source;
+       GMainContext *main_context;
        SignalClosure *signal_closure;
 
        signal_closure = g_slice_new0 (SignalClosure);
-       signal_closure->client = g_object_ref (book_client);
+       signal_closure->client = g_object_ref (client);
        signal_closure->error_message = g_strdup (error_message);
 
+       main_context = e_client_ref_main_context (client);
+
        idle_source = g_idle_source_new ();
        g_source_set_callback (
                idle_source,
                book_client_emit_backend_error_idle_cb,
                signal_closure,
                (GDestroyNotify) signal_closure_free);
-       g_source_attach (idle_source, book_client->priv->main_context);
+       g_source_attach (idle_source, main_context);
        g_source_unref (idle_source);
+
+       g_main_context_unref (main_context);
 }
 
 static void
 book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy,
                                   GParamSpec *pspec,
-                                  EBookClient *book_client)
+                                  EClient *client)
 {
        const gchar *backend_prop_name = NULL;
 
@@ -498,7 +502,7 @@ book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy,
                        csv = g_strjoinv (",", strv);
                        g_strfreev (strv);
                }
-               e_client_set_capabilities (E_CLIENT (book_client), csv);
+               e_client_set_capabilities (client, csv);
                g_free (csv);
        }
 
@@ -508,7 +512,7 @@ book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy,
                backend_prop_name = CLIENT_BACKEND_PROPERTY_ONLINE;
 
                online = e_dbus_address_book_get_online (dbus_proxy);
-               e_client_set_online (E_CLIENT (book_client), online);
+               e_client_set_online (client, online);
        }
 
        if (g_str_equal (pspec->name, "required-fields")) {
@@ -529,38 +533,46 @@ book_client_dbus_proxy_notify_cb (EDBusAddressBook *dbus_proxy,
                backend_prop_name = CLIENT_BACKEND_PROPERTY_READONLY;
 
                writable = e_dbus_address_book_get_writable (dbus_proxy);
-               e_client_set_readonly (E_CLIENT (book_client), !writable);
+               e_client_set_readonly (client, !writable);
        }
 
        if (backend_prop_name != NULL) {
                GSource *idle_source;
+               GMainContext *main_context;
                SignalClosure *signal_closure;
 
                signal_closure = g_slice_new0 (SignalClosure);
-               signal_closure->client = g_object_ref (book_client);
+               signal_closure->client = g_object_ref (client);
                signal_closure->property_name = g_strdup (backend_prop_name);
 
+               main_context = e_client_ref_main_context (client);
+
                idle_source = g_idle_source_new ();
                g_source_set_callback (
                        idle_source,
                        book_client_emit_backend_property_changed_idle_cb,
                        signal_closure,
                        (GDestroyNotify) signal_closure_free);
-               g_source_attach (idle_source, book_client->priv->main_context);
+               g_source_attach (idle_source, main_context);
                g_source_unref (idle_source);
+
+               g_main_context_unref (main_context);
        }
 }
 
 static void
 book_client_name_vanished_cb (GDBusConnection *connection,
                               const gchar *name,
-                              EBookClient *book_client)
+                              EClient *client)
 {
        GSource *idle_source;
+       GMainContext *main_context;
        SignalClosure *signal_closure;
 
        signal_closure = g_slice_new0 (SignalClosure);
-       signal_closure->client = g_object_ref (book_client);
+       signal_closure->client = g_object_ref (client);
+
+       main_context = e_client_ref_main_context (client);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -568,8 +580,10 @@ book_client_name_vanished_cb (GDBusConnection *connection,
                book_client_emit_backend_died_idle_cb,
                signal_closure,
                (GDestroyNotify) signal_closure_free);
-       g_source_attach (idle_source, book_client->priv->main_context);
+       g_source_attach (idle_source, main_context);
        g_source_unref (idle_source);
+
+       g_main_context_unref (main_context);
 }
 
 static void
@@ -621,11 +635,6 @@ book_client_dispose (GObject *object)
                priv->dbus_proxy = NULL;
        }
 
-       if (priv->main_context != NULL) {
-               g_main_context_unref (priv->main_context);
-               priv->main_context = NULL;
-       }
-
        if (book_client->priv->direct_book) {
                e_data_book_close_sync (book_client->priv->direct_book, NULL, NULL);
                g_object_unref (book_client->priv->direct_book);
@@ -995,10 +1004,6 @@ e_book_client_init (EBookClient *client)
        g_atomic_int_inc (&active_book_clients);
 
        client->priv = E_BOOK_CLIENT_GET_PRIVATE (client);
-
-       /* This is so the D-Bus thread can schedule signal emissions
-        * on the thread-default context for this thread. */
-       client->priv->main_context = g_main_context_ref_thread_default ();
 }
 
 /**
index 66e2563..e938b89 100644 (file)
@@ -54,7 +54,6 @@ typedef struct _ConnectClosure ConnectClosure;
 typedef struct _RunInThreadClosure RunInThreadClosure;
 
 struct _ECalClientPrivate {
-       GMainContext *main_context;
        EDBusCalendar *dbus_proxy;
        guint name_watcher_id;
 
@@ -574,29 +573,34 @@ cal_client_emit_timezone_added_idle_cb (gpointer user_data)
 static void
 cal_client_dbus_proxy_error_cb (EDBusCalendar *dbus_proxy,
                                 const gchar *error_message,
-                                ECalClient *cal_client)
+                                EClient *client)
 {
        GSource *idle_source;
+       GMainContext *main_context;
        SignalClosure *signal_closure;
 
        signal_closure = g_slice_new0 (SignalClosure);
-       signal_closure->client = g_object_ref (cal_client);
+       signal_closure->client = g_object_ref (client);
        signal_closure->error_message = g_strdup (error_message);
 
+       main_context = e_client_ref_main_context (client);
+
        idle_source = g_idle_source_new ();
        g_source_set_callback (
                idle_source,
                cal_client_emit_backend_error_idle_cb,
                signal_closure,
                (GDestroyNotify) signal_closure_free);
-       g_source_attach (idle_source, cal_client->priv->main_context);
+       g_source_attach (idle_source, main_context);
        g_source_unref (idle_source);
+
+       g_main_context_unref (main_context);
 }
 
 static void
 cal_client_dbus_proxy_notify_cb (EDBusCalendar *dbus_proxy,
                                  GParamSpec *pspec,
-                                 ECalClient *cal_client)
+                                 EClient *client)
 {
        const gchar *backend_prop_name = NULL;
 
@@ -623,7 +627,7 @@ cal_client_dbus_proxy_notify_cb (EDBusCalendar *dbus_proxy,
                        csv = g_strjoinv (",", strv);
                        g_strfreev (strv);
                }
-               e_client_set_capabilities (E_CLIENT (cal_client), csv);
+               e_client_set_capabilities (client, csv);
                g_free (csv);
        }
 
@@ -637,7 +641,7 @@ cal_client_dbus_proxy_notify_cb (EDBusCalendar *dbus_proxy,
                backend_prop_name = CLIENT_BACKEND_PROPERTY_ONLINE;
 
                online = e_dbus_calendar_get_online (dbus_proxy);
-               e_client_set_online (E_CLIENT (cal_client), online);
+               e_client_set_online (client, online);
        }
 
        if (g_str_equal (pspec->name, "revision")) {
@@ -650,60 +654,73 @@ cal_client_dbus_proxy_notify_cb (EDBusCalendar *dbus_proxy,
                backend_prop_name = CLIENT_BACKEND_PROPERTY_READONLY;
 
                writable = e_dbus_calendar_get_writable (dbus_proxy);
-               e_client_set_readonly (E_CLIENT (cal_client), !writable);
+               e_client_set_readonly (client, !writable);
        }
 
        if (backend_prop_name != NULL) {
                GSource *idle_source;
+               GMainContext *main_context;
                SignalClosure *signal_closure;
 
                signal_closure = g_slice_new0 (SignalClosure);
-               signal_closure->client = g_object_ref (cal_client);
+               signal_closure->client = g_object_ref (client);
                signal_closure->property_name = g_strdup (backend_prop_name);
 
+               main_context = e_client_ref_main_context (client);
+
                idle_source = g_idle_source_new ();
                g_source_set_callback (
                        idle_source,
                        cal_client_emit_backend_property_changed_idle_cb,
                        signal_closure,
                        (GDestroyNotify) signal_closure_free);
-               g_source_attach (idle_source, cal_client->priv->main_context);
+               g_source_attach (idle_source, main_context);
                g_source_unref (idle_source);
+
+               g_main_context_unref (main_context);
        }
 }
 
 static void
 cal_client_dbus_proxy_free_busy_data_cb (EDBusCalendar *dbus_proxy,
                                          gchar **free_busy_data,
-                                         ECalClient *cal_client)
+                                         EClient *client)
 {
        GSource *idle_source;
+       GMainContext *main_context;
        SignalClosure *signal_closure;
 
        signal_closure = g_slice_new0 (SignalClosure);
-       signal_closure->client = g_object_ref (cal_client);
+       signal_closure->client = g_object_ref (client);
        signal_closure->free_busy_data = g_strdupv (free_busy_data);
 
+       main_context = e_client_ref_main_context (client);
+
        idle_source = g_idle_source_new ();
        g_source_set_callback (
                idle_source,
                cal_client_emit_free_busy_data_idle_cb,
                signal_closure,
                (GDestroyNotify) signal_closure_free);
-       g_source_attach (idle_source, cal_client->priv->main_context);
+       g_source_attach (idle_source, main_context);
        g_source_unref (idle_source);
+
+       g_main_context_unref (main_context);
 }
 
 static void
 cal_client_name_vanished_cb (GDBusConnection *connection,
                              const gchar *name,
-                             ECalClient *cal_client)
+                             EClient *client)
 {
        GSource *idle_source;
+       GMainContext *main_context;
        SignalClosure *signal_closure;
 
        signal_closure = g_slice_new0 (SignalClosure);
-       signal_closure->client = g_object_ref (cal_client);
+       signal_closure->client = g_object_ref (client);
+
+       main_context = e_client_ref_main_context (client);
 
        idle_source = g_idle_source_new ();
        g_source_set_callback (
@@ -711,8 +728,10 @@ cal_client_name_vanished_cb (GDBusConnection *connection,
                cal_client_emit_backend_died_idle_cb,
                signal_closure,
                (GDestroyNotify) signal_closure_free);
-       g_source_attach (idle_source, cal_client->priv->main_context);
+       g_source_attach (idle_source, main_context);
        g_source_unref (idle_source);
+
+       g_main_context_unref (main_context);
 }
 
 static void
@@ -824,11 +843,6 @@ cal_client_dispose (GObject *object)
                priv->dbus_proxy = NULL;
        }
 
-       if (priv->main_context != NULL) {
-               g_main_context_unref (priv->main_context);
-               priv->main_context = NULL;
-       }
-
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (e_cal_client_parent_class)->dispose (object);
 }
@@ -1195,6 +1209,7 @@ cal_client_add_cached_timezone (ETimezoneCache *cache,
         * been returned through e_timezone_cache_get_timezone(). */
        if (!g_hash_table_contains (priv->zone_cache, tzid)) {
                GSource *idle_source;
+               GMainContext *main_context;
                SignalClosure *signal_closure;
 
                icalcomponent *icalcomp;
@@ -1216,14 +1231,18 @@ cal_client_add_cached_timezone (ETimezoneCache *cache,
                signal_closure->client = g_object_ref (cache);
                signal_closure->cached_zone = cached_zone;
 
+               main_context = e_client_ref_main_context (E_CLIENT (cache));
+
                idle_source = g_idle_source_new ();
                g_source_set_callback (
                        idle_source,
                        cal_client_emit_timezone_added_idle_cb,
                        signal_closure,
                        (GDestroyNotify) signal_closure_free);
-               g_source_attach (idle_source, priv->main_context);
+               g_source_attach (idle_source, main_context);
                g_source_unref (idle_source);
+
+               g_main_context_unref (main_context);
        }
 
        g_mutex_unlock (&priv->zone_cache_lock);
@@ -1421,10 +1440,6 @@ e_cal_client_init (ECalClient *client)
        client->priv->default_zone = icaltimezone_get_utc_timezone ();
        g_mutex_init (&client->priv->zone_cache_lock);
        client->priv->zone_cache = zone_cache;
-
-       /* This is so the D-Bus thread can schedule signal emissions
-        * on the thread-default context for this thread. */
-       client->priv->main_context = g_main_context_ref_thread_default ();
 }
 
 /**
index 71a8415..9b663e2 100644 (file)
@@ -49,6 +49,7 @@ CLIENT_BACKEND_PROPERTY_REVISION
 EClient
 e_client_get_source
 e_client_get_capabilities
+e_client_ref_main_context
 e_client_check_capability
 e_client_check_refresh_supported
 e_client_is_readonly
index e0b8712..53d1b28 100644 (file)
@@ -54,6 +54,7 @@ struct _EClientPrivate {
        gboolean online;
        gboolean readonly;
        GSList *capabilities;
+       GMainContext *main_context;
 };
 
 struct _AsyncContext {
@@ -66,6 +67,7 @@ struct _AsyncContext {
 enum {
        PROP_0,
        PROP_CAPABILITIES,
+       PROP_MAIN_CONTEXT,
        PROP_ONLINE,
        PROP_OPENED,
        PROP_READONLY,
@@ -246,6 +248,13 @@ client_get_property (GObject *object,
                                E_CLIENT (object)));
                        return;
 
+               case PROP_MAIN_CONTEXT:
+                       g_value_take_boxed (
+                               value,
+                               e_client_ref_main_context (
+                               E_CLIENT (object)));
+                       return;
+
                case PROP_ONLINE:
                        g_value_set_boolean (
                                value,
@@ -285,6 +294,11 @@ client_dispose (GObject *object)
 
        priv = E_CLIENT_GET_PRIVATE (object);
 
+       if (priv->main_context != NULL) {
+               g_main_context_unref (priv->main_context);
+               priv->main_context = NULL;
+       }
+
        g_clear_object (&priv->source);
 
        /* Chain up to parent's dispose() method. */
@@ -777,6 +791,18 @@ e_client_class_init (EClientClass *class)
 
        g_object_class_install_property (
                object_class,
+               PROP_MAIN_CONTEXT,
+               g_param_spec_boxed (
+                       "main-context",
+                       "Main Context",
+                       "The main loop context on "
+                       "which to attach event sources",
+                       G_TYPE_MAIN_CONTEXT,
+                       G_PARAM_READABLE |
+                       G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
                PROP_ONLINE,
                g_param_spec_boolean (
                        "online",
@@ -871,6 +897,7 @@ e_client_init (EClient *client)
        client->priv = E_CLIENT_GET_PRIVATE (client);
 
        client->priv->readonly = TRUE;
+       client->priv->main_context = g_main_context_ref_thread_default ();
 
        g_rec_mutex_init (&client->priv->prop_mutex);
 }
@@ -935,6 +962,28 @@ e_client_get_capabilities (EClient *client)
 }
 
 /**
+ * e_client_ref_main_context:
+ * @client: an #EClient
+ *
+ * Returns the #GMainContext on which event sources for @client are to
+ * be attached.
+ *
+ * The returned #GMainContext is referenced for thread-safety and must be
+ * unreferenced with g_main_context_unref() when finished with it.
+ *
+ * Returns: (transfer full): a #GMainContext
+ *
+ * Since: 3.8
+ **/
+GMainContext *
+e_client_ref_main_context (EClient *client)
+{
+       g_return_val_if_fail (E_IS_CLIENT (client), NULL);
+
+       return g_main_context_ref (client->priv->main_context);
+}
+
+/**
  * e_client_check_capability:
  * @client: an #EClient
  * @capability: a capability
index 5319d9d..69638b4 100644 (file)
@@ -284,6 +284,7 @@ GType               e_client_get_type               (void) G_GNUC_CONST;
 
 ESource *      e_client_get_source             (EClient *client);
 const GSList * e_client_get_capabilities       (EClient *client);
+GMainContext * e_client_ref_main_context       (EClient *client);
 gboolean       e_client_check_capability       (EClient *client,
                                                 const gchar *capability);
 gboolean       e_client_check_refresh_supported