ECalClient: Follow up on a timezone-related FIXME comment.
authorMatthew Barnes <mbarnes@redhat.com>
Fri, 8 Feb 2013 13:18:33 +0000 (08:18 -0500)
committerMatthew Barnes <mbarnes@redhat.com>
Fri, 8 Feb 2013 13:24:38 +0000 (08:24 -0500)
Emit the "timezone-added" signal from an idle callback on ECalClient's
GMainContext, instead of from whichever thread the timezone was added.
This makes life easier for any handlers of that signal.

Still need to address a similar FIXME comment in ECalBackend, but that
will have to wait until after the backend API rewrite.

calendar/libecal/e-cal-client.c

index 0b5b233..60cf34a 100644 (file)
@@ -92,6 +92,7 @@ struct _SignalClosure {
        gchar *property_name;
        gchar *error_message;
        gchar **free_busy_data;
+       icaltimezone *cached_zone;
 };
 
 struct _ConnectClosure {
@@ -185,6 +186,9 @@ signal_closure_free (SignalClosure *signal_closure)
 
        g_strfreev (signal_closure->free_busy_data);
 
+       /* The icaltimezone is cached in ECalClient's internal
+        * "zone_cache" hash table and must not be freed here. */
+
        g_slice_free (SignalClosure, signal_closure);
 }
 
@@ -710,6 +714,19 @@ cal_client_emit_free_busy_data_idle_cb (gpointer user_data)
        return FALSE;
 }
 
+static gboolean
+cal_client_emit_timezone_added_idle_cb (gpointer user_data)
+{
+       SignalClosure *signal_closure = user_data;
+
+       g_signal_emit_by_name (
+               signal_closure->client,
+               "timezone-added",
+               signal_closure->cached_zone);
+
+       return FALSE;
+}
+
 static void
 cal_client_dbus_proxy_error_cb (EDBusCalendar *dbus_proxy,
                                 const gchar *error_message,
@@ -1292,7 +1309,6 @@ cal_client_add_cached_timezone (ETimezoneCache *cache,
 {
        ECalClientPrivate *priv;
        const gchar *tzid;
-       gboolean timezone_added = FALSE;
 
        priv = E_CAL_CLIENT_GET_PRIVATE (cache);
 
@@ -1304,6 +1320,9 @@ cal_client_add_cached_timezone (ETimezoneCache *cache,
         * invalidate any icaltimezone pointers that may have already
         * been returned through e_timezone_cache_get_timezone(). */
        if (!g_hash_table_contains (priv->zone_cache, tzid)) {
+               GSource *idle_source;
+               SignalClosure *signal_closure;
+
                icalcomponent *icalcomp;
                icaltimezone *cached_zone;
 
@@ -1316,17 +1335,24 @@ cal_client_add_cached_timezone (ETimezoneCache *cache,
                        priv->zone_cache,
                        g_strdup (tzid), cached_zone);
 
-               timezone_added = TRUE;
+               /* The closure's client reference will keep the
+                * internally cached icaltimezone alive for the
+                * duration of the idle callback. */
+               signal_closure = g_slice_new0 (SignalClosure);
+               signal_closure->client = g_object_ref (cache);
+               signal_closure->cached_zone = cached_zone;
+
+               idle_source = g_idle_source_new ();
+               g_source_set_callback (
+                       idle_source,
+                       cal_client_emit_timezone_added_idle_cb,
+                       signal_closure,
+                       (GDestroyNotify) g_object_unref);
+               g_source_attach (idle_source, priv->main_context);
+               g_source_unref (idle_source);
        }
 
        g_mutex_unlock (&priv->zone_cache_lock);
-
-       /* FIXME Should emit this from an idle GSource on
-        *       a stored GMainContext, but we don't have
-        *       a stored GMainContext.  Check back after
-        *       the D-Bus API rewrite. */
-       if (timezone_added)
-               g_signal_emit_by_name (cache, "timezone-added", zone);
 }
 
 static icaltimezone *