diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2013-05-30 00:18:31 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2013-05-30 01:09:36 +0800 |
commit | d845222a117a665f25e4d6e110760c8908182336 (patch) | |
tree | 287fb16cb3993375b797ae61fb024c8783293dab /e-util | |
parent | 93101352ee3fb8608f9f604d116bd8b601fa0a14 (diff) | |
download | gsoc2013-evolution-d845222a117a665f25e4d6e110760c8908182336.tar.gz gsoc2013-evolution-d845222a117a665f25e4d6e110760c8908182336.tar.zst gsoc2013-evolution-d845222a117a665f25e4d6e110760c8908182336.zip |
Bug 700277 - EClientCache allocates memory ad infinity
Remove a ClientData entry on "source-removed" or "source-disabled"
signals from the ESourceRegistry.
Diffstat (limited to 'e-util')
-rw-r--r-- | e-util/e-client-cache.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/e-util/e-client-cache.c b/e-util/e-client-cache.c index 4b48db875a..94530951e0 100644 --- a/e-util/e-client-cache.c +++ b/e-util/e-client-cache.c @@ -49,6 +49,8 @@ typedef struct _SignalClosure SignalClosure; struct _EClientCachePrivate { ESourceRegistry *registry; + gulong source_removed_handler_id; + gulong source_disabled_handler_id; GHashTable *client_ht; GMutex client_ht_lock; @@ -226,6 +228,31 @@ client_ht_lookup (EClientCache *client_cache, } static gboolean +client_ht_remove (EClientCache *client_cache, + ESource *source) +{ + GHashTable *client_ht; + GHashTableIter client_ht_iter; + gpointer inner_ht; + gboolean removed = FALSE; + + g_return_val_if_fail (E_IS_SOURCE (source), FALSE); + + client_ht = client_cache->priv->client_ht; + + g_mutex_lock (&client_cache->priv->client_ht_lock); + + g_hash_table_iter_init (&client_ht_iter, client_ht); + + while (g_hash_table_iter_next (&client_ht_iter, NULL, &inner_ht)) + removed |= g_hash_table_remove (inner_ht, source); + + g_mutex_unlock (&client_cache->priv->client_ht_lock); + + return removed; +} + +static gboolean client_cache_emit_backend_died_idle_cb (gpointer user_data) { SignalClosure *signal_closure = user_data; @@ -627,6 +654,36 @@ client_cache_cal_connect_cb (GObject *source_object, } static void +client_cache_source_removed_cb (ESourceRegistry *registry, + ESource *source, + GWeakRef *weak_ref) +{ + EClientCache *client_cache; + + client_cache = g_weak_ref_get (weak_ref); + + if (client_cache != NULL) { + client_ht_remove (client_cache, source); + g_object_unref (client_cache); + } +} + +static void +client_cache_source_disabled_cb (ESourceRegistry *registry, + ESource *source, + GWeakRef *weak_ref) +{ + EClientCache *client_cache; + + client_cache = g_weak_ref_get (weak_ref); + + if (client_cache != NULL) { + client_ht_remove (client_cache, source); + g_object_unref (client_cache); + } +} + +static void client_cache_set_registry (EClientCache *client_cache, ESourceRegistry *registry) { @@ -678,6 +735,20 @@ client_cache_dispose (GObject *object) priv = E_CLIENT_CACHE_GET_PRIVATE (object); + if (priv->source_removed_handler_id > 0) { + g_signal_handler_disconnect ( + priv->registry, + priv->source_removed_handler_id); + priv->source_removed_handler_id = 0; + } + + if (priv->source_disabled_handler_id > 0) { + g_signal_handler_disconnect ( + priv->registry, + priv->source_disabled_handler_id); + priv->source_disabled_handler_id = 0; + } + g_clear_object (&priv->registry); g_hash_table_remove_all (priv->client_ht); @@ -708,9 +779,33 @@ client_cache_finalize (GObject *object) static void client_cache_constructed (GObject *object) { + EClientCache *client_cache; + ESourceRegistry *registry; + gulong handler_id; + + client_cache = E_CLIENT_CACHE (object); + /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_client_cache_parent_class)->constructed (object); + registry = e_client_cache_ref_registry (client_cache); + + handler_id = g_signal_connect_data ( + registry, "source-removed", + G_CALLBACK (client_cache_source_removed_cb), + e_weak_ref_new (client_cache), + (GClosureNotify) e_weak_ref_free, 0); + client_cache->priv->source_removed_handler_id = handler_id; + + handler_id = g_signal_connect_data ( + registry, "source-disabled", + G_CALLBACK (client_cache_source_disabled_cb), + e_weak_ref_new (client_cache), + (GClosureNotify) e_weak_ref_free, 0); + client_cache->priv->source_disabled_handler_id = handler_id; + + g_object_unref (registry); + e_extensible_load_extensions (E_EXTENSIBLE (object)); } |