mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 23:16:14 +01:00
prepared deprecation of GMemChunk and GAllocator. added g_slice_*() API to
Tue Nov 1 16:24:20 2005 Tim Janik <timj@imendio.com> * 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.
This commit is contained in:
parent
3a042a8959
commit
0cba1b531d
50
ChangeLog
50
ChangeLog
@ -1,3 +1,53 @@
|
||||
Tue Nov 1 16:24:20 2005 Tim Janik <timj@imendio.com>
|
||||
|
||||
* 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 <mclasen@redhat.com>
|
||||
|
||||
* tests/convert-test.c: Add some tests for conversions between
|
||||
|
@ -1,3 +1,53 @@
|
||||
Tue Nov 1 16:24:20 2005 Tim Janik <timj@imendio.com>
|
||||
|
||||
* 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 <mclasen@redhat.com>
|
||||
|
||||
* tests/convert-test.c: Add some tests for conversions between
|
||||
|
@ -1,3 +1,53 @@
|
||||
Tue Nov 1 16:24:20 2005 Tim Janik <timj@imendio.com>
|
||||
|
||||
* 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 <mclasen@redhat.com>
|
||||
|
||||
* tests/convert-test.c: Add some tests for conversions between
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
84
glib/ghash.c
84
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__
|
||||
|
23
glib/ghook.c
23
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
|
||||
|
@ -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];
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
212
glib/glist.c
212
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 */
|
||||
};
|
||||
void g_list_push_allocator (gpointer dummy) { /* present for binary compat only */ }
|
||||
void g_list_pop_allocator (void) { /* present for binary compat only */ }
|
||||
|
||||
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;
|
||||
}
|
||||
#define _g_list_alloc0() g_slice_new0 (GList)
|
||||
#define _g_list_free1(list) g_slice_free (GList, list)
|
||||
|
||||
GList*
|
||||
g_list_alloc (void)
|
||||
{
|
||||
return _g_list_alloc ();
|
||||
return _g_list_alloc0 ();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
#ifdef ENABLE_GC_FRIENDLY
|
||||
list->prev = NULL;
|
||||
#endif /* ENABLE_GC_FRIENDLY */
|
||||
|
||||
G_LOCK (current_allocator);
|
||||
list->next = current_allocator->free_lists;
|
||||
current_allocator->free_lists = list;
|
||||
G_UNLOCK (current_allocator);
|
||||
}
|
||||
g_slice_free_chain (sizeof (GList), list, G_STRUCT_OFFSET (GList, next));
|
||||
}
|
||||
|
||||
void
|
||||
g_list_free_1 (GList *list)
|
||||
{
|
||||
_g_list_free_1 (list);
|
||||
_g_list_free1 (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;
|
||||
}
|
||||
|
||||
void
|
||||
g_list_free (GList *list)
|
||||
{
|
||||
GList *last;
|
||||
|
||||
while (list)
|
||||
{
|
||||
last = list;
|
||||
list = list->next;
|
||||
g_free (last);
|
||||
}
|
||||
}
|
||||
|
||||
#define _g_list_free_1 g_list_free_1
|
||||
void
|
||||
g_list_free_1 (GList *list)
|
||||
{
|
||||
g_free (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))
|
||||
|
@ -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__ */
|
||||
|
50
glib/gmain.c
50
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;
|
||||
|
95
glib/gmem.c
95
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
|
||||
|
74
glib/gmem.h
74
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
|
||||
|
||||
|
157
glib/gnode.c
157
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)
|
||||
while (node)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -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__ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
46
glib/grel.c
46
glib/grel.c
@ -45,7 +45,6 @@ struct _GRelation
|
||||
|
||||
GHashTable *all_tuples;
|
||||
GHashTable **hashed_tuple_tables;
|
||||
GMemChunk *tuple_chunk;
|
||||
|
||||
gint count;
|
||||
};
|
||||
@ -109,16 +108,22 @@ 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);
|
||||
|
||||
return rel;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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;
|
||||
}
|
||||
|
204
glib/gslist.c
204
glib/gslist.c
@ -34,199 +34,29 @@
|
||||
#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 */
|
||||
};
|
||||
void g_slist_push_allocator (gpointer dummy) { /* present for binary compat only */ }
|
||||
void g_slist_pop_allocator (void) { /* present for binary compat only */ }
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
return list;
|
||||
}
|
||||
#define _g_slist_alloc0() g_slice_new0 (GSList)
|
||||
#define _g_slist_free1(slist) g_slice_free (GSList, slist)
|
||||
|
||||
GSList*
|
||||
g_slist_alloc (void)
|
||||
{
|
||||
return _g_slist_alloc ();
|
||||
return _g_slist_alloc0 ();
|
||||
}
|
||||
|
||||
void
|
||||
g_slist_free (GSList *list)
|
||||
g_slist_free (GSList *slist)
|
||||
{
|
||||
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);
|
||||
}
|
||||
g_slice_free_chain (sizeof (GSList), slist, G_STRUCT_OFFSET (GSList, next));
|
||||
}
|
||||
|
||||
void
|
||||
g_slist_free_1 (GSList *list)
|
||||
g_slist_free_1 (GSList *slist)
|
||||
{
|
||||
_g_slist_free_1 (list);
|
||||
_g_slist_free1 (slist);
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
void
|
||||
g_slist_free (GSList *list)
|
||||
{
|
||||
GSList *last;
|
||||
|
||||
while (list)
|
||||
{
|
||||
last = list;
|
||||
list = list->next;
|
||||
g_free (last);
|
||||
}
|
||||
}
|
||||
|
||||
#define _g_slist_free_1 g_slist_free_1
|
||||
void
|
||||
g_slist_free_1 (GSList *list)
|
||||
{
|
||||
g_free (list);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
GSList*
|
||||
g_slist_append (GSList *list,
|
||||
@ -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))
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
115
glib/gthread.c
115
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"
|
||||
|
@ -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__ */
|
||||
|
35
glib/gtree.c
35
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;
|
||||
}
|
||||
|
@ -1,3 +1,11 @@
|
||||
Tue Nov 1 17:07:43 2005 Tim Janik <timj@imendio.com>
|
||||
|
||||
* 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 <mclasen@redhat.com>
|
||||
|
||||
* glib-mkenums.in: Really fix #314890.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user