[evolution-data-server] EBackend: Update online state from the correct main loop context.



commit a0e55108497390d8efd4d8b2b505ef1c9cb43081
Author: Matthew Barnes <mbarnes redhat com>
Date:   Fri Feb 22 10:09:31 2013 -0500

    EBackend: Update online state from the correct main loop context.
    
    Use a low-priority idle callback on the backend's main loop context to
    reduce the number of times we cancel g_network_monitor_can_reach_async().

 libebackend/e-backend.c |   80 +++++++++++++++++++++++++++-------------------
 1 files changed, 47 insertions(+), 33 deletions(-)
---
diff --git a/libebackend/e-backend.c b/libebackend/e-backend.c
index 608f4d2..23720eb 100644
--- a/libebackend/e-backend.c
+++ b/libebackend/e-backend.c
@@ -63,7 +63,9 @@ struct _EBackendPrivate {
 
        GNetworkMonitor *network_monitor;
        gulong network_changed_handler_id;
-       guint network_changed_timeout_id;
+
+       GSource *update_online_state;
+       GMutex update_online_state_lock;
 
        GMutex network_monitor_cancellable_lock;
        GCancellable *network_monitor_cancellable;
@@ -151,20 +153,21 @@ backend_network_monitor_can_reach_cb (GObject *source_object,
        g_thread_unref (thread);
 }
 
-static void
-backend_update_online_state (EBackend *backend)
+static gboolean
+backend_update_online_state_idle_cb (gpointer user_data)
 {
+       EBackend *backend;
        GSocketConnectable *connectable;
        GCancellable *cancellable;
 
-       /* This should be eventually replaced with default implementation
-          of EBackend::get_destination_address() doing basically the same
-          what currently does the backend silently on construction, thus
-          it'll get also current values from the ESource, not stale from
-          construct time.
-       */
+       backend = E_BACKEND (user_data);
        connectable = e_backend_ref_connectable (backend);
 
+       g_mutex_lock (&backend->priv->update_online_state_lock);
+       g_source_unref (backend->priv->update_online_state);
+       backend->priv->update_online_state = NULL;
+       g_mutex_unlock (&backend->priv->update_online_state_lock);
+
        g_mutex_lock (&backend->priv->network_monitor_cancellable_lock);
 
        cancellable = backend->priv->network_monitor_cancellable;
@@ -223,20 +226,37 @@ backend_update_online_state (EBackend *backend)
 
        if (connectable != NULL)
                g_object_unref (connectable);
+
+       return FALSE;
 }
 
-static gboolean
-backend_network_changed_timeout_cb (gpointer user_data)
+static void
+backend_update_online_state (EBackend *backend)
 {
-       EBackend *backend = user_data;
-
-       if (!g_source_is_destroyed (g_main_current_source ())) {
-               backend->priv->network_changed_timeout_id = 0;
-
-               backend_update_online_state (backend);
+       g_mutex_lock (&backend->priv->update_online_state_lock);
+
+       if (backend->priv->update_online_state == NULL) {
+               GMainContext *main_context;
+               GSource *idle_source;
+
+               main_context = e_backend_ref_main_context (backend);
+
+               idle_source = g_idle_source_new ();
+               g_source_set_priority (idle_source, G_PRIORITY_LOW);
+               g_source_set_callback (
+                       idle_source,
+                       backend_update_online_state_idle_cb,
+                       g_object_ref (backend),
+                       (GDestroyNotify) g_object_unref);
+               g_source_attach (idle_source, main_context);
+               backend->priv->update_online_state =
+                       g_source_ref (idle_source);
+               g_source_unref (idle_source);
+
+               g_main_context_unref (main_context);
        }
 
-       return FALSE;
+       g_mutex_unlock (&backend->priv->update_online_state_lock);
 }
 
 static void
@@ -244,11 +264,7 @@ backend_network_changed_cb (GNetworkMonitor *network_monitor,
                             gboolean network_available,
                             EBackend *backend)
 {
-       if (backend->priv->network_changed_timeout_id)
-               g_source_remove (backend->priv->network_changed_timeout_id);
-
-       /* wait few seconds, a network change can fire this event multiple times */
-       backend->priv->network_changed_timeout_id = g_timeout_add_seconds (3, 
backend_network_changed_timeout_cb, backend);
+       backend_update_online_state (backend);
 }
 
 static void
@@ -345,16 +361,17 @@ backend_dispose (GObject *object)
                priv->network_changed_handler_id = 0;
        }
 
-       if (priv->network_changed_timeout_id) {
-               g_source_remove (priv->network_changed_timeout_id);
-               priv->network_changed_timeout_id = 0;
-       }
-
        if (priv->main_context != NULL) {
                g_main_context_unref (priv->main_context);
                priv->main_context = NULL;
        }
 
+       if (priv->update_online_state != NULL) {
+               g_source_destroy (priv->update_online_state);
+               g_source_unref (priv->update_online_state);
+               priv->update_online_state = NULL;
+       }
+
        g_clear_object (&priv->source);
        g_clear_object (&priv->prompter);
        g_clear_object (&priv->connectable);
@@ -373,13 +390,9 @@ backend_finalize (GObject *object)
        priv = E_BACKEND_GET_PRIVATE (object);
 
        g_mutex_clear (&priv->property_lock);
+       g_mutex_clear (&priv->update_online_state_lock);
        g_mutex_clear (&priv->network_monitor_cancellable_lock);
 
-       if (priv->network_changed_timeout_id) {
-               g_source_remove (priv->network_changed_timeout_id);
-               priv->network_changed_timeout_id = 0;
-       }
-
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (e_backend_parent_class)->finalize (object);
 }
@@ -591,6 +604,7 @@ e_backend_init (EBackend *backend)
        backend->priv->main_context = g_main_context_ref_thread_default ();
 
        g_mutex_init (&backend->priv->property_lock);
+       g_mutex_init (&backend->priv->update_online_state_lock);
        g_mutex_init (&backend->priv->network_monitor_cancellable_lock);
 
        /* Configure network monitoring. */


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