From fad86a267fd3c0ebc402ca67f14a0d2f74f57b74 Mon Sep 17 00:00:00 2001 From: Srinivasa Ragavan Date: Mon, 4 May 2009 09:40:18 +0530 Subject: =?UTF-8?q?**=20BUGFIX:=20569696=20=E2=80=93=20Memory=20leak=20in?= =?UTF-8?q?=20message-list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not exactly a leak, but a build-up over a period of time. Clear the internal gnode on regen. --- mail/message-list.c | 11 ++++++----- widgets/table/e-tree-model.c | 30 ++++++++++++++++++++++++++++++ widgets/table/e-tree-model.h | 2 ++ widgets/table/e-tree-table-adapter.c | 27 +++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/mail/message-list.c b/mail/message-list.c index 3027fcf3e8..68177535e2 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -2584,7 +2584,7 @@ clear_info(char *key, ETreePath *node, MessageList *ml) } static void -clear_tree (MessageList *ml) +clear_tree (MessageList *ml, gboolean tfree) { ETreeModel *etm = ml->model; @@ -2608,7 +2608,8 @@ clear_tree (MessageList *ml) } ml->tree_root = e_tree_memory_node_insert (E_TREE_MEMORY(etm), NULL, 0, NULL); - + if (tfree) + e_tree_model_rebuilt (E_TREE_MODEL(etm)); #ifdef TIMEIT gettimeofday(&end, NULL); diff = end.tv_sec * 1000 + end.tv_usec/1000; @@ -2769,7 +2770,7 @@ build_tree (MessageList *ml, CamelFolderThread *thread, CamelFolderChangeInfo *c selected = message_list_get_selected(ml); #endif e_tree_memory_freeze(E_TREE_MEMORY(etm)); - clear_tree (ml); + clear_tree (ml, FALSE); build_subtree(ml, ml->tree_root, thread->tree, &row); e_tree_memory_thaw(E_TREE_MEMORY(etm)); @@ -3088,7 +3089,7 @@ build_flat (MessageList *ml, GPtrArray *summary, CamelFolderChangeInfo *changes) selected = message_list_get_selected(ml); #endif e_tree_memory_freeze(E_TREE_MEMORY(etm)); - clear_tree (ml); + clear_tree (ml, FALSE); for (i = 0; i < summary->len; i++) { ETreePath node; CamelMessageInfo *info = summary->pdata[i]; @@ -3354,7 +3355,7 @@ message_list_set_folder (MessageList *message_list, CamelFolder *folder, const c } e_tree_memory_freeze(E_TREE_MEMORY(etm)); - clear_tree (message_list); + clear_tree (message_list, TRUE); e_tree_memory_thaw(E_TREE_MEMORY(etm)); if (message_list->folder) { diff --git a/widgets/table/e-tree-model.c b/widgets/table/e-tree-model.c index 10c7afeb54..b2e2d99a75 100644 --- a/widgets/table/e-tree-model.c +++ b/widgets/table/e-tree-model.c @@ -53,6 +53,7 @@ enum { NODE_REMOVED, NODE_DELETED, NODE_REQUEST_COLLAPSE, + REBUILT, LAST_SIGNAL }; @@ -82,6 +83,15 @@ e_tree_model_class_init (ETreeModelClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + e_tree_model_signals [REBUILT] = + g_signal_new ("rebuilt", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ETreeModelClass, rebuilt), + (GSignalAccumulator) NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + e_tree_model_signals [NODE_CHANGED] = g_signal_new ("node_changed", G_TYPE_FROM_CLASS (object_class), @@ -183,6 +193,7 @@ e_tree_model_class_init (ETreeModelClass *klass) klass->pre_change = NULL; klass->no_change = NULL; + klass->rebuilt = NULL; klass->node_changed = NULL; klass->node_data_changed = NULL; klass->node_col_changed = NULL; @@ -240,6 +251,25 @@ e_tree_model_no_change (ETreeModel *tree_model) g_signal_emit (G_OBJECT (tree_model), e_tree_model_signals [NO_CHANGE], 0); } +/** + * e_tree_model_rebuilt: + * @tree_model: + * @node: + * + * + * + * Return value: + **/ +void +e_tree_model_rebuilt (ETreeModel *tree_model) +{ + g_return_if_fail (tree_model != NULL); + g_return_if_fail (E_IS_TREE_MODEL (tree_model)); + + d(g_print("Emitting rebuilt on model 0x%p, a %s.\n", tree_model, g_type_name (GTK_OBJECT(tree_model)->klass->type))); + + g_signal_emit (G_OBJECT (tree_model), e_tree_model_signals [REBUILT], 0); +} /** * e_tree_model_node_changed: * @tree_model: diff --git a/widgets/table/e-tree-model.h b/widgets/table/e-tree-model.h index a318bd7df0..96828a8e0a 100644 --- a/widgets/table/e-tree-model.h +++ b/widgets/table/e-tree-model.h @@ -112,6 +112,7 @@ struct ETreeModelClass { void (*node_inserted) (ETreeModel *etm, ETreePath parent, ETreePath inserted_node); void (*node_removed) (ETreeModel *etm, ETreePath parent, ETreePath removed_node, int old_position); void (*node_deleted) (ETreeModel *etm, ETreePath deleted_node); + void (*rebuilt) (ETreeModel *etm); /* This signal requests that any viewers of the tree that * collapse and expand nodes collapse this node. @@ -206,6 +207,7 @@ ETreePath e_tree_model_node_find (ETreeModel *model, */ void e_tree_model_pre_change (ETreeModel *tree_model); void e_tree_model_no_change (ETreeModel *tree_model); +void e_tree_model_rebuilt (ETreeModel *tree_model); void e_tree_model_node_changed (ETreeModel *tree_model, ETreePath node); void e_tree_model_node_data_changed (ETreeModel *tree_model, diff --git a/widgets/table/e-tree-table-adapter.c b/widgets/table/e-tree-table-adapter.c index 7e63a64783..10c29fbf10 100644 --- a/widgets/table/e-tree-table-adapter.c +++ b/widgets/table/e-tree-table-adapter.c @@ -72,6 +72,7 @@ struct ETreeTableAdapterPriv { int pre_change_id; int no_change_id; + int rebuilt_id; int node_changed_id; int node_data_changed_id; int node_col_changed_id; @@ -542,6 +543,8 @@ etta_dispose (GObject *object) etta->priv->pre_change_id); g_signal_handler_disconnect (G_OBJECT (etta->priv->source), etta->priv->no_change_id); + g_signal_handler_disconnect (G_OBJECT (etta->priv->source), + etta->priv->rebuilt_id); g_signal_handler_disconnect (G_OBJECT (etta->priv->source), etta->priv->node_changed_id); g_signal_handler_disconnect (G_OBJECT (etta->priv->source), @@ -730,6 +733,7 @@ etta_init (ETreeTableAdapter *etta) etta->priv->pre_change_id = 0; etta->priv->no_change_id = 0; + etta->priv->rebuilt_id = 0; etta->priv->node_changed_id = 0; etta->priv->node_data_changed_id = 0; etta->priv->node_col_changed_id = 0; @@ -753,6 +757,27 @@ etta_proxy_no_change (ETreeModel *etm, ETreeTableAdapter *etta) e_table_model_no_change(E_TABLE_MODEL(etta)); } +static gboolean +remove_all (gpointer key, gpointer value, gpointer data) +{ + GNode *gn = (GNode *) data; + if (data) + g_free (gn->data); + + return TRUE; +} + +static void +etta_proxy_rebuilt (ETreeModel *etm, ETreeTableAdapter *etta) +{ + if (!etta->priv->root) + return; + kill_gnode (etta->priv->root, etta); + etta->priv->root = NULL; + g_hash_table_destroy (etta->priv->nodes); + etta->priv->nodes = g_hash_table_new(NULL, NULL); +} + static gboolean resort_model (ETreeTableAdapter *etta) { @@ -866,6 +891,8 @@ e_tree_table_adapter_construct (ETreeTableAdapter *etta, ETreeModel *source, ETa G_CALLBACK (etta_proxy_pre_change), etta); etta->priv->no_change_id = g_signal_connect (G_OBJECT (source), "no_change", G_CALLBACK (etta_proxy_no_change), etta); + etta->priv->rebuilt_id = g_signal_connect (G_OBJECT (source), "rebuilt", + G_CALLBACK (etta_proxy_rebuilt), etta); etta->priv->node_changed_id = g_signal_connect (G_OBJECT (source), "node_changed", G_CALLBACK (etta_proxy_node_changed), etta); etta->priv->node_data_changed_id = g_signal_connect (G_OBJECT (source), "node_data_changed", -- cgit v1.2.3