[evolution-data-server/evolution-data-server-3-12] Bug #728414 - Deliver ESource data changes on idle



commit d3df5164070dd084d4d4b7791d9903677605de49
Author: Milan Crha <mcrha redhat com>
Date:   Fri May 2 16:03:48 2014 +0200

    Bug #728414 - Deliver ESource data changes on idle
    
    The data D-Bus property change is received in a gdbus dedicated thread,
    thus any ESource property changes, caused by reload of the data file,
    are also delivered in the same gdbus dedicated thread, which is wrong
    when there are still left property bindings which update gtk widgets.
    Update the ESource data on idle, to workaround this issue.

 libedataserver/e-source.c |   55 +++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 51 insertions(+), 4 deletions(-)
---
diff --git a/libedataserver/e-source.c b/libedataserver/e-source.c
index a9a923f..977ccec 100644
--- a/libedataserver/e-source.c
+++ b/libedataserver/e-source.c
@@ -126,6 +126,9 @@ struct _ESourcePrivate {
        GSource *changed;
        GMutex changed_lock;
 
+       GSource *data_change;
+       GMutex data_change_lock;
+
        GMutex property_lock;
 
        gchar *display_name;
@@ -784,13 +787,26 @@ source_parse_dbus_data (ESource *source,
        return TRUE;
 }
 
-static void
-source_notify_dbus_data_cb (EDBusSource *dbus_source,
-                            GParamSpec *pspec,
-                            ESource *source)
+static gboolean
+source_idle_data_change_cb (gpointer user_data)
 {
+       ESource *source = E_SOURCE (user_data);
        GError *local_error = NULL;
 
+       /* If the ESource is still initializing itself in a different
+        * thread, skip the signal emission and try again on the next
+        * main loop iteration. This is a busy wait but it should be
+        * a very short wait. */
+       if (!source->priv->initialized)
+               return TRUE;
+
+       g_mutex_lock (&source->priv->data_change_lock);
+       if (source->priv->data_change != NULL) {
+               g_source_unref (source->priv->data_change);
+               source->priv->data_change = NULL;
+       }
+       g_mutex_unlock (&source->priv->data_change_lock);
+
        g_rec_mutex_lock (&source->priv->lock);
 
        /* Since the source data came from a GKeyFile structure on the
@@ -804,6 +820,27 @@ source_notify_dbus_data_cb (EDBusSource *dbus_source,
        }
 
        g_rec_mutex_unlock (&source->priv->lock);
+
+       return FALSE;
+}
+
+static void
+source_notify_dbus_data_cb (EDBusSource *dbus_source,
+                            GParamSpec *pspec,
+                            ESource *source)
+{
+       g_mutex_lock (&source->priv->data_change_lock);
+       if (source->priv->data_change == NULL) {
+               source->priv->data_change = g_idle_source_new ();
+               g_source_set_callback (
+                       source->priv->data_change,
+                       source_idle_data_change_cb,
+                       source, NULL);
+               g_source_attach (
+                       source->priv->data_change,
+                       source->priv->main_context);
+       }
+       g_mutex_unlock (&source->priv->data_change_lock);
 }
 
 static gboolean
@@ -1026,6 +1063,14 @@ source_dispose (GObject *object)
        }
        g_mutex_unlock (&priv->changed_lock);
 
+       g_mutex_lock (&priv->data_change_lock);
+       if (priv->data_change != NULL) {
+               g_source_destroy (priv->data_change);
+               g_source_unref (priv->data_change);
+               priv->data_change = NULL;
+       }
+       g_mutex_unlock (&priv->data_change_lock);
+
        g_hash_table_remove_all (priv->extensions);
 
        /* Chain up to parent's dispose() method. */
@@ -1040,6 +1085,7 @@ source_finalize (GObject *object)
        priv = E_SOURCE_GET_PRIVATE (object);
 
        g_mutex_clear (&priv->changed_lock);
+       g_mutex_clear (&priv->data_change_lock);
        g_mutex_clear (&priv->property_lock);
 
        g_free (priv->display_name);
@@ -2043,6 +2089,7 @@ e_source_init (ESource *source)
 
        source->priv = E_SOURCE_GET_PRIVATE (source);
        g_mutex_init (&source->priv->changed_lock);
+       g_mutex_init (&source->priv->data_change_lock);
        g_mutex_init (&source->priv->property_lock);
        source->priv->key_file = g_key_file_new ();
        source->priv->extensions = extensions;


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