From 0cba1b531d5d28890fa4f48359d4e7adacf2a603 Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Tue, 1 Nov 2005 18:10:31 +0000 Subject: [PATCH] prepared deprecation of GMemChunk and GAllocator. added g_slice_*() API to Tue Nov 1 16:24:20 2005 Tim Janik * glib/gmem.[hc]: prepared deprecation of GMemChunk and GAllocator. added g_slice_*() API to allocate and cache small bits of memory. an actuall allocator implementation for g_slice_*() is still pending. * glib/gthread.[hc]: changes from a patch by Matthias Clasen. changed GRealThread list to use in-structure *next; fields instead of GSList, in order for thread iteration to not depenend on g_slice_*() indirectly. _g_thread_mem_private_get(): _g_thread_mem_private_set(): added accessors for private memory, needed because the ordinary GPrivate implementation relies on GArray and GSList and therefore indirectly on working g_slice_*() allocations. * glib/gthread.[hc]: g_thread_foreach(): new public API function to loop over all existing threads. * glib/gdataset.c: * glib/gstring.c: * glib/gcache.c: * glib/garray.c: * glib/gqueue.c: * glib/gslist.c: * glib/glist.c: * glib/ghash.c: * glib/gtree.c: * glib/ghook.c: * glib/gmain.c: * glib/gnode.c: removed GAllocator and free list usages and accompanying locks. use g_slice_*() API to allocate and cache small bits of memory. * glib/ghook.h: removed GMemChunk field from public API. * glib/gslist.h: * glib/glist.h: deprecate allocator API, provide _free1() for consistency. * glib/gnode.h: deprecate allocator API. * glib/gmain.c: reordered GPollRec fields so g_slice_free_chain() can be used for poll rec lists. * glib/grel.c: removed mem chunk usage, and allocated tuples via g_slice_*(). g_relation_destroy(): free all tuples from the all_tuples hash table, this effectively maintains the life time track keeping of tuples. g_relation_delete_tuple(): free tuples which are removed from the all_tuples hash table. this fixes a temporary leak that was present in the memchunk code until the destruction of the relation. --- ChangeLog | 50 +++++++++++++ ChangeLog.pre-2-10 | 50 +++++++++++++ ChangeLog.pre-2-12 | 50 +++++++++++++ glib/garray.c | 37 +--------- glib/gcache.c | 51 ++++--------- glib/gdataset.c | 24 ++---- glib/ghash.c | 84 ++------------------- glib/ghook.c | 23 ++---- glib/ghook.h | 2 +- glib/glib.symbols | 25 ++++--- glib/glist.c | 212 +++++------------------------------------------------ glib/glist.h | 7 +- glib/gmain.c | 50 ++----------- glib/gmem.c | 95 +++++++++++++++--------- glib/gmem.h | 74 +++++++------------ glib/gnode.c | 157 +++------------------------------------ glib/gnode.h | 6 +- glib/gqueue.c | 37 +--------- glib/grel.c | 46 +++++++----- glib/gslist.c | 204 +++++---------------------------------------------- glib/gslist.h | 7 +- glib/gstring.c | 18 +---- glib/gthread.c | 115 ++++++++++++++++++++++++++--- glib/gthread.h | 8 ++ glib/gtree.c | 35 +-------- gobject/ChangeLog | 8 ++ gobject/gsignal.c | 55 ++------------ gobject/gtype.c | 51 +++---------- 28 files changed, 518 insertions(+), 1063 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0761d3d..1b3c98e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,53 @@ +Tue Nov 1 16:24:20 2005 Tim Janik + + * glib/gmem.[hc]: prepared deprecation of GMemChunk and GAllocator. + added g_slice_*() API to allocate and cache small bits of memory. + an actuall allocator implementation for g_slice_*() is still pending. + + * glib/gthread.[hc]: changes from a patch by Matthias Clasen. + changed GRealThread list to use in-structure *next; fields instead + of GSList, in order for thread iteration to not depenend on g_slice_*() + indirectly. + _g_thread_mem_private_get(): + _g_thread_mem_private_set(): added accessors for private memory, + needed because the ordinary GPrivate implementation relies on GArray + and GSList and therefore indirectly on working g_slice_*() allocations. + + * glib/gthread.[hc]: + g_thread_foreach(): new public API function to loop over all existing threads. + + * glib/gdataset.c: + * glib/gstring.c: + * glib/gcache.c: + * glib/garray.c: + * glib/gqueue.c: + * glib/gslist.c: + * glib/glist.c: + * glib/ghash.c: + * glib/gtree.c: + * glib/ghook.c: + * glib/gmain.c: + * glib/gnode.c: + removed GAllocator and free list usages and accompanying locks. + use g_slice_*() API to allocate and cache small bits of memory. + + * glib/ghook.h: removed GMemChunk field from public API. + + * glib/gslist.h: + * glib/glist.h: deprecate allocator API, provide _free1() for consistency. + + * glib/gnode.h: deprecate allocator API. + + * glib/gmain.c: reordered GPollRec fields so g_slice_free_chain() can + be used for poll rec lists. + + * glib/grel.c: removed mem chunk usage, and allocated tuples via g_slice_*(). + g_relation_destroy(): free all tuples from the all_tuples hash table, + this effectively maintains the life time track keeping of tuples. + g_relation_delete_tuple(): free tuples which are removed from the + all_tuples hash table. this fixes a temporary leak that was present + in the memchunk code until the destruction of the relation. + 2005-10-29 Matthias Clasen * tests/convert-test.c: Add some tests for conversions between diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 0761d3d..1b3c98e 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,53 @@ +Tue Nov 1 16:24:20 2005 Tim Janik + + * glib/gmem.[hc]: prepared deprecation of GMemChunk and GAllocator. + added g_slice_*() API to allocate and cache small bits of memory. + an actuall allocator implementation for g_slice_*() is still pending. + + * glib/gthread.[hc]: changes from a patch by Matthias Clasen. + changed GRealThread list to use in-structure *next; fields instead + of GSList, in order for thread iteration to not depenend on g_slice_*() + indirectly. + _g_thread_mem_private_get(): + _g_thread_mem_private_set(): added accessors for private memory, + needed because the ordinary GPrivate implementation relies on GArray + and GSList and therefore indirectly on working g_slice_*() allocations. + + * glib/gthread.[hc]: + g_thread_foreach(): new public API function to loop over all existing threads. + + * glib/gdataset.c: + * glib/gstring.c: + * glib/gcache.c: + * glib/garray.c: + * glib/gqueue.c: + * glib/gslist.c: + * glib/glist.c: + * glib/ghash.c: + * glib/gtree.c: + * glib/ghook.c: + * glib/gmain.c: + * glib/gnode.c: + removed GAllocator and free list usages and accompanying locks. + use g_slice_*() API to allocate and cache small bits of memory. + + * glib/ghook.h: removed GMemChunk field from public API. + + * glib/gslist.h: + * glib/glist.h: deprecate allocator API, provide _free1() for consistency. + + * glib/gnode.h: deprecate allocator API. + + * glib/gmain.c: reordered GPollRec fields so g_slice_free_chain() can + be used for poll rec lists. + + * glib/grel.c: removed mem chunk usage, and allocated tuples via g_slice_*(). + g_relation_destroy(): free all tuples from the all_tuples hash table, + this effectively maintains the life time track keeping of tuples. + g_relation_delete_tuple(): free tuples which are removed from the + all_tuples hash table. this fixes a temporary leak that was present + in the memchunk code until the destruction of the relation. + 2005-10-29 Matthias Clasen * tests/convert-test.c: Add some tests for conversions between diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 0761d3d..1b3c98e 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,53 @@ +Tue Nov 1 16:24:20 2005 Tim Janik + + * glib/gmem.[hc]: prepared deprecation of GMemChunk and GAllocator. + added g_slice_*() API to allocate and cache small bits of memory. + an actuall allocator implementation for g_slice_*() is still pending. + + * glib/gthread.[hc]: changes from a patch by Matthias Clasen. + changed GRealThread list to use in-structure *next; fields instead + of GSList, in order for thread iteration to not depenend on g_slice_*() + indirectly. + _g_thread_mem_private_get(): + _g_thread_mem_private_set(): added accessors for private memory, + needed because the ordinary GPrivate implementation relies on GArray + and GSList and therefore indirectly on working g_slice_*() allocations. + + * glib/gthread.[hc]: + g_thread_foreach(): new public API function to loop over all existing threads. + + * glib/gdataset.c: + * glib/gstring.c: + * glib/gcache.c: + * glib/garray.c: + * glib/gqueue.c: + * glib/gslist.c: + * glib/glist.c: + * glib/ghash.c: + * glib/gtree.c: + * glib/ghook.c: + * glib/gmain.c: + * glib/gnode.c: + removed GAllocator and free list usages and accompanying locks. + use g_slice_*() API to allocate and cache small bits of memory. + + * glib/ghook.h: removed GMemChunk field from public API. + + * glib/gslist.h: + * glib/glist.h: deprecate allocator API, provide _free1() for consistency. + + * glib/gnode.h: deprecate allocator API. + + * glib/gmain.c: reordered GPollRec fields so g_slice_free_chain() can + be used for poll rec lists. + + * glib/grel.c: removed mem chunk usage, and allocated tuples via g_slice_*(). + g_relation_destroy(): free all tuples from the all_tuples hash table, + this effectively maintains the life time track keeping of tuples. + g_relation_delete_tuple(): free tuples which are removed from the + all_tuples hash table. this fixes a temporary leak that was present + in the memchunk code until the destruction of the relation. + 2005-10-29 Matthias Clasen * tests/convert-test.c: Add some tests for conversions between diff --git a/glib/garray.c b/glib/garray.c index 54ee05b..aca3b6a 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -70,9 +70,6 @@ static gint g_nearest_pow (gint num) G_GNUC_CONST; static void g_array_maybe_expand (GRealArray *array, gint len); -static GMemChunk *array_mem_chunk = NULL; -G_LOCK_DEFINE_STATIC (array_mem_chunk); - GArray* g_array_new (gboolean zero_terminated, gboolean clear, @@ -86,16 +83,7 @@ GArray* g_array_sized_new (gboolean zero_terminated, guint elt_size, guint reserved_size) { - GRealArray *array; - - G_LOCK (array_mem_chunk); - if (!array_mem_chunk) - array_mem_chunk = g_mem_chunk_new ("array mem chunk", - sizeof (GRealArray), - 1024, G_ALLOC_AND_FREE); - - array = g_chunk_new (GRealArray, array_mem_chunk); - G_UNLOCK (array_mem_chunk); + GRealArray *array = g_slice_new (GRealArray); array->data = NULL; array->len = 0; @@ -129,9 +117,7 @@ g_array_free (GArray *array, else segment = array->data; - G_LOCK (array_mem_chunk); - g_mem_chunk_free (array_mem_chunk, array); - G_UNLOCK (array_mem_chunk); + g_slice_free1 (sizeof (GRealArray), array); return segment; } @@ -380,10 +366,6 @@ struct _GRealPtrArray static void g_ptr_array_maybe_expand (GRealPtrArray *array, gint len); -static GMemChunk *ptr_array_mem_chunk = NULL; -G_LOCK_DEFINE_STATIC (ptr_array_mem_chunk); - - GPtrArray* g_ptr_array_new (void) { @@ -393,16 +375,7 @@ g_ptr_array_new (void) GPtrArray* g_ptr_array_sized_new (guint reserved_size) { - GRealPtrArray *array; - - G_LOCK (ptr_array_mem_chunk); - if (!ptr_array_mem_chunk) - ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk", - sizeof (GRealPtrArray), - 1024, G_ALLOC_AND_FREE); - - array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk); - G_UNLOCK (ptr_array_mem_chunk); + GRealPtrArray *array = g_slice_new (GRealPtrArray); array->pdata = NULL; array->len = 0; @@ -430,9 +403,7 @@ g_ptr_array_free (GPtrArray *array, else segment = array->pdata; - G_LOCK (ptr_array_mem_chunk); - g_mem_chunk_free (ptr_array_mem_chunk, array); - G_UNLOCK (ptr_array_mem_chunk); + g_slice_free1 (sizeof (GRealPtrArray), array); return segment; } diff --git a/glib/gcache.c b/glib/gcache.c index e3080c9..a5b0297 100644 --- a/glib/gcache.c +++ b/glib/gcache.c @@ -64,13 +64,20 @@ struct _GCache GHashTable *value_table; }; +static inline GCacheNode* +g_cache_node_new (gpointer value) +{ + GCacheNode *node = g_slice_new (GCacheNode); + node->value = value; + node->ref_count = 1; + return node; +} -static GCacheNode* g_cache_node_new (gpointer value); -static void g_cache_node_destroy (GCacheNode *node); - - -static GMemChunk *node_mem_chunk = NULL; -G_LOCK_DEFINE_STATIC (node_mem_chunk); +static inline void +g_cache_node_destroy (GCacheNode *node) +{ + g_slice_free (GCacheNode, node); +} GCache* g_cache_new (GCacheNewFunc value_new_func, @@ -91,7 +98,7 @@ g_cache_new (GCacheNewFunc value_new_func, g_return_val_if_fail (hash_value_func != NULL, NULL); g_return_val_if_fail (key_equal_func != NULL, NULL); - cache = g_new (GCache, 1); + cache = g_slice_new (GCache); cache->value_new_func = value_new_func; cache->value_destroy_func = value_destroy_func; cache->key_dup_func = key_dup_func; @@ -109,7 +116,7 @@ g_cache_destroy (GCache *cache) g_hash_table_destroy (cache->key_table); g_hash_table_destroy (cache->value_table); - g_free (cache); + g_slice_free (GCache, cache); } gpointer @@ -186,33 +193,5 @@ g_cache_value_foreach (GCache *cache, g_hash_table_foreach (cache->key_table, func, user_data); } - -static GCacheNode* -g_cache_node_new (gpointer value) -{ - GCacheNode *node; - - G_LOCK (node_mem_chunk); - if (!node_mem_chunk) - node_mem_chunk = g_mem_chunk_new ("cache node mem chunk", sizeof (GCacheNode), - 1024, G_ALLOC_AND_FREE); - - node = g_chunk_new (GCacheNode, node_mem_chunk); - G_UNLOCK (node_mem_chunk); - - node->value = value; - node->ref_count = 1; - - return node; -} - -static void -g_cache_node_destroy (GCacheNode *node) -{ - G_LOCK (node_mem_chunk); - g_mem_chunk_free (node_mem_chunk, node); - G_UNLOCK (node_mem_chunk); -} - #define __G_CACHE_C__ #include "galiasdef.c" diff --git a/glib/gdataset.c b/glib/gdataset.c index 37c3466..f0c46bc 100644 --- a/glib/gdataset.c +++ b/glib/gdataset.c @@ -41,9 +41,7 @@ /* --- defines --- */ #define G_QUARK_BLOCK_SIZE (512) -#define G_DATA_MEM_CHUNK_PREALLOC (128) #define G_DATA_CACHE_MAX (512) -#define G_DATASET_MEM_CHUNK_PREALLOC (32) /* datalist pointer modifications have to be done with the g_dataset_global mutex held */ #define G_DATALIST_GET_POINTER(datalist) \ @@ -89,8 +87,6 @@ G_LOCK_DEFINE_STATIC (g_dataset_global); static GHashTable *g_dataset_location_ht = NULL; static GDataset *g_dataset_cached = NULL; /* should this be threadspecific? */ -static GMemChunk *g_dataset_mem_chunk = NULL; -static GMemChunk *g_data_mem_chunk = NULL; static GData *g_data_cache = NULL; static guint g_data_cache_length = 0; @@ -133,7 +129,7 @@ g_datalist_clear_i (GData **datalist) g_data_cache_length++; } else - g_mem_chunk_free (g_data_mem_chunk, prev); + g_slice_free (GData, prev); } } @@ -181,7 +177,7 @@ g_dataset_destroy_internal (GDataset *dataset) if (dataset == g_dataset_cached) g_dataset_cached = NULL; g_hash_table_remove (g_dataset_location_ht, dataset_location); - g_mem_chunk_free (g_dataset_mem_chunk, dataset); + g_slice_free (GDataset, dataset); break; } @@ -264,7 +260,7 @@ g_data_set_internal (GData **datalist, g_data_cache_length++; } else - g_mem_chunk_free (g_data_mem_chunk, list); + g_slice_free (GData, list); return ret_data; } @@ -315,7 +311,7 @@ g_data_set_internal (GData **datalist, g_data_cache_length--; } else - list = g_chunk_new (GData, g_data_mem_chunk); + list = g_slice_new (GData); list->next = G_DATALIST_GET_POINTER (datalist); list->id = key_id; list->data = data; @@ -352,7 +348,7 @@ g_dataset_id_set_data_full (gconstpointer dataset_location, dataset = g_dataset_lookup (dataset_location); if (!dataset) { - dataset = g_chunk_new (GDataset, g_dataset_mem_chunk); + dataset = g_slice_new (GDataset); dataset->location = dataset_location; g_datalist_init (&dataset->datalist); g_hash_table_insert (g_dataset_location_ht, @@ -610,16 +606,6 @@ g_data_initialize (void) g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL); g_dataset_cached = NULL; - g_dataset_mem_chunk = - g_mem_chunk_new ("GDataset MemChunk", - sizeof (GDataset), - sizeof (GDataset) * G_DATASET_MEM_CHUNK_PREALLOC, - G_ALLOC_AND_FREE); - g_data_mem_chunk = - g_mem_chunk_new ("GData MemChunk", - sizeof (GData), - sizeof (GData) * G_DATA_MEM_CHUNK_PREALLOC, - G_ALLOC_AND_FREE); } GQuark diff --git a/glib/ghash.c b/glib/ghash.c index d3ae9ae..debb6c9 100644 --- a/glib/ghash.c +++ b/glib/ghash.c @@ -84,13 +84,6 @@ static guint g_hash_table_foreach_remove_or_steal (GHashTable *hash_table, gboolean notify); -#ifndef DISABLE_MEM_POOLS -G_LOCK_DEFINE_STATIC (g_hash_global); - -static GMemChunk *node_mem_chunk = NULL; -static GHashNode *node_free_list = NULL; -#endif - /** * g_hash_table_new: * @hash_func: a function to create a hash value from a key. @@ -143,7 +136,7 @@ g_hash_table_new_full (GHashFunc hash_func, GHashTable *hash_table; guint i; - hash_table = g_new (GHashTable, 1); + hash_table = g_slice_new (GHashTable); hash_table->size = HASH_TABLE_MIN_SIZE; hash_table->nnodes = 0; hash_table->hash_func = hash_func ? hash_func : g_direct_hash; @@ -181,7 +174,7 @@ g_hash_table_destroy (GHashTable *hash_table) hash_table->value_destroy_func); g_free (hash_table->nodes); - g_free (hash_table); + g_slice_free (GHashTable, hash_table); } static inline GHashNode** @@ -649,28 +642,7 @@ static GHashNode* g_hash_node_new (gpointer key, gpointer value) { - GHashNode *hash_node; - -#ifdef DISABLE_MEM_POOLS - hash_node = g_new (GHashNode, 1); -#else - G_LOCK (g_hash_global); - if (node_free_list) - { - hash_node = node_free_list; - node_free_list = node_free_list->next; - } - else - { - if (!node_mem_chunk) - node_mem_chunk = g_mem_chunk_new ("hash node mem chunk", - sizeof (GHashNode), - 1024, G_ALLOC_ONLY); - - hash_node = g_chunk_new (GHashNode, node_mem_chunk); - } - G_UNLOCK (g_hash_global); -#endif + GHashNode *hash_node = g_slice_new (GHashNode); hash_node->key = key; hash_node->value = value; @@ -694,14 +666,7 @@ g_hash_node_destroy (GHashNode *hash_node, hash_node->value = NULL; #endif /* ENABLE_GC_FRIENDLY */ -#ifdef DISABLE_MEM_POOLS - g_free (hash_node); -#else - G_LOCK (g_hash_global); - hash_node->next = node_free_list; - node_free_list = hash_node; - G_UNLOCK (g_hash_global); -#endif + g_slice_free (GHashNode, hash_node); } static void @@ -709,55 +674,16 @@ g_hash_nodes_destroy (GHashNode *hash_node, GFreeFunc key_destroy_func, GFreeFunc value_destroy_func) { -#ifdef DISABLE_MEM_POOLS while (hash_node) { GHashNode *next = hash_node->next; - if (key_destroy_func) key_destroy_func (hash_node->key); if (value_destroy_func) value_destroy_func (hash_node->value); - - g_free (hash_node); + g_slice_free (GHashNode, hash_node); hash_node = next; - } -#else - if (hash_node) - { - GHashNode *node = hash_node; - - while (node->next) - { - if (key_destroy_func) - key_destroy_func (node->key); - if (value_destroy_func) - value_destroy_func (node->value); - -#ifdef ENABLE_GC_FRIENDLY - node->key = NULL; - node->value = NULL; -#endif /* ENABLE_GC_FRIENDLY */ - - node = node->next; - } - - if (key_destroy_func) - key_destroy_func (node->key); - if (value_destroy_func) - value_destroy_func (node->value); - -#ifdef ENABLE_GC_FRIENDLY - node->key = NULL; - node->value = NULL; -#endif /* ENABLE_GC_FRIENDLY */ - - G_LOCK (g_hash_global); - node->next = node_free_list; - node_free_list = hash_node; - G_UNLOCK (g_hash_global); } -#endif } #define __G_HASH_C__ diff --git a/glib/ghook.c b/glib/ghook.c index 88ff448..01ab78d 100644 --- a/glib/ghook.c +++ b/glib/ghook.c @@ -37,10 +37,6 @@ #include "galias.h" -/* --- defines --- */ -#define G_HOOKS_PREALLOC (16) - - /* --- functions --- */ static void default_finalize_hook (GHookList *hook_list, @@ -61,16 +57,12 @@ g_hook_list_init (GHookList *hook_list, { g_return_if_fail (hook_list != NULL); g_return_if_fail (hook_size >= sizeof (GHook)); - g_return_if_fail (hook_size < 65536); hook_list->seq_id = 1; hook_list->hook_size = hook_size; hook_list->is_setup = TRUE; hook_list->hooks = NULL; - hook_list->hook_memchunk = g_mem_chunk_new ("GHook Memchunk", - hook_size, - hook_size * G_HOOKS_PREALLOC, - G_ALLOC_AND_FREE); + hook_list->dummy3 = NULL; hook_list->finalize_hook = default_finalize_hook; hook_list->dummy[0] = NULL; hook_list->dummy[1] = NULL; @@ -90,8 +82,7 @@ g_hook_list_clear (GHookList *hook_list) hook = hook_list->hooks; if (!hook) { - g_mem_chunk_destroy (hook_list->hook_memchunk); - hook_list->hook_memchunk = NULL; + /* destroy hook_list->hook_memchunk */ } else do @@ -105,8 +96,6 @@ g_hook_list_clear (GHookList *hook_list) hook = tmp; } while (hook); - if (hook_list->hook_memchunk) - g_warning (G_STRLOC ": failed to clear hooklist, unconsolidated references on hooks left"); } } @@ -118,7 +107,7 @@ g_hook_alloc (GHookList *hook_list) g_return_val_if_fail (hook_list != NULL, NULL); g_return_val_if_fail (hook_list->is_setup, NULL); - hook = g_chunk_new0 (GHook, hook_list->hook_memchunk); + hook = g_slice_alloc0 (hook_list->hook_size); hook->data = NULL; hook->next = NULL; hook->prev = NULL; @@ -142,7 +131,7 @@ g_hook_free (GHookList *hook_list, g_return_if_fail (!G_HOOK_IN_CALL (hook)); hook_list->finalize_hook (hook_list, hook); - g_chunk_free (hook, hook_list->hook_memchunk); + g_slice_free1 (hook_list->hook_size, hook); } void @@ -184,7 +173,6 @@ g_hook_unref (GHookList *hook_list, GHook *hook) { g_return_if_fail (hook_list != NULL); - g_return_if_fail (hook_list->hook_memchunk != NULL); g_return_if_fail (hook != NULL); g_return_if_fail (hook->ref_count > 0); @@ -213,8 +201,7 @@ g_hook_unref (GHookList *hook_list, if (!hook_list->hooks) { - g_mem_chunk_destroy (hook_list->hook_memchunk); - hook_list->hook_memchunk = NULL; + /* destroy hook_list->hook_memchunk */ } } else diff --git a/glib/ghook.h b/glib/ghook.h index a552bfb..cb4f8e1 100644 --- a/glib/ghook.h +++ b/glib/ghook.h @@ -64,7 +64,7 @@ struct _GHookList guint hook_size : 16; guint is_setup : 1; GHook *hooks; - GMemChunk *hook_memchunk; + gpointer dummy3; GHookFinalizeFunc finalize_hook; gpointer dummy[2]; }; diff --git a/glib/glib.symbols b/glib/glib.symbols index 85a7b13..7ca791c 100644 --- a/glib/glib.symbols +++ b/glib/glib.symbols @@ -565,6 +565,18 @@ g_markup_vprintf_escaped #if IN_HEADER(__G_MEM_H__) #if IN_FILE(__G_MEM_C__) g_free +g_malloc G_GNUC_MALLOC +g_malloc0 G_GNUC_MALLOC +g_mem_is_system_malloc +g_mem_profile +g_mem_set_vtable +g_realloc +g_try_malloc G_GNUC_MALLOC +g_try_malloc0 G_GNUC_MALLOC +g_try_realloc +#ifndef G_DISABLE_DEPRECATED +g_allocator_free +g_allocator_new g_mem_chunk_alloc g_mem_chunk_alloc0 g_mem_chunk_clean @@ -574,18 +586,8 @@ g_mem_chunk_info g_mem_chunk_new g_mem_chunk_print g_mem_chunk_reset -g_malloc G_GNUC_MALLOC -g_malloc0 G_GNUC_MALLOC -g_mem_is_system_malloc -g_mem_profile -g_mem_set_vtable -g_realloc -g_allocator_free -g_allocator_new g_blow_chunks -g_try_malloc G_GNUC_MALLOC -g_try_malloc0 G_GNUC_MALLOC -g_try_realloc +#endif #endif #endif @@ -1031,6 +1033,7 @@ g_static_rw_lock_reader_unlock g_static_rw_lock_writer_lock g_static_rw_lock_writer_trylock g_static_rw_lock_writer_unlock +g_thread_foreach #endif #endif diff --git a/glib/glist.c b/glib/glist.c index ab94a3d..45799a5 100644 --- a/glib/glist.c +++ b/glib/glist.c @@ -34,208 +34,30 @@ #include "galias.h" -#ifndef DISABLE_MEM_POOLS -struct _GAllocator /* from gmem.c */ -{ - gchar *name; - guint16 n_preallocs; - guint is_unused : 1; - guint type : 4; - GAllocator *last; - GMemChunk *mem_chunk; - GList *free_lists; /* implementation specific */ -}; - -static GAllocator *current_allocator = NULL; -G_LOCK_DEFINE_STATIC (current_allocator); - -/* HOLDS: current_allocator_lock */ -static void -g_list_validate_allocator (GAllocator *allocator) -{ - g_return_if_fail (allocator != NULL); - g_return_if_fail (allocator->is_unused == TRUE); - - if (allocator->type != G_ALLOCATOR_LIST) - { - allocator->type = G_ALLOCATOR_LIST; - if (allocator->mem_chunk) - { - g_mem_chunk_destroy (allocator->mem_chunk); - allocator->mem_chunk = NULL; - } - } - - if (!allocator->mem_chunk) - { - allocator->mem_chunk = g_mem_chunk_new (allocator->name, - sizeof (GList), - sizeof (GList) * allocator->n_preallocs, - G_ALLOC_ONLY); - allocator->free_lists = NULL; - } - - allocator->is_unused = FALSE; -} - -void -g_list_push_allocator(GAllocator *allocator) -{ - G_LOCK (current_allocator); - g_list_validate_allocator (allocator); - allocator->last = current_allocator; - current_allocator = allocator; - G_UNLOCK (current_allocator); -} - -void -g_list_pop_allocator (void) -{ - G_LOCK (current_allocator); - if (current_allocator) - { - GAllocator *allocator; - - allocator = current_allocator; - current_allocator = allocator->last; - allocator->last = NULL; - allocator->is_unused = TRUE; - } - G_UNLOCK (current_allocator); -} - -static inline GList* -_g_list_alloc (void) -{ - GList *list; - - G_LOCK (current_allocator); - if (!current_allocator) - { - GAllocator *allocator = g_allocator_new ("GLib default GList allocator", - 128); - g_list_validate_allocator (allocator); - allocator->last = NULL; - current_allocator = allocator; - } - if (!current_allocator->free_lists) - { - list = g_chunk_new (GList, current_allocator->mem_chunk); - list->data = NULL; - } - else - { - if (current_allocator->free_lists->data) - { - list = current_allocator->free_lists->data; - current_allocator->free_lists->data = list->next; - list->data = NULL; - } - else - { - list = current_allocator->free_lists; - current_allocator->free_lists = list->next; - } - } - G_UNLOCK (current_allocator); - list->next = NULL; - list->prev = NULL; - - return list; -} - -GList* -g_list_alloc (void) -{ - return _g_list_alloc (); -} - -void -g_list_free (GList *list) -{ - if (list) - { - GList *last_node = list; - -#ifdef ENABLE_GC_FRIENDLY - while (last_node->next) - { - last_node->data = NULL; - last_node->prev = NULL; - last_node = last_node->next; - } - last_node->data = NULL; - last_node->prev = NULL; -#else /* !ENABLE_GC_FRIENDLY */ - list->data = list->next; -#endif /* ENABLE_GC_FRIENDLY */ - - G_LOCK (current_allocator); - last_node->next = current_allocator->free_lists; - current_allocator->free_lists = list; - G_UNLOCK (current_allocator); - } -} - -static inline void -_g_list_free_1 (GList *list) -{ - if (list) - { - list->data = NULL; +void g_list_push_allocator (gpointer dummy) { /* present for binary compat only */ } +void g_list_pop_allocator (void) { /* present for binary compat only */ } -#ifdef ENABLE_GC_FRIENDLY - list->prev = NULL; -#endif /* ENABLE_GC_FRIENDLY */ +#define _g_list_alloc0() g_slice_new0 (GList) +#define _g_list_free1(list) g_slice_free (GList, list) - G_LOCK (current_allocator); - list->next = current_allocator->free_lists; - current_allocator->free_lists = list; - G_UNLOCK (current_allocator); - } -} - -void -g_list_free_1 (GList *list) -{ - _g_list_free_1 (list); -} - -#else /* DISABLE_MEM_POOLS */ - -#define _g_list_alloc g_list_alloc GList* g_list_alloc (void) { - GList *list; - - list = g_new0 (GList, 1); - - return list; + return _g_list_alloc0 (); } void g_list_free (GList *list) { - GList *last; - - while (list) - { - last = list; - list = list->next; - g_free (last); - } + g_slice_free_chain (sizeof (GList), list, G_STRUCT_OFFSET (GList, next)); } -#define _g_list_free_1 g_list_free_1 void g_list_free_1 (GList *list) { - g_free (list); + _g_list_free1 (list); } -#endif - GList* g_list_append (GList *list, gpointer data) @@ -243,7 +65,7 @@ g_list_append (GList *list, GList *new_list; GList *last; - new_list = _g_list_alloc (); + new_list = _g_list_alloc0 (); new_list->data = data; if (list) @@ -265,7 +87,7 @@ g_list_prepend (GList *list, { GList *new_list; - new_list = _g_list_alloc (); + new_list = _g_list_alloc0 (); new_list->data = data; if (list) @@ -299,7 +121,7 @@ g_list_insert (GList *list, if (!tmp_list) return g_list_append (list, data); - new_list = _g_list_alloc (); + new_list = _g_list_alloc0 (); new_list->data = data; if (tmp_list->prev) @@ -405,7 +227,7 @@ g_list_remove (GList *list, if (list == tmp) list = list->next; - _g_list_free_1 (tmp); + _g_list_free1 (tmp); break; } @@ -434,7 +256,7 @@ g_list_remove_all (GList *list, if (next) next->prev = tmp->prev; - _g_list_free_1 (tmp); + _g_list_free1 (tmp); tmp = next; } } @@ -474,7 +296,7 @@ g_list_delete_link (GList *list, GList *link) { list = _g_list_remove_link (list, link); - _g_list_free_1 (link); + _g_list_free1 (link); return list; } @@ -488,13 +310,13 @@ g_list_copy (GList *list) { GList *last; - new_list = _g_list_alloc (); + new_list = _g_list_alloc0 (); new_list->data = list->data; last = new_list; list = list->next; while (list) { - last->next = _g_list_alloc (); + last->next = _g_list_alloc0 (); last->next->prev = last; last = last->next; last->data = list->data; @@ -686,7 +508,7 @@ g_list_insert_sorted (GList *list, if (!list) { - new_list = _g_list_alloc (); + new_list = _g_list_alloc0 (); new_list->data = data; return new_list; } @@ -699,7 +521,7 @@ g_list_insert_sorted (GList *list, cmp = (*func) (data, tmp_list->data); } - new_list = _g_list_alloc (); + new_list = _g_list_alloc0 (); new_list->data = data; if ((!tmp_list->next) && (cmp > 0)) diff --git a/glib/glist.h b/glib/glist.h index 9434dde..fde99e5 100644 --- a/glib/glist.h +++ b/glib/glist.h @@ -42,11 +42,10 @@ struct _GList /* Doubly linked lists */ -void g_list_push_allocator (GAllocator *allocator); -void g_list_pop_allocator (void); GList* g_list_alloc (void); void g_list_free (GList *list); void g_list_free_1 (GList *list); +#define g_list_free1 g_list_free_1 GList* g_list_append (GList *list, gpointer data); GList* g_list_prepend (GList *list, @@ -102,6 +101,10 @@ gpointer g_list_nth_data (GList *list, #define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL) #define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL) +#ifndef G_DISABLE_DEPRECATED +void g_list_push_allocator (gpointer allocator); +void g_list_pop_allocator (void); +#endif G_END_DECLS #endif /* __G_LIST_H__ */ diff --git a/glib/gmain.c b/glib/gmain.c index b5021b3..b41438a 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -125,8 +125,6 @@ struct _GMainContext gint in_check_or_prepare; GPollRec *poll_records; - GPollRec *poll_free_list; - GMemChunk *poll_chunk; guint n_poll_records; GPollFD *cached_poll_array; guint cached_poll_array_size; @@ -190,9 +188,9 @@ struct _GChildWatchSource struct _GPollRec { - gint priority; GPollFD *fd; - GPollRec *next; + GPollRec *next; /* chaining via second pointer member allows use of g_slice_free_chain() */ + gint priority; }; #ifdef G_THREADS_ENABLED @@ -597,25 +595,12 @@ g_main_context_ref (GMainContext *context) return context; } -/* If DISABLE_MEM_POOLS is defined, then freeing the - * mem chunk won't free the records, so we have to - * do it manually. The conditionalization here is - * an optimization; g_mem_chunk_free() is a no-op - * when DISABLE_MEM_POOLS is set. - */ -#ifdef DISABLE_MEM_POOLS -static void +static inline void poll_rec_list_free (GMainContext *context, GPollRec *list) { - while (list) - { - GPollRec *tmp_rec = list; - list = list->next; - g_chunk_free (tmp_rec, context->poll_chunk); - } + g_slice_free_chain (sizeof (GPollRec), list, G_STRUCT_OFFSET (GPollRec, next)); } -#endif /* DISABLE_MEM_POOLS */ /** * g_main_context_unref: @@ -653,14 +638,8 @@ g_main_context_unref (GMainContext *context) g_ptr_array_free (context->pending_dispatches, TRUE); g_free (context->cached_poll_array); -#ifdef DISABLE_MEM_POLLS poll_rec_list_free (context, context->poll_records); - poll_rec_list_free (context, context->poll_free_list); -#endif /* DISABLE_MEM_POOLS */ - if (context->poll_chunk) - g_mem_chunk_destroy (context->poll_chunk); - #ifdef G_THREADS_ENABLED if (g_thread_supported()) { @@ -2951,18 +2930,8 @@ g_main_context_add_poll_unlocked (GMainContext *context, gint priority, GPollFD *fd) { - GPollRec *lastrec, *pollrec, *newrec; - - if (!context->poll_chunk) - context->poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY); - - if (context->poll_free_list) - { - newrec = context->poll_free_list; - context->poll_free_list = newrec->next; - } - else - newrec = g_chunk_new (GPollRec, context->poll_chunk); + GPollRec *lastrec, *pollrec; + GPollRec *newrec = g_slice_new (GPollRec); /* This file descriptor may be checked before we ever poll */ fd->revents = 0; @@ -3035,12 +3004,7 @@ g_main_context_remove_poll_unlocked (GMainContext *context, else context->poll_records = pollrec->next; -#ifdef ENABLE_GC_FRIENDLY - pollrec->fd = NULL; -#endif /* ENABLE_GC_FRIENDLY */ - - pollrec->next = context->poll_free_list; - context->poll_free_list = pollrec; + g_slice_free (GPollRec, pollrec); context->n_poll_records--; break; diff --git a/glib/gmem.c b/glib/gmem.c index f2c6d20..44873f8 100644 --- a/glib/gmem.c +++ b/glib/gmem.c @@ -602,8 +602,55 @@ GMemVTable *glib_mem_profiler_table = &profiler_table; #endif /* !G_DISABLE_CHECKS */ +/* --- memory slices --- */ +typedef struct { + gpointer dummy, next; +} MemSlice; + +gpointer +g_slice_alloc (guint block_size) +{ + return g_malloc (block_size); +} + +gpointer +g_slice_alloc0 (guint block_size) +{ + return g_malloc0 (block_size); +} + +void +g_slice_free1 (guint block_size, + gpointer mem_block) +{ + if (mem_block) + g_free (mem_block); +} + +void +g_slice_free_chain (guint block_size, + gpointer mem_chain, + guint next_offset) +{ + MemSlice *slice = mem_chain; + g_return_if_fail (next_offset == G_STRUCT_OFFSET (MemSlice, next)); + g_return_if_fail (block_size >= sizeof (MemSlice)); + while (slice) + { + MemSlice *current = slice; + slice = slice->next; + g_slice_free1 (block_size, current); + } +} /* --- MemChunks --- */ +#ifndef G_ALLOC_AND_FREE +typedef struct _GAllocator GAllocator; +typedef struct _GMemChunk GMemChunk; +#define G_ALLOC_ONLY 1 +#define G_ALLOC_AND_FREE 2 +#endif + typedef struct _GFreeAtom GFreeAtom; typedef struct _GMemArea GMemArea; @@ -1219,50 +1266,28 @@ void g_blow_chunks (void) {} #endif /* DISABLE_MEM_POOLS */ -/* generic allocators - */ -struct _GAllocator /* from gmem.c */ -{ - gchar *name; - guint16 n_preallocs; - guint is_unused : 1; - guint type : 4; - GAllocator *last; - GMemChunk *mem_chunk; - gpointer dummy; /* implementation specific */ -}; - GAllocator* g_allocator_new (const gchar *name, guint n_preallocs) { - GAllocator *allocator; - - g_return_val_if_fail (name != NULL, NULL); - - allocator = g_new0 (GAllocator, 1); - allocator->name = g_strdup (name); - allocator->n_preallocs = CLAMP (n_preallocs, 1, 65535); - allocator->is_unused = TRUE; - allocator->type = 0; - allocator->last = NULL; - allocator->mem_chunk = NULL; - allocator->dummy = NULL; - - return allocator; + static const struct _GAllocator { + gchar *name; + guint16 n_preallocs; + guint is_unused : 1; + guint type : 4; + GAllocator *last; + GMemChunk *mem_chunk; + gpointer free_list; + } dummy = { + "GAllocator is deprecated", 0, TRUE, 0, NULL, NULL, NULL, + }; + /* some (broken) GAllocator uses depend on non-NULL allocators */ + return (GAllocator*) &dummy; } void g_allocator_free (GAllocator *allocator) { - g_return_if_fail (allocator != NULL); - g_return_if_fail (allocator->is_unused == TRUE); - - g_free (allocator->name); - if (allocator->mem_chunk) - g_mem_chunk_destroy (allocator->mem_chunk); - - g_free (allocator); } void diff --git a/glib/gmem.h b/glib/gmem.h index 6966b28..6e1773e 100644 --- a/glib/gmem.h +++ b/glib/gmem.h @@ -31,8 +31,6 @@ G_BEGIN_DECLS -typedef struct _GAllocator GAllocator; -typedef struct _GMemChunk GMemChunk; typedef struct _GMemVTable GMemVTable; @@ -98,9 +96,24 @@ gboolean g_mem_is_system_malloc (void); GLIB_VAR GMemVTable *glib_mem_profiler_table; void g_mem_profile (void); - -/* Memchunk convenience functions +/* slices - fast allocation/release of small memory blocks */ +gpointer g_slice_alloc (guint block_size); +gpointer g_slice_alloc0 (guint block_size); +void g_slice_free1 (guint block_size, + gpointer mem_block); +void g_slice_free_chain (guint block_size, + gpointer mem_chain, + guint next_offset); +#define g_slice_new(type) ((type*) g_slice_alloc (sizeof (type))) +#define g_slice_new0(type) ((type*) g_slice_alloc0 (sizeof (type))) +#define g_slice_free(type,mem) g_slice_free1 (sizeof (type), mem) + + +/* deprecated memchunks and allocators */ +#if !defined G_DISABLE_DEPRECATED || 1 +typedef struct _GAllocator GAllocator; +typedef struct _GMemChunk GMemChunk; #define g_mem_chunk_create(type, pre_alloc, alloc_type) ( \ g_mem_chunk_new (#type " mem chunks (" #pre_alloc ")", \ sizeof (type), \ @@ -116,30 +129,8 @@ void g_mem_profile (void); #define g_chunk_free(mem, mem_chunk) G_STMT_START { \ g_mem_chunk_free ((mem_chunk), (mem)); \ } G_STMT_END - - -/* "g_mem_chunk_new" creates a new memory chunk. - * Memory chunks are used to allocate pieces of memory which are - * always the same size. Lists are a good example of such a data type. - * The memory chunk allocates and frees blocks of memory as needed. - * Just be sure to call "g_mem_chunk_free" and not "g_free" on data - * allocated in a mem chunk. ("g_free" will most likely cause a seg - * fault...somewhere). - * - * Oh yeah, GMemChunk is an opaque data type. (You don't really - * want to know what's going on inside do you?) - */ - -/* ALLOC_ONLY MemChunks can only allocate memory. The free operation - * is interpreted as a no op. ALLOC_ONLY MemChunks save 4 bytes per - * atom. (They are also useful for lists which use MemChunk to allocate - * memory but are also part of the MemChunk implementation). - * ALLOC_AND_FREE MemChunks can allocate and free memory. - */ - #define G_ALLOC_ONLY 1 #define G_ALLOC_AND_FREE 2 - GMemChunk* g_mem_chunk_new (const gchar *name, gint atom_size, gulong area_size, @@ -153,29 +144,14 @@ void g_mem_chunk_clean (GMemChunk *mem_chunk); void g_mem_chunk_reset (GMemChunk *mem_chunk); void g_mem_chunk_print (GMemChunk *mem_chunk); void g_mem_chunk_info (void); - -/* Ah yes...we have a "g_blow_chunks" function. - * "g_blow_chunks" simply compresses all the chunks. This operation - * consists of freeing every memory area that should be freed (but - * which we haven't gotten around to doing yet). And, no, - * "g_blow_chunks" doesn't follow the naming scheme, but it is a - * much better name than "g_mem_chunk_clean_all" or something - * similar. - */ -void g_blow_chunks (void); - - -/* Generic allocators - */ -GAllocator* g_allocator_new (const gchar *name, - guint n_preallocs); -void g_allocator_free (GAllocator *allocator); - -/* internal */ -#define G_ALLOCATOR_LIST (1) -#define G_ALLOCATOR_SLIST (2) -#define G_ALLOCATOR_NODE (3) - +void g_blow_chunks (void); +GAllocator*g_allocator_new (const gchar *name, + guint n_preallocs); +void g_allocator_free (GAllocator *allocator); +#define G_ALLOCATOR_LIST (1) +#define G_ALLOCATOR_SLIST (2) +#define G_ALLOCATOR_NODE (3) +#endif /* G_DISABLE_DEPRECATED */ G_END_DECLS diff --git a/glib/gnode.c b/glib/gnode.c index 572da5c..c9c5bcb 100644 --- a/glib/gnode.c +++ b/glib/gnode.c @@ -36,170 +36,33 @@ #include "glib.h" #include "galias.h" -#ifndef DISABLE_MEM_POOLS -/* node allocation - */ -struct _GAllocator /* from gmem.c */ -{ - gchar *name; - guint16 n_preallocs; - guint is_unused : 1; - guint type : 4; - GAllocator *last; - GMemChunk *mem_chunk; - GNode *free_nodes; /* implementation specific */ -}; - -G_LOCK_DEFINE_STATIC (current_allocator); -static GAllocator *current_allocator = NULL; - -/* HOLDS: current_allocator_lock */ -static void -g_node_validate_allocator (GAllocator *allocator) -{ - g_return_if_fail (allocator != NULL); - g_return_if_fail (allocator->is_unused == TRUE); - - if (allocator->type != G_ALLOCATOR_NODE) - { - allocator->type = G_ALLOCATOR_NODE; - if (allocator->mem_chunk) - { - g_mem_chunk_destroy (allocator->mem_chunk); - allocator->mem_chunk = NULL; - } - } - - if (!allocator->mem_chunk) - { - allocator->mem_chunk = g_mem_chunk_new (allocator->name, - sizeof (GNode), - sizeof (GNode) * allocator->n_preallocs, - G_ALLOC_ONLY); - allocator->free_nodes = NULL; - } - - allocator->is_unused = FALSE; -} - -void -g_node_push_allocator (GAllocator *allocator) -{ - G_LOCK (current_allocator); - g_node_validate_allocator (allocator); - allocator->last = current_allocator; - current_allocator = allocator; - G_UNLOCK (current_allocator); -} - -void -g_node_pop_allocator (void) -{ - G_LOCK (current_allocator); - if (current_allocator) - { - GAllocator *allocator; - - allocator = current_allocator; - current_allocator = allocator->last; - allocator->last = NULL; - allocator->is_unused = TRUE; - } - G_UNLOCK (current_allocator); -} +void g_node_push_allocator (gpointer dummy) { /* present for binary compat only */ } +void g_node_pop_allocator (void) { /* present for binary compat only */ } +#define g_node_alloc0() g_slice_new0 (GNode) +#define g_node_free(node) g_slice_free (GNode, node) /* --- functions --- */ GNode* g_node_new (gpointer data) { - GNode *node; - - G_LOCK (current_allocator); - if (!current_allocator) - { - GAllocator *allocator = g_allocator_new ("GLib default GNode allocator", - 128); - g_node_validate_allocator (allocator); - allocator->last = NULL; - current_allocator = allocator; - } - if (!current_allocator->free_nodes) - node = g_chunk_new (GNode, current_allocator->mem_chunk); - else - { - node = current_allocator->free_nodes; - current_allocator->free_nodes = node->next; - } - G_UNLOCK (current_allocator); - + GNode *node = g_node_alloc0(); node->data = data; - node->next = NULL; - node->prev = NULL; - node->parent = NULL; - node->children = NULL; - return node; } static void g_nodes_free (GNode *node) { - GNode *parent; - - parent = node; - while (1) - { - if (parent->children) - g_nodes_free (parent->children); - -#ifdef ENABLE_GC_FRIENDLY - parent->data = NULL; - parent->prev = NULL; - parent->parent = NULL; - parent->children = NULL; -#endif /* ENABLE_GC_FRIENDLY */ - - if (parent->next) - parent = parent->next; - else - break; - } - - G_LOCK (current_allocator); - parent->next = current_allocator->free_nodes; - current_allocator->free_nodes = node; - G_UNLOCK (current_allocator); -} -#else /* DISABLE_MEM_POOLS */ - -GNode* -g_node_new (gpointer data) -{ - GNode *node; - - node = g_new0 (GNode, 1); - - node->data = data; - - return node; -} - -static void -g_nodes_free (GNode *root) -{ - GNode *node, *next; - - node = root; - while (node != NULL) + while (node) { - next = node->next; - g_nodes_free (node->children); - g_free (node); + GNode *next = node->next; + if (node->children) + g_nodes_free (node->children); + g_node_free (node); node = next; } } -#endif void g_node_destroy (GNode *root) diff --git a/glib/gnode.h b/glib/gnode.h index 9da362a..a22c8fb 100644 --- a/glib/gnode.h +++ b/glib/gnode.h @@ -76,8 +76,6 @@ struct _GNode ((GNode*) (node))->next == NULL) #define G_NODE_IS_LEAF(node) (((GNode*) (node))->children == NULL) -void g_node_push_allocator (GAllocator *allocator); -void g_node_pop_allocator (void); GNode* g_node_new (gpointer data); void g_node_destroy (GNode *root); void g_node_unlink (GNode *node); @@ -165,6 +163,10 @@ GNode* g_node_last_sibling (GNode *node); #define g_node_first_child(node) ((node) ? \ ((GNode*) (node))->children : NULL) +#ifndef G_DISABLE_DEPRECATED +void g_node_push_allocator (gpointer dummy); +void g_node_pop_allocator (void); +#endif G_END_DECLS #endif /* __G_NODE_H__ */ diff --git a/glib/gqueue.c b/glib/gqueue.c index 2b149cf..f381db3 100644 --- a/glib/gqueue.c +++ b/glib/gqueue.c @@ -29,11 +29,6 @@ #include "glib.h" #include "galias.h" - -G_LOCK_DEFINE_STATIC (queue_memchunk); -static GMemChunk *queue_memchunk = NULL; -static GTrashStack *free_queue_nodes = NULL; - /** * g_queue_new: * @@ -44,27 +39,7 @@ static GTrashStack *free_queue_nodes = NULL; GQueue* g_queue_new (void) { - GQueue *queue; - - G_LOCK (queue_memchunk); - queue = g_trash_stack_pop (&free_queue_nodes); - - if (!queue) - { - if (!queue_memchunk) - queue_memchunk = g_mem_chunk_new ("GLib GQueue chunk", - sizeof (GQueue), - sizeof (GQueue) * 128, - G_ALLOC_ONLY); - queue = g_chunk_new (GQueue, queue_memchunk); - } - G_UNLOCK (queue_memchunk); - - queue->head = NULL; - queue->tail = NULL; - queue->length = 0; - - return queue; + return g_slice_new0 (GQueue); } /** @@ -79,15 +54,7 @@ g_queue_free (GQueue *queue) g_return_if_fail (queue != NULL); g_list_free (queue->head); - -#ifdef ENABLE_GC_FRIENDLY - queue->head = NULL; - queue->tail = NULL; -#endif /* ENABLE_GC_FRIENDLY */ - - G_LOCK (queue_memchunk); - g_trash_stack_push (&free_queue_nodes, queue); - G_UNLOCK (queue_memchunk); + g_slice_free (GQueue, queue); } /** diff --git a/glib/grel.c b/glib/grel.c index eeb9be4..814401b 100644 --- a/glib/grel.c +++ b/glib/grel.c @@ -45,7 +45,6 @@ struct _GRelation GHashTable *all_tuples; GHashTable **hashed_tuple_tables; - GMemChunk *tuple_chunk; gint count; }; @@ -109,10 +108,6 @@ g_relation_new (gint fields) GRelation* rel = g_new0 (GRelation, 1); rel->fields = fields; - rel->tuple_chunk = g_mem_chunk_new ("Relation Chunk", - fields * sizeof (gpointer), - fields * sizeof (gpointer) * 128, - G_ALLOC_AND_FREE); rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields)); rel->hashed_tuple_tables = g_new0 (GHashTable*, fields); @@ -120,6 +115,16 @@ g_relation_new (gint fields) } static void +relation_delete_value_tuple (gpointer tuple_key, + gpointer tuple_value, + gpointer user_data) +{ + GRelation *relation = user_data; + gpointer *tuple = tuple_value; + g_slice_free1 (relation->fields * sizeof (gpointer), tuple); +} + +static void g_relation_free_array (gpointer key, gpointer value, gpointer user_data) { g_hash_table_destroy ((GHashTable*) value); @@ -132,9 +137,6 @@ g_relation_destroy (GRelation *relation) if (relation) { - g_hash_table_destroy (relation->all_tuples); - g_mem_chunk_destroy (relation->tuple_chunk); - for (i = 0; i < relation->fields; i += 1) { if (relation->hashed_tuple_tables[i]) @@ -143,6 +145,9 @@ g_relation_destroy (GRelation *relation) g_hash_table_destroy (relation->hashed_tuple_tables[i]); } } + + g_hash_table_foreach (relation->all_tuples, relation_delete_value_tuple, relation); + g_hash_table_destroy (relation->all_tuples); g_free (relation->hashed_tuple_tables); g_free (relation); @@ -166,16 +171,16 @@ void g_relation_insert (GRelation *relation, ...) { - gpointer* tuple = g_chunk_new (gpointer, relation->tuple_chunk); + gpointer* tuple = g_slice_alloc (relation->fields * sizeof (gpointer)); va_list args; gint i; - va_start(args, relation); + va_start (args, relation); for (i = 0; i < relation->fields; i += 1) - tuple[i] = va_arg(args, gpointer); + tuple[i] = va_arg (args, gpointer); - va_end(args); + va_end (args); g_hash_table_insert (relation->all_tuples, tuple, tuple); @@ -211,21 +216,21 @@ g_relation_delete_tuple (gpointer tuple_key, gpointer user_data) { gpointer *tuple = (gpointer*) tuple_value; - GRelation *rel = (GRelation *) user_data; + GRelation *relation = (GRelation *) user_data; gint j; g_assert (tuple_key == tuple_value); - for (j = 0; j < rel->fields; j += 1) + for (j = 0; j < relation->fields; j += 1) { - GHashTable *one_table = rel->hashed_tuple_tables[j]; + GHashTable *one_table = relation->hashed_tuple_tables[j]; gpointer one_key; GHashTable *per_key_table; if (one_table == NULL) continue; - if (j == rel->current_field) + if (j == relation->current_field) /* can't delete from the table we're foreaching in */ continue; @@ -236,9 +241,10 @@ g_relation_delete_tuple (gpointer tuple_key, g_hash_table_remove (per_key_table, tuple); } - g_hash_table_remove (rel->all_tuples, tuple); + if (g_hash_table_remove (relation->all_tuples, tuple)) + g_slice_free1 (relation->fields * sizeof (gpointer), tuple); - rel->count -= 1; + relation->count -= 1; } gint @@ -341,7 +347,7 @@ g_relation_count (GRelation *relation, gboolean g_relation_exists (GRelation *relation, ...) { - gpointer* tuple = g_chunk_new (gpointer, relation->tuple_chunk); + gpointer *tuple = g_slice_alloc (relation->fields * sizeof (gpointer)); va_list args; gint i; gboolean result; @@ -355,7 +361,7 @@ g_relation_exists (GRelation *relation, ...) result = g_hash_table_lookup (relation->all_tuples, tuple) != NULL; - g_mem_chunk_free (relation->tuple_chunk, tuple); + g_slice_free1 (relation->fields * sizeof (gpointer), tuple); return result; } diff --git a/glib/gslist.c b/glib/gslist.c index bdba1f3..6483f07 100644 --- a/glib/gslist.c +++ b/glib/gslist.c @@ -34,200 +34,30 @@ #include "galias.h" -#ifndef DISABLE_MEM_POOLS -struct _GAllocator /* from gmem.c */ -{ - gchar *name; - guint16 n_preallocs; - guint is_unused : 1; - guint type : 4; - GAllocator *last; - GMemChunk *mem_chunk; - GSList *free_lists; /* implementation specific */ -}; - -G_LOCK_DEFINE_STATIC (current_allocator); -static GAllocator *current_allocator = NULL; - -/* HOLDS: current_allocator_lock */ -static void -g_slist_validate_allocator (GAllocator *allocator) -{ - g_return_if_fail (allocator != NULL); - g_return_if_fail (allocator->is_unused == TRUE); - - if (allocator->type != G_ALLOCATOR_SLIST) - { - allocator->type = G_ALLOCATOR_SLIST; - if (allocator->mem_chunk) - { - g_mem_chunk_destroy (allocator->mem_chunk); - allocator->mem_chunk = NULL; - } - } - - if (!allocator->mem_chunk) - { - allocator->mem_chunk = g_mem_chunk_new (allocator->name, - sizeof (GSList), - sizeof (GSList) * allocator->n_preallocs, - G_ALLOC_ONLY); - allocator->free_lists = NULL; - } - - allocator->is_unused = FALSE; -} - -void -g_slist_push_allocator (GAllocator *allocator) -{ - G_LOCK (current_allocator); - g_slist_validate_allocator (allocator); - allocator->last = current_allocator; - current_allocator = allocator; - G_UNLOCK (current_allocator); -} - -void -g_slist_pop_allocator (void) -{ - G_LOCK (current_allocator); - if (current_allocator) - { - GAllocator *allocator; +void g_slist_push_allocator (gpointer dummy) { /* present for binary compat only */ } +void g_slist_pop_allocator (void) { /* present for binary compat only */ } - allocator = current_allocator; - current_allocator = allocator->last; - allocator->last = NULL; - allocator->is_unused = TRUE; - } - G_UNLOCK (current_allocator); -} - -static inline GSList* -_g_slist_alloc (void) -{ - GSList *list; - - G_LOCK (current_allocator); - if (!current_allocator) - { - GAllocator *allocator = g_allocator_new ("GLib default GSList allocator", - 128); - g_slist_validate_allocator (allocator); - allocator->last = NULL; - current_allocator = allocator; - } - if (!current_allocator->free_lists) - { - list = g_chunk_new (GSList, current_allocator->mem_chunk); - list->data = NULL; - } - else - { - if (current_allocator->free_lists->data) - { - list = current_allocator->free_lists->data; - current_allocator->free_lists->data = list->next; - list->data = NULL; - } - else - { - list = current_allocator->free_lists; - current_allocator->free_lists = list->next; - } - } - G_UNLOCK (current_allocator); - - list->next = NULL; +#define _g_slist_alloc0() g_slice_new0 (GSList) +#define _g_slist_free1(slist) g_slice_free (GSList, slist) - return list; -} - -GSList* -g_slist_alloc (void) -{ - return _g_slist_alloc (); -} - -void -g_slist_free (GSList *list) -{ - if (list) - { - GSList *last_node = list; - -#ifdef ENABLE_GC_FRIENDLY - while (last_node->next) - { - last_node->data = NULL; - last_node = last_node->next; - } - last_node->data = NULL; -#else /* !ENABLE_GC_FRIENDLY */ - list->data = list->next; -#endif /* ENABLE_GC_FRIENDLY */ - - G_LOCK (current_allocator); - last_node->next = current_allocator->free_lists; - current_allocator->free_lists = list; - G_UNLOCK (current_allocator); - } -} - -static inline void -_g_slist_free_1 (GSList *list) -{ - if (list) - { - list->data = NULL; - G_LOCK (current_allocator); - list->next = current_allocator->free_lists; - current_allocator->free_lists = list; - G_UNLOCK (current_allocator); - } -} - -void -g_slist_free_1 (GSList *list) -{ - _g_slist_free_1 (list); -} -#else /* DISABLE_MEM_POOLS */ - -#define _g_slist_alloc g_slist_alloc GSList* g_slist_alloc (void) { - GSList *list; - - list = g_new0 (GSList, 1); - - return list; + return _g_slist_alloc0 (); } void -g_slist_free (GSList *list) +g_slist_free (GSList *slist) { - GSList *last; - - while (list) - { - last = list; - list = list->next; - g_free (last); - } + g_slice_free_chain (sizeof (GSList), slist, G_STRUCT_OFFSET (GSList, next)); } -#define _g_slist_free_1 g_slist_free_1 void -g_slist_free_1 (GSList *list) +g_slist_free_1 (GSList *slist) { - g_free (list); + _g_slist_free1 (slist); } -#endif - GSList* g_slist_append (GSList *list, gpointer data) @@ -235,7 +65,7 @@ g_slist_append (GSList *list, GSList *new_list; GSList *last; - new_list = _g_slist_alloc (); + new_list = _g_slist_alloc0 (); new_list->data = data; if (list) @@ -256,7 +86,7 @@ g_slist_prepend (GSList *list, { GSList *new_list; - new_list = _g_slist_alloc (); + new_list = _g_slist_alloc0 (); new_list->data = data; new_list->next = list; @@ -277,7 +107,7 @@ g_slist_insert (GSList *list, else if (position == 0) return g_slist_prepend (list, data); - new_list = _g_slist_alloc (); + new_list = _g_slist_alloc0 (); new_list->data = data; if (!list) @@ -458,7 +288,7 @@ g_slist_delete_link (GSList *list, GSList *link) { list = _g_slist_remove_link (list, link); - _g_slist_free_1 (link); + _g_slist_free1 (link); return list; } @@ -472,13 +302,13 @@ g_slist_copy (GSList *list) { GSList *last; - new_list = _g_slist_alloc (); + new_list = _g_slist_alloc0 (); new_list->data = list->data; last = new_list; list = list->next; while (list) { - last->next = _g_slist_alloc (); + last->next = _g_slist_alloc0 (); last = last->next; last->data = list->data; list = list->next; @@ -647,7 +477,7 @@ g_slist_insert_sorted (GSList *list, if (!list) { - new_list = _g_slist_alloc (); + new_list = _g_slist_alloc0 (); new_list->data = data; return new_list; } @@ -661,7 +491,7 @@ g_slist_insert_sorted (GSList *list, cmp = (*func) (data, tmp_list->data); } - new_list = _g_slist_alloc (); + new_list = _g_slist_alloc0 (); new_list->data = data; if ((!tmp_list->next) && (cmp > 0)) diff --git a/glib/gslist.h b/glib/gslist.h index 72ce9d1..6df15dd 100644 --- a/glib/gslist.h +++ b/glib/gslist.h @@ -41,11 +41,10 @@ struct _GSList /* Singly linked lists */ -void g_slist_push_allocator (GAllocator *allocator); -void g_slist_pop_allocator (void); GSList* g_slist_alloc (void); void g_slist_free (GSList *list); void g_slist_free_1 (GSList *list); +#define g_slist_free1 g_slist_free_1 GSList* g_slist_append (GSList *list, gpointer data); GSList* g_slist_prepend (GSList *list, @@ -96,6 +95,10 @@ gpointer g_slist_nth_data (GSList *list, guint n); #define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL) +#ifndef G_DISABLE_DEPRECATED +void g_slist_push_allocator (gpointer dummy); +void g_slist_pop_allocator (void); +#endif G_END_DECLS #endif /* __G_SLIST_H__ */ diff --git a/glib/gstring.c b/glib/gstring.c index c0c0b6f..87ba2e2 100644 --- a/glib/gstring.c +++ b/glib/gstring.c @@ -53,9 +53,6 @@ struct _GStringChunk gsize default_size; }; -G_LOCK_DEFINE_STATIC (string_mem_chunk); -static GMemChunk *string_mem_chunk = NULL; - /* Hash Functions. */ @@ -268,16 +265,7 @@ g_string_maybe_expand (GString* string, GString* g_string_sized_new (gsize dfl_size) { - GString *string; - - G_LOCK (string_mem_chunk); - if (!string_mem_chunk) - string_mem_chunk = g_mem_chunk_new ("string mem chunk", - sizeof (GString), - 1024, G_ALLOC_AND_FREE); - - string = g_chunk_new (GString, string_mem_chunk); - G_UNLOCK (string_mem_chunk); + GString *string = g_slice_new (GString); string->allocated_len = 0; string->len = 0; @@ -344,9 +332,7 @@ g_string_free (GString *string, else segment = string->str; - G_LOCK (string_mem_chunk); - g_mem_chunk_free (string_mem_chunk, string); - G_UNLOCK (string_mem_chunk); + g_slice_free (GString, string); return segment; } diff --git a/glib/gthread.c b/glib/gthread.c index 85290db..d39faa2 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -76,6 +76,8 @@ struct _GRealThread { GThread thread; gpointer private_data; + gpointer mem_private; + GRealThread *next; gpointer retval; GSystemThread system_thread; }; @@ -126,7 +128,7 @@ GThreadFunctions g_thread_functions_for_glib_use = { static GMutex *g_once_mutex = NULL; static GCond *g_once_cond = NULL; static GPrivate *g_thread_specific_private = NULL; -static GSList *g_thread_all_threads = NULL; +static GRealThread *g_thread_all_threads = NULL; static GSList *g_thread_free_indeces = NULL; G_LOCK_DEFINE_STATIC (g_thread); @@ -465,7 +467,7 @@ void g_static_private_free (GStaticPrivate *private_key) { guint index = private_key->index; - GSList *list; + GRealThread *thread; if (!index) return; @@ -473,12 +475,12 @@ g_static_private_free (GStaticPrivate *private_key) private_key->index = 0; G_LOCK (g_thread); - list = g_thread_all_threads; - while (list) + + thread = g_thread_all_threads; + while (thread) { - GRealThread *thread = list->data; GArray *array = thread->private_data; - list = list->next; + thread = thread->next; if (array && index <= array->len) { @@ -529,8 +531,20 @@ g_thread_cleanup (gpointer data) it is, the structure is freed in g_thread_join */ if (!thread->thread.joinable) { + GRealThread *t, *p; + G_LOCK (g_thread); - g_thread_all_threads = g_slist_remove (g_thread_all_threads, data); + for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next) + { + if (t == thread) + { + if (p) + p->next = t->next; + else + g_thread_all_threads = t->next; + break; + } + } G_UNLOCK (g_thread); /* Just to make sure, this isn't used any more */ @@ -581,7 +595,7 @@ g_thread_create_full (GThreadFunc func, g_return_val_if_fail (priority >= G_THREAD_PRIORITY_LOW, NULL); g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL); - result = g_new (GRealThread, 1); + result = g_new0 (GRealThread, 1); result->thread.joinable = joinable; result->thread.priority = priority; @@ -592,7 +606,8 @@ g_thread_create_full (GThreadFunc func, G_THREAD_UF (thread_create, (g_thread_create_proxy, result, stack_size, joinable, bound, priority, &result->system_thread, &local_error)); - g_thread_all_threads = g_slist_prepend (g_thread_all_threads, result); + result->next = g_thread_all_threads; + g_thread_all_threads = result; G_UNLOCK (g_thread); if (local_error) @@ -617,6 +632,7 @@ gpointer g_thread_join (GThread* thread) { GRealThread* real = (GRealThread*) thread; + GRealThread *p, *t; gpointer retval; g_return_val_if_fail (thread, NULL); @@ -629,7 +645,17 @@ g_thread_join (GThread* thread) retval = real->retval; G_LOCK (g_thread); - g_thread_all_threads = g_slist_remove (g_thread_all_threads, thread); + for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next) + { + if (t == (GRealThread*) thread) + { + if (p) + p->next = t->next; + else + g_thread_all_threads = t->next; + break; + } + } G_UNLOCK (g_thread); /* Just to make sure, this isn't used any more */ @@ -672,7 +698,7 @@ g_thread_self (void) /* If no thread data is available, provide and set one. This can happen for the main thread and for threads, that are not created by GLib. */ - thread = g_new (GRealThread, 1); + thread = g_new0 (GRealThread, 1); thread->thread.joinable = FALSE; /* This is a save guess */ thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is just a guess */ @@ -686,7 +712,8 @@ g_thread_self (void) g_private_set (g_thread_specific_private, thread); G_LOCK (g_thread); - g_thread_all_threads = g_slist_prepend (g_thread_all_threads, thread); + thread->next = g_thread_all_threads; + g_thread_all_threads = thread; G_UNLOCK (g_thread); } @@ -841,5 +868,69 @@ g_static_rw_lock_free (GStaticRWLock* lock) g_static_mutex_free (&lock->mutex); } +/* + * Memory allocation can't use the regular GPrivate + * API, since that relies on GArray, which uses + * chunked memory. + */ +gpointer +_g_thread_mem_private_get (GThread *thread) +{ + GRealThread *real_thread = (GRealThread*) thread; + + return real_thread->mem_private; +} + +void +_g_thread_mem_private_set (GThread *thread, + gpointer data) +{ + GRealThread *real_thread = (GRealThread*) thread; + + real_thread->mem_private = data; +} + +/** + * g_thread_foreach + * @thread_func: function to call for all GThread structures + * @user_data: second argument to @thread_func + * Call @thread_func on all existing GThread structures. Note that + * threads may decide to exit while @thread_func is running, so + * without intimate knowledge about the lifetime of foreign threads, + * @thread_func shouldn't access the GThread* pointer passed in as + * first argument. However, @thread_func will not be called for threads + * which are known to have exited already. + * Due to thread lifetime checks, this function has an execution complexity + * which is quadratic in the number of existing threads. + */ +void +g_thread_foreach (GFunc thread_func, + gpointer user_data) +{ + GSList *slist = NULL; + GRealThread *thread; + g_return_if_fail (thread_func != NULL); + /* snapshot the list of threads for iteration */ + G_LOCK (g_thread); + for (thread = g_thread_all_threads; thread; thread = thread->next) + slist = g_slist_prepend (slist, thread); + G_UNLOCK (g_thread); + /* walk the list, skipping non-existant threads */ + while (slist) + { + GSList *node = slist; + slist = node->next; + /* check whether the current thread still exists */ + G_LOCK (g_thread); + for (thread = g_thread_all_threads; thread; thread = thread->next) + if (thread == node->data) + break; + G_UNLOCK (g_thread); + if (thread) + thread_func (thread, user_data); + g_slist_free_1 (node); + } +} + #define __G_THREAD_C__ #include "galiasdef.c" diff --git a/glib/gthread.h b/glib/gthread.h index 7471635..743981f 100644 --- a/glib/gthread.h +++ b/glib/gthread.h @@ -289,6 +289,9 @@ gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock); void g_static_rw_lock_writer_unlock (GStaticRWLock* lock); void g_static_rw_lock_free (GStaticRWLock* lock); +void g_thread_foreach (GFunc thread_func, + gpointer user_data); + typedef enum { G_ONCE_STATUS_NOTCALLED, @@ -367,6 +370,11 @@ extern void glib_dummy_decl (void); # define G_TRYLOCK(name) (TRUE) #endif /* !G_THREADS_ENABLED */ +/* --- internal API --- */ +gpointer _g_thread_mem_private_get (GThread *thread); +void _g_thread_mem_private_set (GThread *thread, + gpointer data); + G_END_DECLS #endif /* __G_THREAD_H__ */ diff --git a/glib/gtree.c b/glib/gtree.c index 1c81f3e..8411231 100644 --- a/glib/gtree.c +++ b/glib/gtree.c @@ -101,34 +101,11 @@ static GTreeNode* g_tree_node_rotate_right (GTreeNode *node); static void g_tree_node_check (GTreeNode *node); -G_LOCK_DEFINE_STATIC (g_tree_global); -static GMemChunk *node_mem_chunk = NULL; -static GTreeNode *node_free_list = NULL; - - static GTreeNode* g_tree_node_new (gpointer key, gpointer value) { - GTreeNode *node; - - G_LOCK (g_tree_global); - if (node_free_list) - { - node = node_free_list; - node_free_list = node->right; - } - else - { - if (!node_mem_chunk) - node_mem_chunk = g_mem_chunk_new ("GLib GTreeNode mem chunk", - sizeof (GTreeNode), - 1024, - G_ALLOC_ONLY); - - node = g_chunk_new (GTreeNode, node_mem_chunk); - } - G_UNLOCK (g_tree_global); + GTreeNode *node = g_slice_new (GTreeNode); node->balance = 0; node->left = NULL; @@ -162,10 +139,7 @@ g_tree_node_destroy (GTreeNode *node, node->value = NULL; #endif /* ENABLE_GC_FRIENDLY */ - G_LOCK (g_tree_global); - node->right = node_free_list; - node_free_list = node; - G_UNLOCK (g_tree_global); + g_slice_free (GTreeNode, node); } } @@ -742,10 +716,7 @@ g_tree_node_remove (GTree *tree, garbage->value = NULL; #endif /* ENABLE_GC_FRIENDLY */ - G_LOCK (g_tree_global); - garbage->right = node_free_list; - node_free_list = garbage; - G_UNLOCK (g_tree_global); + g_slice_free (GTreeNode, garbage); *removed = TRUE; } diff --git a/gobject/ChangeLog b/gobject/ChangeLog index 6fade6f..a35641a 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,11 @@ +Tue Nov 1 17:07:43 2005 Tim Janik + + * gsignal.c: allocate signal handlers and handler match structures + via the new g_slice_*() API (get's rid of GList allocation hack). + + * gtype.c: got rid of per-type memchunks. if GTypeInfo.n_preallocs + is > 0, objects are allocated via g_slice_*() instead of g_malloc(). + 2005-10-03 Matthias Clasen * glib-mkenums.in: Really fix #314890. diff --git a/gobject/gsignal.c b/gobject/gsignal.c index 50eebdd..1da35bf 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -42,7 +42,6 @@ /* pre allocation configurations */ #define MAX_STACK_VALUES (16) -#define HANDLER_PRE_ALLOC (48) #define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org" #ifdef G_ENABLE_DEBUG @@ -52,41 +51,6 @@ static volatile gpointer g_trap_instance_signals = NULL; #endif /* G_ENABLE_DEBUG */ -/* --- generic allocation --- */ -/* we special case allocations generically by replacing - * these functions with more speed/memory aware variants - */ -#ifndef DISABLE_MEM_POOLS -static inline gpointer -g_generic_node_alloc (GTrashStack **trash_stack_p, - guint sizeof_node, - guint nodes_pre_alloc) -{ - gpointer node = g_trash_stack_pop (trash_stack_p); - - if (!node) - { - guint8 *block; - - nodes_pre_alloc = MAX (nodes_pre_alloc, 1); - block = g_malloc (sizeof_node * nodes_pre_alloc); - while (--nodes_pre_alloc) - { - g_trash_stack_push (trash_stack_p, block); - block += sizeof_node; - } - node = block; - } - - return node; -} -#define g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node) -#else /* !DISABLE_MEM_POOLS */ -#define g_generic_node_alloc(t,sizeof_node,p) g_malloc (sizeof_node) -#define g_generic_node_free(t,node) g_free (node) -#endif /* !DISABLE_MEM_POOLS */ - - /* --- typedefs --- */ typedef struct _SignalNode SignalNode; typedef struct _SignalKey SignalKey; @@ -232,10 +196,7 @@ struct _HandlerMatch { Handler *handler; HandlerMatch *next; - union { - guint signal_id; - gpointer dummy; - } d; + guint signal_id; }; typedef struct @@ -434,10 +395,10 @@ handler_match_prepend (HandlerMatch *list, * instead, we use GList* nodes, since they are exactly the size * we need and are already cached. g_signal_init() asserts this. */ - node = (HandlerMatch*) g_list_alloc (); + node = g_slice_new (HandlerMatch); node->handler = handler; node->next = list; - node->d.signal_id = signal_id; + node->signal_id = signal_id; handler_ref (handler); return node; @@ -448,8 +409,8 @@ handler_match_free1_R (HandlerMatch *node, { HandlerMatch *next = node->next; - handler_unref_R (node->d.signal_id, instance, node->handler); - g_list_free_1 ((GList*) node); + handler_unref_R (node->signal_id, instance, node->handler); + g_slice_free (HandlerMatch, node); return next; } @@ -541,9 +502,7 @@ handlers_find (gpointer instance, static inline Handler* handler_new (gboolean after) { - Handler *handler = g_generic_node_alloc (&g_handler_ts, - sizeof (Handler), - HANDLER_PRE_ALLOC); + Handler *handler = g_slice_new (Handler); #ifndef G_DISABLE_CHECKS if (g_handler_sequential_number < 1) g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG); @@ -624,7 +583,7 @@ handler_unref_R (guint signal_id, SIGNAL_UNLOCK (); g_closure_unref (handler->closure); SIGNAL_LOCK (); - g_generic_node_free (&g_handler_ts, handler); + g_slice_free (Handler, handler); } } diff --git a/gobject/gtype.c b/gobject/gtype.c index c67ed6d..3d312b2 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -278,7 +278,6 @@ struct _InstanceData guint16 private_size; guint16 n_preallocs; GInstanceInitFunc instance_init; - GMemChunk *mem_chunk; }; union _TypeData { @@ -976,7 +975,6 @@ type_data_make_W (TypeNode *node, data->instance.n_preallocs = MIN (info->n_preallocs, 1024); #endif /* !DISABLE_MEM_POOLS */ data->instance.instance_init = info->instance_init; - data->instance.mem_chunk = NULL; } else if (node->is_classed) /* only classed */ { @@ -1526,8 +1524,7 @@ g_type_create_instance (GType type) TypeNode *node; GTypeInstance *instance; GTypeClass *class; - guint i; - gsize total_instance_size; + guint i, total_size; node = lookup_type_node_I (type); if (!node || !node->is_instantiatable) @@ -1545,35 +1542,12 @@ g_type_create_instance (GType type) } class = g_type_class_ref (type); + total_size = type_total_instance_size_I (node); - total_instance_size = type_total_instance_size_I (node); - if (node->data->instance.n_preallocs) - { - G_WRITE_LOCK (&type_rw_lock); - if (!node->data->instance.mem_chunk) - { - /* If there isn't private data, the compiler will have already - * added the necessary padding, but in the private data case, we - * have to pad ourselves to ensure proper alignment of all the - * atoms in the slab. - */ - gsize atom_size = total_instance_size; - if (node->data->instance.private_size) - atom_size = ALIGN_STRUCT (atom_size); - - node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node), - atom_size, - (atom_size * - node->data->instance.n_preallocs), - G_ALLOC_AND_FREE); - } - - instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk); - G_WRITE_UNLOCK (&type_rw_lock); - } + instance = g_slice_alloc0 (total_size); else - instance = g_malloc0 (total_instance_size); /* fine without read lock */ + instance = g_malloc0 (total_size); if (node->data->instance.private_size) instance_real_class_set (instance, class); @@ -1624,17 +1598,13 @@ g_type_free_instance (GTypeInstance *instance) instance->g_class = NULL; #ifdef G_ENABLE_DEBUG - memset (instance, 0xaa, type_total_instance_size_I (node)); /* debugging hack */ -#endif + memset (instance, 0xaa, type_total_instance_size_I (node)); +#endif if (node->data->instance.n_preallocs) - { - G_WRITE_LOCK (&type_rw_lock); - g_chunk_free (instance, node->data->instance.mem_chunk); - G_WRITE_UNLOCK (&type_rw_lock); - } + g_slice_free1 (type_total_instance_size_I (node), instance); else g_free (instance); - + g_type_class_unref (class); } @@ -2045,10 +2015,9 @@ type_data_last_unref_Wm (GType type, node->data->common.ref_count = 0; - if (node->is_instantiatable && node->data->instance.mem_chunk) + if (node->is_instantiatable) { - g_mem_chunk_destroy (node->data->instance.mem_chunk); - node->data->instance.mem_chunk = NULL; + /* destroy node->data->instance.mem_chunk */ } tdata = node->data; -- 2.7.4