[glib/wip/gcleanup] gtype: Use a single cleanup function for gtype memory
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/gcleanup] gtype: Use a single cleanup function for gtype memory
- Date: Fri, 8 Nov 2013 08:36:34 +0000 (UTC)
commit ce1c6aa334cba7d3283bd34169087d19d55c908f
Author: Stef Walter <stefw gnome org>
Date: Fri Nov 8 08:46:57 2013 +0100
gtype: Use a single cleanup function for gtype memory
There are a lot of intertwined pointer references between
types, their vtables, and other bits. Free the memory for them
all together.
Note that we still do all finalization (ie: callbacks) per type
and module, in the relevant cleanup lists.
gobject/gtype.c | 181 +++++++++++++++++++++++++------------------------------
1 files changed, 82 insertions(+), 99 deletions(-)
---
diff --git a/gobject/gtype.c b/gobject/gtype.c
index 3dd9e6c..8f44c7d 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -202,6 +202,7 @@ static void type_iface_vtable_iface_init_Wm (TypeNod
TypeNode *node);
static gboolean type_node_is_a_L (TypeNode *node,
TypeNode *iface_node);
+static void type_cleanup (void);
/* --- enumeration --- */
@@ -2443,12 +2444,6 @@ type_data_unref_U (TypeNode *node,
} while (!g_atomic_int_compare_and_exchange ((int *) &node->ref_count, current, current - 1));
}
-static void
-cleanup_class_cache_funcs (void)
-{
- g_free (static_class_cache_funcs);
-}
-
/**
* g_type_add_class_cache_func: (skip)
* @cache_data: data to be passed to @cache_func
@@ -2472,11 +2467,6 @@ g_type_add_class_cache_func (gpointer cache_data,
G_WRITE_LOCK (&type_rw_lock);
i = static_n_class_cache_funcs++;
- if (static_class_cache_funcs == NULL)
- {
- g_cleanup_list_push (G_CLEANUP_LIST, (GCleanupFunc)cleanup_class_cache_funcs, NULL,
- G_CLEANUP_PHASE_GRAVEYARD, "cleanup_class_cache_funcs");
- }
static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
static_class_cache_funcs[i].cache_data = cache_data;
static_class_cache_funcs[i].cache_func = cache_func;
@@ -2521,12 +2511,6 @@ g_type_remove_class_cache_func (gpointer cache_data,
cache_func, cache_data);
}
-static void
-cleanup_iface_check_funcs (void)
-{
- g_free (static_iface_check_funcs);
-}
-
/**
* g_type_add_interface_check: (skip)
* @check_data: data to pass to @check_func
@@ -2555,11 +2539,6 @@ g_type_add_interface_check (gpointer check_data,
G_WRITE_LOCK (&type_rw_lock);
i = static_n_iface_check_funcs++;
- if (static_iface_check_funcs == NULL)
- {
- g_cleanup_list_push (G_CLEANUP_LIST, (GCleanupFunc)cleanup_iface_check_funcs, NULL,
- G_CLEANUP_PHASE_GRAVEYARD, "cleanup_iface_check_funcs");
- }
static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
static_iface_check_funcs[i].check_data = check_data;
static_iface_check_funcs[i].check_func = check_func;
@@ -4392,8 +4371,6 @@ gobject_init_ctor (void)
/* type qname hash table */
static_type_nodes_ht = g_hash_table_new (g_str_hash, g_str_equal);
- g_cleanup_list_push (G_CLEANUP_LIST, (GCleanupFunc)g_hash_table_unref, static_type_nodes_ht,
- G_CLEANUP_PHASE_GRAVEYARD, "static_type_nodes_ht");
/* invalid type G_TYPE_INVALID (0)
*/
@@ -4454,6 +4431,9 @@ gobject_init_ctor (void)
/* Signal system
*/
_g_signal_init ();
+
+ g_cleanup_list_push (G_CLEANUP_LIST, (GCleanupFunc)type_cleanup, NULL,
+ G_CLEANUP_PHASE_GRAVEYARD, "type_cleanup");
}
static void
@@ -4965,105 +4945,112 @@ finalize_type (gpointer data)
node = lookup_type_node_I (type);
if (node->data && !node->plugin)
type_data_finalize (node);
+
+ if (node->global_gdata != NULL)
+ {
+ QData *qdatas = node->global_gdata->qdatas;
+ int i;
+
+ for (i = 0; i < node->global_gdata->n_qdatas; i++)
+ {
+ if (qdatas[i].destroy)
+ {
+ qdatas[i].destroy (qdatas[i].data);
+ qdatas[i].destroy = NULL;
+ qdatas[i].data = NULL;
+ }
+ }
+ }
}
static void
-g_type_cleanup (GType type)
+type_cleanup (void)
{
- const gchar *name;
- TypeNode *node;
+ GHashTableIter iter;
+ gpointer value;
+ GHashTable *vtables;
- node = lookup_type_node_I (type);
+ static_n_class_cache_funcs = 0;
+ g_free (static_class_cache_funcs);
+ static_class_cache_funcs = NULL;
- g_free (node->children);
+ static_n_iface_check_funcs = 0;
+ g_free (static_iface_check_funcs);
+ static_iface_check_funcs = NULL;
- if (node->is_classed)
+ g_hash_table_iter_init (&iter, static_type_nodes_ht);
+ vtables = g_hash_table_new (NULL, NULL);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
{
- IFaceEntries *entries;
+ GType gtype = (GType) GPOINTER_TO_SIZE (value);
+ TypeNode *node;
- entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node);
- if (entries)
+ node = lookup_type_node_I (gtype);
+
+ g_free (node->children);
+
+ if (node->is_classed)
{
- guint i;
+ IFaceEntries *entries;
- for (i = 0; i != IFACE_ENTRIES_N_ENTRIES (entries); i++)
+ entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node);
+ if (entries)
{
- g_cleanup_list_push (G_CLEANUP_LIST, g_free, entries->entry[i].vtable,
- G_CLEANUP_PHASE_GRAVEYARD, "entries->entry[i].vtable");
- entries->entry[i].vtable = NULL;
+ guint i;
+
+ for (i = 0; i != IFACE_ENTRIES_N_ENTRIES (entries); i++)
+ g_hash_table_insert (vtables, entries->entry[i].vtable, NULL);
}
- }
- _g_atomic_array_free (CLASSED_NODE_IFACES_ENTRIES (node));
+ _g_atomic_array_free (CLASSED_NODE_IFACES_ENTRIES (node));
- if (node->data && node->data->class.class)
- {
- g_cleanup_list_push (G_CLEANUP_LIST, g_free, node->data->class.class,
- G_CLEANUP_PHASE_GRAVEYARD, "node->data->class.class");
- node->data->class.class = NULL;
+ if (node->data)
+ g_free (node->data->class.class);
}
- }
- if (NODE_IS_IFACE (node))
- {
- IFaceHolder *iholder, *next;
-
- _g_atomic_array_free (&node->_prot.offsets);
-
- iholder = iface_node_get_holders_L (node);
- while (iholder)
+ if (NODE_IS_IFACE (node))
{
- next = iholder->next;
+ IFaceHolder *iholder, *next;
- g_free (iholder->info);
- g_free (iholder);
+ _g_atomic_array_free (&node->_prot.offsets);
- iholder = next;
- }
+ iholder = iface_node_get_holders_L (node);
+ while (iholder)
+ {
+ next = iholder->next;
- if (node->data != NULL)
- g_free (node->data->iface.dflt_vtable);
+ g_free (iholder->info);
+ g_free (iholder);
- g_free (iface_node_get_dependants_array_L (node));
- }
+ iholder = next;
+ }
- g_free (node->data);
+ if (node->data != NULL)
+ g_free (node->data->iface.dflt_vtable);
- if (node->global_gdata != NULL)
- {
- QData *qdatas = node->global_gdata->qdatas;
- int i;
-
- for (i = 0; i < node->global_gdata->n_qdatas; i++)
- {
- if (qdatas[i].destroy)
- qdatas[i].destroy (qdatas[i].data);
+ g_free (iface_node_get_dependants_array_L (node));
}
- g_free (qdatas);
- g_free (node->global_gdata);
- }
- g_free (node->prerequisites);
+ g_free (node->data);
- if (!node->plugin)
- {
- name = g_quark_to_string (node->qname);
- if (name != NULL)
+ if (node->global_gdata != NULL)
{
- if (!g_hash_table_remove (static_type_nodes_ht, name))
- g_assert_not_reached ();
+ g_free (node->global_gdata->qdatas);
+ g_free (node->global_gdata);
}
- }
- if (G_TYPE_IS_FUNDAMENTAL (type))
- node = G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO);
- g_free (node);
-}
+ g_free (node->prerequisites);
-static void
-cleanup_type (gpointer data)
-{
- g_type_cleanup (GPOINTER_TO_SIZE (data));
+ if (G_TYPE_IS_FUNDAMENTAL (gtype))
+ node = G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO);
+
+ g_free (node);
+ }
+
+ g_hash_table_foreach (vtables, (GHFunc) g_free, NULL);
+ g_hash_table_unref (vtables);
+ g_hash_table_unref (static_type_nodes_ht);
+ static_type_nodes_ht = NULL;
}
void
@@ -5071,7 +5058,6 @@ g_type_cleanup_push (GCleanupList *cleanup,
GType type)
{
GCleanupPhase phase;
- const gchar *name;
/*
* For types in our own module, we want them finalized before
@@ -5081,19 +5067,16 @@ g_type_cleanup_push (GCleanupList *cleanup,
phase = G_CLEANUP_PHASE_MAIN;
else
phase = G_CLEANUP_PHASE_LATE;
- name = g_type_name (type);
/*
* We want all the finalizers called first. They refer to each
* other so we can't free anything at this point.
*/
g_cleanup_list_push (cleanup, finalize_type, GSIZE_TO_POINTER (type),
- phase, name);
+ phase, g_type_name (type));
/*
- * And at the very end memory is freed. At this point we shouldn't
- * be doing any callbacks.
+ * And at the very end memory is freed. This is all done in one shot
+ * in the graveyard shift, due to intertwined pointers. See type_cleanup().
*/
- g_cleanup_list_push (cleanup, cleanup_type, GSIZE_TO_POINTER (type),
- G_CLEANUP_PHASE_GRAVEYARD, name);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]