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>
|
2005-10-29 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* tests/convert-test.c: Add some tests for conversions between
|
* 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>
|
2005-10-29 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* tests/convert-test.c: Add some tests for conversions between
|
* 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>
|
2005-10-29 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* tests/convert-test.c: Add some tests for conversions between
|
* 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,
|
static void g_array_maybe_expand (GRealArray *array,
|
||||||
gint len);
|
gint len);
|
||||||
|
|
||||||
static GMemChunk *array_mem_chunk = NULL;
|
|
||||||
G_LOCK_DEFINE_STATIC (array_mem_chunk);
|
|
||||||
|
|
||||||
GArray*
|
GArray*
|
||||||
g_array_new (gboolean zero_terminated,
|
g_array_new (gboolean zero_terminated,
|
||||||
gboolean clear,
|
gboolean clear,
|
||||||
@ -86,16 +83,7 @@ GArray* g_array_sized_new (gboolean zero_terminated,
|
|||||||
guint elt_size,
|
guint elt_size,
|
||||||
guint reserved_size)
|
guint reserved_size)
|
||||||
{
|
{
|
||||||
GRealArray *array;
|
GRealArray *array = g_slice_new (GRealArray);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
array->data = NULL;
|
array->data = NULL;
|
||||||
array->len = 0;
|
array->len = 0;
|
||||||
@ -129,9 +117,7 @@ g_array_free (GArray *array,
|
|||||||
else
|
else
|
||||||
segment = array->data;
|
segment = array->data;
|
||||||
|
|
||||||
G_LOCK (array_mem_chunk);
|
g_slice_free1 (sizeof (GRealArray), array);
|
||||||
g_mem_chunk_free (array_mem_chunk, array);
|
|
||||||
G_UNLOCK (array_mem_chunk);
|
|
||||||
|
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
@ -380,10 +366,6 @@ struct _GRealPtrArray
|
|||||||
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
|
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
|
||||||
gint len);
|
gint len);
|
||||||
|
|
||||||
static GMemChunk *ptr_array_mem_chunk = NULL;
|
|
||||||
G_LOCK_DEFINE_STATIC (ptr_array_mem_chunk);
|
|
||||||
|
|
||||||
|
|
||||||
GPtrArray*
|
GPtrArray*
|
||||||
g_ptr_array_new (void)
|
g_ptr_array_new (void)
|
||||||
{
|
{
|
||||||
@ -393,16 +375,7 @@ g_ptr_array_new (void)
|
|||||||
GPtrArray*
|
GPtrArray*
|
||||||
g_ptr_array_sized_new (guint reserved_size)
|
g_ptr_array_sized_new (guint reserved_size)
|
||||||
{
|
{
|
||||||
GRealPtrArray *array;
|
GRealPtrArray *array = g_slice_new (GRealPtrArray);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
array->pdata = NULL;
|
array->pdata = NULL;
|
||||||
array->len = 0;
|
array->len = 0;
|
||||||
@ -430,9 +403,7 @@ g_ptr_array_free (GPtrArray *array,
|
|||||||
else
|
else
|
||||||
segment = array->pdata;
|
segment = array->pdata;
|
||||||
|
|
||||||
G_LOCK (ptr_array_mem_chunk);
|
g_slice_free1 (sizeof (GRealPtrArray), array);
|
||||||
g_mem_chunk_free (ptr_array_mem_chunk, array);
|
|
||||||
G_UNLOCK (ptr_array_mem_chunk);
|
|
||||||
|
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
@ -64,13 +64,20 @@ struct _GCache
|
|||||||
GHashTable *value_table;
|
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 inline void
|
||||||
static void g_cache_node_destroy (GCacheNode *node);
|
g_cache_node_destroy (GCacheNode *node)
|
||||||
|
{
|
||||||
|
g_slice_free (GCacheNode, node);
|
||||||
static GMemChunk *node_mem_chunk = NULL;
|
}
|
||||||
G_LOCK_DEFINE_STATIC (node_mem_chunk);
|
|
||||||
|
|
||||||
GCache*
|
GCache*
|
||||||
g_cache_new (GCacheNewFunc value_new_func,
|
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 (hash_value_func != NULL, NULL);
|
||||||
g_return_val_if_fail (key_equal_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_new_func = value_new_func;
|
||||||
cache->value_destroy_func = value_destroy_func;
|
cache->value_destroy_func = value_destroy_func;
|
||||||
cache->key_dup_func = key_dup_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->key_table);
|
||||||
g_hash_table_destroy (cache->value_table);
|
g_hash_table_destroy (cache->value_table);
|
||||||
g_free (cache);
|
g_slice_free (GCache, cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpointer
|
gpointer
|
||||||
@ -186,33 +193,5 @@ g_cache_value_foreach (GCache *cache,
|
|||||||
g_hash_table_foreach (cache->key_table, func, user_data);
|
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__
|
#define __G_CACHE_C__
|
||||||
#include "galiasdef.c"
|
#include "galiasdef.c"
|
||||||
|
@ -41,9 +41,7 @@
|
|||||||
|
|
||||||
/* --- defines --- */
|
/* --- defines --- */
|
||||||
#define G_QUARK_BLOCK_SIZE (512)
|
#define G_QUARK_BLOCK_SIZE (512)
|
||||||
#define G_DATA_MEM_CHUNK_PREALLOC (128)
|
|
||||||
#define G_DATA_CACHE_MAX (512)
|
#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 */
|
/* datalist pointer modifications have to be done with the g_dataset_global mutex held */
|
||||||
#define G_DATALIST_GET_POINTER(datalist) \
|
#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 GHashTable *g_dataset_location_ht = NULL;
|
||||||
static GDataset *g_dataset_cached = NULL; /* should this be
|
static GDataset *g_dataset_cached = NULL; /* should this be
|
||||||
threadspecific? */
|
threadspecific? */
|
||||||
static GMemChunk *g_dataset_mem_chunk = NULL;
|
|
||||||
static GMemChunk *g_data_mem_chunk = NULL;
|
|
||||||
static GData *g_data_cache = NULL;
|
static GData *g_data_cache = NULL;
|
||||||
static guint g_data_cache_length = 0;
|
static guint g_data_cache_length = 0;
|
||||||
|
|
||||||
@ -133,7 +129,7 @@ g_datalist_clear_i (GData **datalist)
|
|||||||
g_data_cache_length++;
|
g_data_cache_length++;
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (dataset == g_dataset_cached)
|
||||||
g_dataset_cached = NULL;
|
g_dataset_cached = NULL;
|
||||||
g_hash_table_remove (g_dataset_location_ht, dataset_location);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +260,7 @@ g_data_set_internal (GData **datalist,
|
|||||||
g_data_cache_length++;
|
g_data_cache_length++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
g_mem_chunk_free (g_data_mem_chunk, list);
|
g_slice_free (GData, list);
|
||||||
|
|
||||||
return ret_data;
|
return ret_data;
|
||||||
}
|
}
|
||||||
@ -315,7 +311,7 @@ g_data_set_internal (GData **datalist,
|
|||||||
g_data_cache_length--;
|
g_data_cache_length--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
list = g_chunk_new (GData, g_data_mem_chunk);
|
list = g_slice_new (GData);
|
||||||
list->next = G_DATALIST_GET_POINTER (datalist);
|
list->next = G_DATALIST_GET_POINTER (datalist);
|
||||||
list->id = key_id;
|
list->id = key_id;
|
||||||
list->data = data;
|
list->data = data;
|
||||||
@ -352,7 +348,7 @@ g_dataset_id_set_data_full (gconstpointer dataset_location,
|
|||||||
dataset = g_dataset_lookup (dataset_location);
|
dataset = g_dataset_lookup (dataset_location);
|
||||||
if (!dataset)
|
if (!dataset)
|
||||||
{
|
{
|
||||||
dataset = g_chunk_new (GDataset, g_dataset_mem_chunk);
|
dataset = g_slice_new (GDataset);
|
||||||
dataset->location = dataset_location;
|
dataset->location = dataset_location;
|
||||||
g_datalist_init (&dataset->datalist);
|
g_datalist_init (&dataset->datalist);
|
||||||
g_hash_table_insert (g_dataset_location_ht,
|
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_location_ht = g_hash_table_new (g_direct_hash, NULL);
|
||||||
g_dataset_cached = 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
|
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);
|
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:
|
* g_hash_table_new:
|
||||||
* @hash_func: a function to create a hash value from a key.
|
* @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;
|
GHashTable *hash_table;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
hash_table = g_new (GHashTable, 1);
|
hash_table = g_slice_new (GHashTable);
|
||||||
hash_table->size = HASH_TABLE_MIN_SIZE;
|
hash_table->size = HASH_TABLE_MIN_SIZE;
|
||||||
hash_table->nnodes = 0;
|
hash_table->nnodes = 0;
|
||||||
hash_table->hash_func = hash_func ? hash_func : g_direct_hash;
|
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);
|
hash_table->value_destroy_func);
|
||||||
|
|
||||||
g_free (hash_table->nodes);
|
g_free (hash_table->nodes);
|
||||||
g_free (hash_table);
|
g_slice_free (GHashTable, hash_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline GHashNode**
|
static inline GHashNode**
|
||||||
@ -649,28 +642,7 @@ static GHashNode*
|
|||||||
g_hash_node_new (gpointer key,
|
g_hash_node_new (gpointer key,
|
||||||
gpointer value)
|
gpointer value)
|
||||||
{
|
{
|
||||||
GHashNode *hash_node;
|
GHashNode *hash_node = g_slice_new (GHashNode);
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
||||||
hash_node->key = key;
|
hash_node->key = key;
|
||||||
hash_node->value = value;
|
hash_node->value = value;
|
||||||
@ -694,14 +666,7 @@ g_hash_node_destroy (GHashNode *hash_node,
|
|||||||
hash_node->value = NULL;
|
hash_node->value = NULL;
|
||||||
#endif /* ENABLE_GC_FRIENDLY */
|
#endif /* ENABLE_GC_FRIENDLY */
|
||||||
|
|
||||||
#ifdef DISABLE_MEM_POOLS
|
g_slice_free (GHashNode, hash_node);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -709,55 +674,16 @@ g_hash_nodes_destroy (GHashNode *hash_node,
|
|||||||
GFreeFunc key_destroy_func,
|
GFreeFunc key_destroy_func,
|
||||||
GFreeFunc value_destroy_func)
|
GFreeFunc value_destroy_func)
|
||||||
{
|
{
|
||||||
#ifdef DISABLE_MEM_POOLS
|
|
||||||
while (hash_node)
|
while (hash_node)
|
||||||
{
|
{
|
||||||
GHashNode *next = hash_node->next;
|
GHashNode *next = hash_node->next;
|
||||||
|
|
||||||
if (key_destroy_func)
|
if (key_destroy_func)
|
||||||
key_destroy_func (hash_node->key);
|
key_destroy_func (hash_node->key);
|
||||||
if (value_destroy_func)
|
if (value_destroy_func)
|
||||||
value_destroy_func (hash_node->value);
|
value_destroy_func (hash_node->value);
|
||||||
|
g_slice_free (GHashNode, hash_node);
|
||||||
g_free (hash_node);
|
|
||||||
hash_node = next;
|
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__
|
#define __G_HASH_C__
|
||||||
|
23
glib/ghook.c
23
glib/ghook.c
@ -37,10 +37,6 @@
|
|||||||
#include "galias.h"
|
#include "galias.h"
|
||||||
|
|
||||||
|
|
||||||
/* --- defines --- */
|
|
||||||
#define G_HOOKS_PREALLOC (16)
|
|
||||||
|
|
||||||
|
|
||||||
/* --- functions --- */
|
/* --- functions --- */
|
||||||
static void
|
static void
|
||||||
default_finalize_hook (GHookList *hook_list,
|
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_list != NULL);
|
||||||
g_return_if_fail (hook_size >= sizeof (GHook));
|
g_return_if_fail (hook_size >= sizeof (GHook));
|
||||||
g_return_if_fail (hook_size < 65536);
|
|
||||||
|
|
||||||
hook_list->seq_id = 1;
|
hook_list->seq_id = 1;
|
||||||
hook_list->hook_size = hook_size;
|
hook_list->hook_size = hook_size;
|
||||||
hook_list->is_setup = TRUE;
|
hook_list->is_setup = TRUE;
|
||||||
hook_list->hooks = NULL;
|
hook_list->hooks = NULL;
|
||||||
hook_list->hook_memchunk = g_mem_chunk_new ("GHook Memchunk",
|
hook_list->dummy3 = NULL;
|
||||||
hook_size,
|
|
||||||
hook_size * G_HOOKS_PREALLOC,
|
|
||||||
G_ALLOC_AND_FREE);
|
|
||||||
hook_list->finalize_hook = default_finalize_hook;
|
hook_list->finalize_hook = default_finalize_hook;
|
||||||
hook_list->dummy[0] = NULL;
|
hook_list->dummy[0] = NULL;
|
||||||
hook_list->dummy[1] = NULL;
|
hook_list->dummy[1] = NULL;
|
||||||
@ -90,8 +82,7 @@ g_hook_list_clear (GHookList *hook_list)
|
|||||||
hook = hook_list->hooks;
|
hook = hook_list->hooks;
|
||||||
if (!hook)
|
if (!hook)
|
||||||
{
|
{
|
||||||
g_mem_chunk_destroy (hook_list->hook_memchunk);
|
/* destroy hook_list->hook_memchunk */
|
||||||
hook_list->hook_memchunk = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
do
|
do
|
||||||
@ -105,8 +96,6 @@ g_hook_list_clear (GHookList *hook_list)
|
|||||||
hook = tmp;
|
hook = tmp;
|
||||||
}
|
}
|
||||||
while (hook);
|
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 != NULL, NULL);
|
||||||
g_return_val_if_fail (hook_list->is_setup, 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->data = NULL;
|
||||||
hook->next = NULL;
|
hook->next = NULL;
|
||||||
hook->prev = NULL;
|
hook->prev = NULL;
|
||||||
@ -142,7 +131,7 @@ g_hook_free (GHookList *hook_list,
|
|||||||
g_return_if_fail (!G_HOOK_IN_CALL (hook));
|
g_return_if_fail (!G_HOOK_IN_CALL (hook));
|
||||||
|
|
||||||
hook_list->finalize_hook (hook_list, 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
|
void
|
||||||
@ -184,7 +173,6 @@ g_hook_unref (GHookList *hook_list,
|
|||||||
GHook *hook)
|
GHook *hook)
|
||||||
{
|
{
|
||||||
g_return_if_fail (hook_list != NULL);
|
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 != NULL);
|
||||||
g_return_if_fail (hook->ref_count > 0);
|
g_return_if_fail (hook->ref_count > 0);
|
||||||
|
|
||||||
@ -213,8 +201,7 @@ g_hook_unref (GHookList *hook_list,
|
|||||||
|
|
||||||
if (!hook_list->hooks)
|
if (!hook_list->hooks)
|
||||||
{
|
{
|
||||||
g_mem_chunk_destroy (hook_list->hook_memchunk);
|
/* destroy hook_list->hook_memchunk */
|
||||||
hook_list->hook_memchunk = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -64,7 +64,7 @@ struct _GHookList
|
|||||||
guint hook_size : 16;
|
guint hook_size : 16;
|
||||||
guint is_setup : 1;
|
guint is_setup : 1;
|
||||||
GHook *hooks;
|
GHook *hooks;
|
||||||
GMemChunk *hook_memchunk;
|
gpointer dummy3;
|
||||||
GHookFinalizeFunc finalize_hook;
|
GHookFinalizeFunc finalize_hook;
|
||||||
gpointer dummy[2];
|
gpointer dummy[2];
|
||||||
};
|
};
|
||||||
|
@ -565,6 +565,18 @@ g_markup_vprintf_escaped
|
|||||||
#if IN_HEADER(__G_MEM_H__)
|
#if IN_HEADER(__G_MEM_H__)
|
||||||
#if IN_FILE(__G_MEM_C__)
|
#if IN_FILE(__G_MEM_C__)
|
||||||
g_free
|
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_alloc
|
||||||
g_mem_chunk_alloc0
|
g_mem_chunk_alloc0
|
||||||
g_mem_chunk_clean
|
g_mem_chunk_clean
|
||||||
@ -574,18 +586,8 @@ g_mem_chunk_info
|
|||||||
g_mem_chunk_new
|
g_mem_chunk_new
|
||||||
g_mem_chunk_print
|
g_mem_chunk_print
|
||||||
g_mem_chunk_reset
|
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_blow_chunks
|
||||||
g_try_malloc G_GNUC_MALLOC
|
#endif
|
||||||
g_try_malloc0 G_GNUC_MALLOC
|
|
||||||
g_try_realloc
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1031,6 +1033,7 @@ g_static_rw_lock_reader_unlock
|
|||||||
g_static_rw_lock_writer_lock
|
g_static_rw_lock_writer_lock
|
||||||
g_static_rw_lock_writer_trylock
|
g_static_rw_lock_writer_trylock
|
||||||
g_static_rw_lock_writer_unlock
|
g_static_rw_lock_writer_unlock
|
||||||
|
g_thread_foreach
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
212
glib/glist.c
212
glib/glist.c
@ -34,208 +34,30 @@
|
|||||||
#include "galias.h"
|
#include "galias.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef DISABLE_MEM_POOLS
|
void g_list_push_allocator (gpointer dummy) { /* present for binary compat only */ }
|
||||||
struct _GAllocator /* from gmem.c */
|
void g_list_pop_allocator (void) { /* present for binary compat only */ }
|
||||||
{
|
|
||||||
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;
|
#define _g_list_alloc0() g_slice_new0 (GList)
|
||||||
G_LOCK_DEFINE_STATIC (current_allocator);
|
#define _g_list_free1(list) g_slice_free (GList, list)
|
||||||
|
|
||||||
/* 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*
|
GList*
|
||||||
g_list_alloc (void)
|
g_list_alloc (void)
|
||||||
{
|
{
|
||||||
return _g_list_alloc ();
|
return _g_list_alloc0 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
g_list_free (GList *list)
|
g_list_free (GList *list)
|
||||||
{
|
{
|
||||||
if (list)
|
g_slice_free_chain (sizeof (GList), list, G_STRUCT_OFFSET (GList, next));
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
g_list_free_1 (GList *list)
|
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*
|
GList*
|
||||||
g_list_append (GList *list,
|
g_list_append (GList *list,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
@ -243,7 +65,7 @@ g_list_append (GList *list,
|
|||||||
GList *new_list;
|
GList *new_list;
|
||||||
GList *last;
|
GList *last;
|
||||||
|
|
||||||
new_list = _g_list_alloc ();
|
new_list = _g_list_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
|
|
||||||
if (list)
|
if (list)
|
||||||
@ -265,7 +87,7 @@ g_list_prepend (GList *list,
|
|||||||
{
|
{
|
||||||
GList *new_list;
|
GList *new_list;
|
||||||
|
|
||||||
new_list = _g_list_alloc ();
|
new_list = _g_list_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
|
|
||||||
if (list)
|
if (list)
|
||||||
@ -299,7 +121,7 @@ g_list_insert (GList *list,
|
|||||||
if (!tmp_list)
|
if (!tmp_list)
|
||||||
return g_list_append (list, data);
|
return g_list_append (list, data);
|
||||||
|
|
||||||
new_list = _g_list_alloc ();
|
new_list = _g_list_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
|
|
||||||
if (tmp_list->prev)
|
if (tmp_list->prev)
|
||||||
@ -405,7 +227,7 @@ g_list_remove (GList *list,
|
|||||||
if (list == tmp)
|
if (list == tmp)
|
||||||
list = list->next;
|
list = list->next;
|
||||||
|
|
||||||
_g_list_free_1 (tmp);
|
_g_list_free1 (tmp);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -434,7 +256,7 @@ g_list_remove_all (GList *list,
|
|||||||
if (next)
|
if (next)
|
||||||
next->prev = tmp->prev;
|
next->prev = tmp->prev;
|
||||||
|
|
||||||
_g_list_free_1 (tmp);
|
_g_list_free1 (tmp);
|
||||||
tmp = next;
|
tmp = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -474,7 +296,7 @@ g_list_delete_link (GList *list,
|
|||||||
GList *link)
|
GList *link)
|
||||||
{
|
{
|
||||||
list = _g_list_remove_link (list, link);
|
list = _g_list_remove_link (list, link);
|
||||||
_g_list_free_1 (link);
|
_g_list_free1 (link);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@ -488,13 +310,13 @@ g_list_copy (GList *list)
|
|||||||
{
|
{
|
||||||
GList *last;
|
GList *last;
|
||||||
|
|
||||||
new_list = _g_list_alloc ();
|
new_list = _g_list_alloc0 ();
|
||||||
new_list->data = list->data;
|
new_list->data = list->data;
|
||||||
last = new_list;
|
last = new_list;
|
||||||
list = list->next;
|
list = list->next;
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
last->next = _g_list_alloc ();
|
last->next = _g_list_alloc0 ();
|
||||||
last->next->prev = last;
|
last->next->prev = last;
|
||||||
last = last->next;
|
last = last->next;
|
||||||
last->data = list->data;
|
last->data = list->data;
|
||||||
@ -686,7 +508,7 @@ g_list_insert_sorted (GList *list,
|
|||||||
|
|
||||||
if (!list)
|
if (!list)
|
||||||
{
|
{
|
||||||
new_list = _g_list_alloc ();
|
new_list = _g_list_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
return new_list;
|
return new_list;
|
||||||
}
|
}
|
||||||
@ -699,7 +521,7 @@ g_list_insert_sorted (GList *list,
|
|||||||
cmp = (*func) (data, tmp_list->data);
|
cmp = (*func) (data, tmp_list->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_list = _g_list_alloc ();
|
new_list = _g_list_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
|
|
||||||
if ((!tmp_list->next) && (cmp > 0))
|
if ((!tmp_list->next) && (cmp > 0))
|
||||||
|
@ -42,11 +42,10 @@ struct _GList
|
|||||||
|
|
||||||
/* Doubly linked lists
|
/* Doubly linked lists
|
||||||
*/
|
*/
|
||||||
void g_list_push_allocator (GAllocator *allocator);
|
|
||||||
void g_list_pop_allocator (void);
|
|
||||||
GList* g_list_alloc (void);
|
GList* g_list_alloc (void);
|
||||||
void g_list_free (GList *list);
|
void g_list_free (GList *list);
|
||||||
void g_list_free_1 (GList *list);
|
void g_list_free_1 (GList *list);
|
||||||
|
#define g_list_free1 g_list_free_1
|
||||||
GList* g_list_append (GList *list,
|
GList* g_list_append (GList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GList* g_list_prepend (GList *list,
|
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_previous(list) ((list) ? (((GList *)(list))->prev) : NULL)
|
||||||
#define g_list_next(list) ((list) ? (((GList *)(list))->next) : 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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_LIST_H__ */
|
#endif /* __G_LIST_H__ */
|
||||||
|
50
glib/gmain.c
50
glib/gmain.c
@ -125,8 +125,6 @@ struct _GMainContext
|
|||||||
gint in_check_or_prepare;
|
gint in_check_or_prepare;
|
||||||
|
|
||||||
GPollRec *poll_records;
|
GPollRec *poll_records;
|
||||||
GPollRec *poll_free_list;
|
|
||||||
GMemChunk *poll_chunk;
|
|
||||||
guint n_poll_records;
|
guint n_poll_records;
|
||||||
GPollFD *cached_poll_array;
|
GPollFD *cached_poll_array;
|
||||||
guint cached_poll_array_size;
|
guint cached_poll_array_size;
|
||||||
@ -190,9 +188,9 @@ struct _GChildWatchSource
|
|||||||
|
|
||||||
struct _GPollRec
|
struct _GPollRec
|
||||||
{
|
{
|
||||||
gint priority;
|
|
||||||
GPollFD *fd;
|
GPollFD *fd;
|
||||||
GPollRec *next;
|
GPollRec *next; /* chaining via second pointer member allows use of g_slice_free_chain() */
|
||||||
|
gint priority;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef G_THREADS_ENABLED
|
#ifdef G_THREADS_ENABLED
|
||||||
@ -597,25 +595,12 @@ g_main_context_ref (GMainContext *context)
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If DISABLE_MEM_POOLS is defined, then freeing the
|
static inline void
|
||||||
* 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
|
|
||||||
poll_rec_list_free (GMainContext *context,
|
poll_rec_list_free (GMainContext *context,
|
||||||
GPollRec *list)
|
GPollRec *list)
|
||||||
{
|
{
|
||||||
while (list)
|
g_slice_free_chain (sizeof (GPollRec), list, G_STRUCT_OFFSET (GPollRec, next));
|
||||||
{
|
|
||||||
GPollRec *tmp_rec = list;
|
|
||||||
list = list->next;
|
|
||||||
g_chunk_free (tmp_rec, context->poll_chunk);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* DISABLE_MEM_POOLS */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_main_context_unref:
|
* g_main_context_unref:
|
||||||
@ -653,13 +638,7 @@ g_main_context_unref (GMainContext *context)
|
|||||||
g_ptr_array_free (context->pending_dispatches, TRUE);
|
g_ptr_array_free (context->pending_dispatches, TRUE);
|
||||||
g_free (context->cached_poll_array);
|
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_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
|
#ifdef G_THREADS_ENABLED
|
||||||
if (g_thread_supported())
|
if (g_thread_supported())
|
||||||
@ -2951,18 +2930,8 @@ g_main_context_add_poll_unlocked (GMainContext *context,
|
|||||||
gint priority,
|
gint priority,
|
||||||
GPollFD *fd)
|
GPollFD *fd)
|
||||||
{
|
{
|
||||||
GPollRec *lastrec, *pollrec, *newrec;
|
GPollRec *lastrec, *pollrec;
|
||||||
|
GPollRec *newrec = g_slice_new (GPollRec);
|
||||||
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);
|
|
||||||
|
|
||||||
/* This file descriptor may be checked before we ever poll */
|
/* This file descriptor may be checked before we ever poll */
|
||||||
fd->revents = 0;
|
fd->revents = 0;
|
||||||
@ -3035,12 +3004,7 @@ g_main_context_remove_poll_unlocked (GMainContext *context,
|
|||||||
else
|
else
|
||||||
context->poll_records = pollrec->next;
|
context->poll_records = pollrec->next;
|
||||||
|
|
||||||
#ifdef ENABLE_GC_FRIENDLY
|
g_slice_free (GPollRec, pollrec);
|
||||||
pollrec->fd = NULL;
|
|
||||||
#endif /* ENABLE_GC_FRIENDLY */
|
|
||||||
|
|
||||||
pollrec->next = context->poll_free_list;
|
|
||||||
context->poll_free_list = pollrec;
|
|
||||||
|
|
||||||
context->n_poll_records--;
|
context->n_poll_records--;
|
||||||
break;
|
break;
|
||||||
|
95
glib/gmem.c
95
glib/gmem.c
@ -602,8 +602,55 @@ GMemVTable *glib_mem_profiler_table = &profiler_table;
|
|||||||
|
|
||||||
#endif /* !G_DISABLE_CHECKS */
|
#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 --- */
|
/* --- 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 _GFreeAtom GFreeAtom;
|
||||||
typedef struct _GMemArea GMemArea;
|
typedef struct _GMemArea GMemArea;
|
||||||
|
|
||||||
@ -1219,50 +1266,28 @@ void g_blow_chunks (void) {}
|
|||||||
#endif /* DISABLE_MEM_POOLS */
|
#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*
|
GAllocator*
|
||||||
g_allocator_new (const gchar *name,
|
g_allocator_new (const gchar *name,
|
||||||
guint n_preallocs)
|
guint n_preallocs)
|
||||||
{
|
{
|
||||||
GAllocator *allocator;
|
static const struct _GAllocator {
|
||||||
|
gchar *name;
|
||||||
g_return_val_if_fail (name != NULL, NULL);
|
guint16 n_preallocs;
|
||||||
|
guint is_unused : 1;
|
||||||
allocator = g_new0 (GAllocator, 1);
|
guint type : 4;
|
||||||
allocator->name = g_strdup (name);
|
GAllocator *last;
|
||||||
allocator->n_preallocs = CLAMP (n_preallocs, 1, 65535);
|
GMemChunk *mem_chunk;
|
||||||
allocator->is_unused = TRUE;
|
gpointer free_list;
|
||||||
allocator->type = 0;
|
} dummy = {
|
||||||
allocator->last = NULL;
|
"GAllocator is deprecated", 0, TRUE, 0, NULL, NULL, NULL,
|
||||||
allocator->mem_chunk = NULL;
|
};
|
||||||
allocator->dummy = NULL;
|
/* some (broken) GAllocator uses depend on non-NULL allocators */
|
||||||
|
return (GAllocator*) &dummy;
|
||||||
return allocator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
g_allocator_free (GAllocator *allocator)
|
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
|
void
|
||||||
|
74
glib/gmem.h
74
glib/gmem.h
@ -31,8 +31,6 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct _GAllocator GAllocator;
|
|
||||||
typedef struct _GMemChunk GMemChunk;
|
|
||||||
typedef struct _GMemVTable GMemVTable;
|
typedef struct _GMemVTable GMemVTable;
|
||||||
|
|
||||||
|
|
||||||
@ -98,9 +96,24 @@ gboolean g_mem_is_system_malloc (void);
|
|||||||
GLIB_VAR GMemVTable *glib_mem_profiler_table;
|
GLIB_VAR GMemVTable *glib_mem_profiler_table;
|
||||||
void g_mem_profile (void);
|
void g_mem_profile (void);
|
||||||
|
|
||||||
|
/* slices - fast allocation/release of small memory blocks
|
||||||
/* Memchunk convenience functions
|
|
||||||
*/
|
*/
|
||||||
|
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) ( \
|
#define g_mem_chunk_create(type, pre_alloc, alloc_type) ( \
|
||||||
g_mem_chunk_new (#type " mem chunks (" #pre_alloc ")", \
|
g_mem_chunk_new (#type " mem chunks (" #pre_alloc ")", \
|
||||||
sizeof (type), \
|
sizeof (type), \
|
||||||
@ -116,30 +129,8 @@ void g_mem_profile (void);
|
|||||||
#define g_chunk_free(mem, mem_chunk) G_STMT_START { \
|
#define g_chunk_free(mem, mem_chunk) G_STMT_START { \
|
||||||
g_mem_chunk_free ((mem_chunk), (mem)); \
|
g_mem_chunk_free ((mem_chunk), (mem)); \
|
||||||
} G_STMT_END
|
} 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_ONLY 1
|
||||||
#define G_ALLOC_AND_FREE 2
|
#define G_ALLOC_AND_FREE 2
|
||||||
|
|
||||||
GMemChunk* g_mem_chunk_new (const gchar *name,
|
GMemChunk* g_mem_chunk_new (const gchar *name,
|
||||||
gint atom_size,
|
gint atom_size,
|
||||||
gulong area_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_reset (GMemChunk *mem_chunk);
|
||||||
void g_mem_chunk_print (GMemChunk *mem_chunk);
|
void g_mem_chunk_print (GMemChunk *mem_chunk);
|
||||||
void g_mem_chunk_info (void);
|
void g_mem_chunk_info (void);
|
||||||
|
void g_blow_chunks (void);
|
||||||
/* Ah yes...we have a "g_blow_chunks" function.
|
GAllocator*g_allocator_new (const gchar *name,
|
||||||
* "g_blow_chunks" simply compresses all the chunks. This operation
|
guint n_preallocs);
|
||||||
* consists of freeing every memory area that should be freed (but
|
void g_allocator_free (GAllocator *allocator);
|
||||||
* which we haven't gotten around to doing yet). And, no,
|
#define G_ALLOCATOR_LIST (1)
|
||||||
* "g_blow_chunks" doesn't follow the naming scheme, but it is a
|
#define G_ALLOCATOR_SLIST (2)
|
||||||
* much better name than "g_mem_chunk_clean_all" or something
|
#define G_ALLOCATOR_NODE (3)
|
||||||
* similar.
|
#endif /* G_DISABLE_DEPRECATED */
|
||||||
*/
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
157
glib/gnode.c
157
glib/gnode.c
@ -36,170 +36,33 @@
|
|||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
#include "galias.h"
|
#include "galias.h"
|
||||||
|
|
||||||
#ifndef DISABLE_MEM_POOLS
|
void g_node_push_allocator (gpointer dummy) { /* present for binary compat only */ }
|
||||||
/* node allocation
|
void g_node_pop_allocator (void) { /* present for binary compat only */ }
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#define g_node_alloc0() g_slice_new0 (GNode)
|
||||||
|
#define g_node_free(node) g_slice_free (GNode, node)
|
||||||
|
|
||||||
/* --- functions --- */
|
/* --- functions --- */
|
||||||
GNode*
|
GNode*
|
||||||
g_node_new (gpointer data)
|
g_node_new (gpointer data)
|
||||||
{
|
{
|
||||||
GNode *node;
|
GNode *node = g_node_alloc0();
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
node->data = data;
|
node->data = data;
|
||||||
node->next = NULL;
|
|
||||||
node->prev = NULL;
|
|
||||||
node->parent = NULL;
|
|
||||||
node->children = NULL;
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_nodes_free (GNode *node)
|
g_nodes_free (GNode *node)
|
||||||
{
|
{
|
||||||
GNode *parent;
|
while (node)
|
||||||
|
|
||||||
parent = node;
|
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
if (parent->children)
|
GNode *next = node->next;
|
||||||
g_nodes_free (parent->children);
|
if (node->children)
|
||||||
|
g_nodes_free (node->children);
|
||||||
#ifdef ENABLE_GC_FRIENDLY
|
g_node_free (node);
|
||||||
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);
|
|
||||||
node = next;
|
node = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
g_node_destroy (GNode *root)
|
g_node_destroy (GNode *root)
|
||||||
|
@ -76,8 +76,6 @@ struct _GNode
|
|||||||
((GNode*) (node))->next == NULL)
|
((GNode*) (node))->next == NULL)
|
||||||
#define G_NODE_IS_LEAF(node) (((GNode*) (node))->children == 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);
|
GNode* g_node_new (gpointer data);
|
||||||
void g_node_destroy (GNode *root);
|
void g_node_destroy (GNode *root);
|
||||||
void g_node_unlink (GNode *node);
|
void g_node_unlink (GNode *node);
|
||||||
@ -165,6 +163,10 @@ GNode* g_node_last_sibling (GNode *node);
|
|||||||
#define g_node_first_child(node) ((node) ? \
|
#define g_node_first_child(node) ((node) ? \
|
||||||
((GNode*) (node))->children : NULL)
|
((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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_NODE_H__ */
|
#endif /* __G_NODE_H__ */
|
||||||
|
@ -29,11 +29,6 @@
|
|||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
#include "galias.h"
|
#include "galias.h"
|
||||||
|
|
||||||
|
|
||||||
G_LOCK_DEFINE_STATIC (queue_memchunk);
|
|
||||||
static GMemChunk *queue_memchunk = NULL;
|
|
||||||
static GTrashStack *free_queue_nodes = NULL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_queue_new:
|
* g_queue_new:
|
||||||
*
|
*
|
||||||
@ -44,27 +39,7 @@ static GTrashStack *free_queue_nodes = NULL;
|
|||||||
GQueue*
|
GQueue*
|
||||||
g_queue_new (void)
|
g_queue_new (void)
|
||||||
{
|
{
|
||||||
GQueue *queue;
|
return g_slice_new0 (GQueue);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,15 +54,7 @@ g_queue_free (GQueue *queue)
|
|||||||
g_return_if_fail (queue != NULL);
|
g_return_if_fail (queue != NULL);
|
||||||
|
|
||||||
g_list_free (queue->head);
|
g_list_free (queue->head);
|
||||||
|
g_slice_free (GQueue, queue);
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
46
glib/grel.c
46
glib/grel.c
@ -45,7 +45,6 @@ struct _GRelation
|
|||||||
|
|
||||||
GHashTable *all_tuples;
|
GHashTable *all_tuples;
|
||||||
GHashTable **hashed_tuple_tables;
|
GHashTable **hashed_tuple_tables;
|
||||||
GMemChunk *tuple_chunk;
|
|
||||||
|
|
||||||
gint count;
|
gint count;
|
||||||
};
|
};
|
||||||
@ -109,16 +108,22 @@ g_relation_new (gint fields)
|
|||||||
GRelation* rel = g_new0 (GRelation, 1);
|
GRelation* rel = g_new0 (GRelation, 1);
|
||||||
|
|
||||||
rel->fields = fields;
|
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->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields));
|
||||||
rel->hashed_tuple_tables = g_new0 (GHashTable*, fields);
|
rel->hashed_tuple_tables = g_new0 (GHashTable*, fields);
|
||||||
|
|
||||||
return rel;
|
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
|
static void
|
||||||
g_relation_free_array (gpointer key, gpointer value, gpointer user_data)
|
g_relation_free_array (gpointer key, gpointer value, gpointer user_data)
|
||||||
{
|
{
|
||||||
@ -132,9 +137,6 @@ g_relation_destroy (GRelation *relation)
|
|||||||
|
|
||||||
if (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)
|
for (i = 0; i < relation->fields; i += 1)
|
||||||
{
|
{
|
||||||
if (relation->hashed_tuple_tables[i])
|
if (relation->hashed_tuple_tables[i])
|
||||||
@ -144,6 +146,9 @@ g_relation_destroy (GRelation *relation)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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->hashed_tuple_tables);
|
||||||
g_free (relation);
|
g_free (relation);
|
||||||
}
|
}
|
||||||
@ -166,16 +171,16 @@ void
|
|||||||
g_relation_insert (GRelation *relation,
|
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;
|
va_list args;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
va_start(args, relation);
|
va_start (args, relation);
|
||||||
|
|
||||||
for (i = 0; i < relation->fields; i += 1)
|
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);
|
g_hash_table_insert (relation->all_tuples, tuple, tuple);
|
||||||
|
|
||||||
@ -211,21 +216,21 @@ g_relation_delete_tuple (gpointer tuple_key,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
gpointer *tuple = (gpointer*) tuple_value;
|
gpointer *tuple = (gpointer*) tuple_value;
|
||||||
GRelation *rel = (GRelation *) user_data;
|
GRelation *relation = (GRelation *) user_data;
|
||||||
gint j;
|
gint j;
|
||||||
|
|
||||||
g_assert (tuple_key == tuple_value);
|
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;
|
gpointer one_key;
|
||||||
GHashTable *per_key_table;
|
GHashTable *per_key_table;
|
||||||
|
|
||||||
if (one_table == NULL)
|
if (one_table == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (j == rel->current_field)
|
if (j == relation->current_field)
|
||||||
/* can't delete from the table we're foreaching in */
|
/* can't delete from the table we're foreaching in */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -236,9 +241,10 @@ g_relation_delete_tuple (gpointer tuple_key,
|
|||||||
g_hash_table_remove (per_key_table, tuple);
|
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
|
gint
|
||||||
@ -341,7 +347,7 @@ g_relation_count (GRelation *relation,
|
|||||||
gboolean
|
gboolean
|
||||||
g_relation_exists (GRelation *relation, ...)
|
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;
|
va_list args;
|
||||||
gint i;
|
gint i;
|
||||||
gboolean result;
|
gboolean result;
|
||||||
@ -355,7 +361,7 @@ g_relation_exists (GRelation *relation, ...)
|
|||||||
|
|
||||||
result = g_hash_table_lookup (relation->all_tuples, tuple) != NULL;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
204
glib/gslist.c
204
glib/gslist.c
@ -34,199 +34,29 @@
|
|||||||
#include "galias.h"
|
#include "galias.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef DISABLE_MEM_POOLS
|
void g_slist_push_allocator (gpointer dummy) { /* present for binary compat only */ }
|
||||||
struct _GAllocator /* from gmem.c */
|
void g_slist_pop_allocator (void) { /* present for binary compat only */ }
|
||||||
{
|
|
||||||
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);
|
#define _g_slist_alloc0() g_slice_new0 (GSList)
|
||||||
static GAllocator *current_allocator = NULL;
|
#define _g_slist_free1(slist) g_slice_free (GSList, slist)
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
GSList*
|
GSList*
|
||||||
g_slist_alloc (void)
|
g_slist_alloc (void)
|
||||||
{
|
{
|
||||||
return _g_slist_alloc ();
|
return _g_slist_alloc0 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
g_slist_free (GSList *list)
|
g_slist_free (GSList *slist)
|
||||||
{
|
{
|
||||||
if (list)
|
g_slice_free_chain (sizeof (GSList), slist, G_STRUCT_OFFSET (GSList, next));
|
||||||
{
|
|
||||||
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
|
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*
|
GSList*
|
||||||
g_slist_append (GSList *list,
|
g_slist_append (GSList *list,
|
||||||
@ -235,7 +65,7 @@ g_slist_append (GSList *list,
|
|||||||
GSList *new_list;
|
GSList *new_list;
|
||||||
GSList *last;
|
GSList *last;
|
||||||
|
|
||||||
new_list = _g_slist_alloc ();
|
new_list = _g_slist_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
|
|
||||||
if (list)
|
if (list)
|
||||||
@ -256,7 +86,7 @@ g_slist_prepend (GSList *list,
|
|||||||
{
|
{
|
||||||
GSList *new_list;
|
GSList *new_list;
|
||||||
|
|
||||||
new_list = _g_slist_alloc ();
|
new_list = _g_slist_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
new_list->next = list;
|
new_list->next = list;
|
||||||
|
|
||||||
@ -277,7 +107,7 @@ g_slist_insert (GSList *list,
|
|||||||
else if (position == 0)
|
else if (position == 0)
|
||||||
return g_slist_prepend (list, data);
|
return g_slist_prepend (list, data);
|
||||||
|
|
||||||
new_list = _g_slist_alloc ();
|
new_list = _g_slist_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
|
|
||||||
if (!list)
|
if (!list)
|
||||||
@ -458,7 +288,7 @@ g_slist_delete_link (GSList *list,
|
|||||||
GSList *link)
|
GSList *link)
|
||||||
{
|
{
|
||||||
list = _g_slist_remove_link (list, link);
|
list = _g_slist_remove_link (list, link);
|
||||||
_g_slist_free_1 (link);
|
_g_slist_free1 (link);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@ -472,13 +302,13 @@ g_slist_copy (GSList *list)
|
|||||||
{
|
{
|
||||||
GSList *last;
|
GSList *last;
|
||||||
|
|
||||||
new_list = _g_slist_alloc ();
|
new_list = _g_slist_alloc0 ();
|
||||||
new_list->data = list->data;
|
new_list->data = list->data;
|
||||||
last = new_list;
|
last = new_list;
|
||||||
list = list->next;
|
list = list->next;
|
||||||
while (list)
|
while (list)
|
||||||
{
|
{
|
||||||
last->next = _g_slist_alloc ();
|
last->next = _g_slist_alloc0 ();
|
||||||
last = last->next;
|
last = last->next;
|
||||||
last->data = list->data;
|
last->data = list->data;
|
||||||
list = list->next;
|
list = list->next;
|
||||||
@ -647,7 +477,7 @@ g_slist_insert_sorted (GSList *list,
|
|||||||
|
|
||||||
if (!list)
|
if (!list)
|
||||||
{
|
{
|
||||||
new_list = _g_slist_alloc ();
|
new_list = _g_slist_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
return new_list;
|
return new_list;
|
||||||
}
|
}
|
||||||
@ -661,7 +491,7 @@ g_slist_insert_sorted (GSList *list,
|
|||||||
cmp = (*func) (data, tmp_list->data);
|
cmp = (*func) (data, tmp_list->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_list = _g_slist_alloc ();
|
new_list = _g_slist_alloc0 ();
|
||||||
new_list->data = data;
|
new_list->data = data;
|
||||||
|
|
||||||
if ((!tmp_list->next) && (cmp > 0))
|
if ((!tmp_list->next) && (cmp > 0))
|
||||||
|
@ -41,11 +41,10 @@ struct _GSList
|
|||||||
|
|
||||||
/* Singly linked lists
|
/* Singly linked lists
|
||||||
*/
|
*/
|
||||||
void g_slist_push_allocator (GAllocator *allocator);
|
|
||||||
void g_slist_pop_allocator (void);
|
|
||||||
GSList* g_slist_alloc (void);
|
GSList* g_slist_alloc (void);
|
||||||
void g_slist_free (GSList *list);
|
void g_slist_free (GSList *list);
|
||||||
void g_slist_free_1 (GSList *list);
|
void g_slist_free_1 (GSList *list);
|
||||||
|
#define g_slist_free1 g_slist_free_1
|
||||||
GSList* g_slist_append (GSList *list,
|
GSList* g_slist_append (GSList *list,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
GSList* g_slist_prepend (GSList *list,
|
GSList* g_slist_prepend (GSList *list,
|
||||||
@ -96,6 +95,10 @@ gpointer g_slist_nth_data (GSList *list,
|
|||||||
guint n);
|
guint n);
|
||||||
#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL)
|
#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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_SLIST_H__ */
|
#endif /* __G_SLIST_H__ */
|
||||||
|
@ -53,9 +53,6 @@ struct _GStringChunk
|
|||||||
gsize default_size;
|
gsize default_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_LOCK_DEFINE_STATIC (string_mem_chunk);
|
|
||||||
static GMemChunk *string_mem_chunk = NULL;
|
|
||||||
|
|
||||||
/* Hash Functions.
|
/* Hash Functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -268,16 +265,7 @@ g_string_maybe_expand (GString* string,
|
|||||||
GString*
|
GString*
|
||||||
g_string_sized_new (gsize dfl_size)
|
g_string_sized_new (gsize dfl_size)
|
||||||
{
|
{
|
||||||
GString *string;
|
GString *string = g_slice_new (GString);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
string->allocated_len = 0;
|
string->allocated_len = 0;
|
||||||
string->len = 0;
|
string->len = 0;
|
||||||
@ -344,9 +332,7 @@ g_string_free (GString *string,
|
|||||||
else
|
else
|
||||||
segment = string->str;
|
segment = string->str;
|
||||||
|
|
||||||
G_LOCK (string_mem_chunk);
|
g_slice_free (GString, string);
|
||||||
g_mem_chunk_free (string_mem_chunk, string);
|
|
||||||
G_UNLOCK (string_mem_chunk);
|
|
||||||
|
|
||||||
return segment;
|
return segment;
|
||||||
}
|
}
|
||||||
|
115
glib/gthread.c
115
glib/gthread.c
@ -76,6 +76,8 @@ struct _GRealThread
|
|||||||
{
|
{
|
||||||
GThread thread;
|
GThread thread;
|
||||||
gpointer private_data;
|
gpointer private_data;
|
||||||
|
gpointer mem_private;
|
||||||
|
GRealThread *next;
|
||||||
gpointer retval;
|
gpointer retval;
|
||||||
GSystemThread system_thread;
|
GSystemThread system_thread;
|
||||||
};
|
};
|
||||||
@ -126,7 +128,7 @@ GThreadFunctions g_thread_functions_for_glib_use = {
|
|||||||
static GMutex *g_once_mutex = NULL;
|
static GMutex *g_once_mutex = NULL;
|
||||||
static GCond *g_once_cond = NULL;
|
static GCond *g_once_cond = NULL;
|
||||||
static GPrivate *g_thread_specific_private = 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;
|
static GSList *g_thread_free_indeces = NULL;
|
||||||
|
|
||||||
G_LOCK_DEFINE_STATIC (g_thread);
|
G_LOCK_DEFINE_STATIC (g_thread);
|
||||||
@ -465,7 +467,7 @@ void
|
|||||||
g_static_private_free (GStaticPrivate *private_key)
|
g_static_private_free (GStaticPrivate *private_key)
|
||||||
{
|
{
|
||||||
guint index = private_key->index;
|
guint index = private_key->index;
|
||||||
GSList *list;
|
GRealThread *thread;
|
||||||
|
|
||||||
if (!index)
|
if (!index)
|
||||||
return;
|
return;
|
||||||
@ -473,12 +475,12 @@ g_static_private_free (GStaticPrivate *private_key)
|
|||||||
private_key->index = 0;
|
private_key->index = 0;
|
||||||
|
|
||||||
G_LOCK (g_thread);
|
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;
|
GArray *array = thread->private_data;
|
||||||
list = list->next;
|
thread = thread->next;
|
||||||
|
|
||||||
if (array && index <= array->len)
|
if (array && index <= array->len)
|
||||||
{
|
{
|
||||||
@ -529,8 +531,20 @@ g_thread_cleanup (gpointer data)
|
|||||||
it is, the structure is freed in g_thread_join */
|
it is, the structure is freed in g_thread_join */
|
||||||
if (!thread->thread.joinable)
|
if (!thread->thread.joinable)
|
||||||
{
|
{
|
||||||
|
GRealThread *t, *p;
|
||||||
|
|
||||||
G_LOCK (g_thread);
|
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);
|
G_UNLOCK (g_thread);
|
||||||
|
|
||||||
/* Just to make sure, this isn't used any more */
|
/* 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_LOW, NULL);
|
||||||
g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, 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.joinable = joinable;
|
||||||
result->thread.priority = priority;
|
result->thread.priority = priority;
|
||||||
@ -592,7 +606,8 @@ g_thread_create_full (GThreadFunc func,
|
|||||||
G_THREAD_UF (thread_create, (g_thread_create_proxy, result,
|
G_THREAD_UF (thread_create, (g_thread_create_proxy, result,
|
||||||
stack_size, joinable, bound, priority,
|
stack_size, joinable, bound, priority,
|
||||||
&result->system_thread, &local_error));
|
&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);
|
G_UNLOCK (g_thread);
|
||||||
|
|
||||||
if (local_error)
|
if (local_error)
|
||||||
@ -617,6 +632,7 @@ gpointer
|
|||||||
g_thread_join (GThread* thread)
|
g_thread_join (GThread* thread)
|
||||||
{
|
{
|
||||||
GRealThread* real = (GRealThread*) thread;
|
GRealThread* real = (GRealThread*) thread;
|
||||||
|
GRealThread *p, *t;
|
||||||
gpointer retval;
|
gpointer retval;
|
||||||
|
|
||||||
g_return_val_if_fail (thread, NULL);
|
g_return_val_if_fail (thread, NULL);
|
||||||
@ -629,7 +645,17 @@ g_thread_join (GThread* thread)
|
|||||||
retval = real->retval;
|
retval = real->retval;
|
||||||
|
|
||||||
G_LOCK (g_thread);
|
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);
|
G_UNLOCK (g_thread);
|
||||||
|
|
||||||
/* Just to make sure, this isn't used any more */
|
/* 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
|
/* If no thread data is available, provide and set one. This
|
||||||
can happen for the main thread and for threads, that are not
|
can happen for the main thread and for threads, that are not
|
||||||
created by GLib. */
|
created by GLib. */
|
||||||
thread = g_new (GRealThread, 1);
|
thread = g_new0 (GRealThread, 1);
|
||||||
thread->thread.joinable = FALSE; /* This is a save guess */
|
thread->thread.joinable = FALSE; /* This is a save guess */
|
||||||
thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is
|
thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is
|
||||||
just a guess */
|
just a guess */
|
||||||
@ -686,7 +712,8 @@ g_thread_self (void)
|
|||||||
g_private_set (g_thread_specific_private, thread);
|
g_private_set (g_thread_specific_private, thread);
|
||||||
|
|
||||||
G_LOCK (g_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);
|
G_UNLOCK (g_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -841,5 +868,69 @@ g_static_rw_lock_free (GStaticRWLock* lock)
|
|||||||
g_static_mutex_free (&lock->mutex);
|
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__
|
#define __G_THREAD_C__
|
||||||
#include "galiasdef.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_writer_unlock (GStaticRWLock* lock);
|
||||||
void g_static_rw_lock_free (GStaticRWLock* lock);
|
void g_static_rw_lock_free (GStaticRWLock* lock);
|
||||||
|
|
||||||
|
void g_thread_foreach (GFunc thread_func,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
G_ONCE_STATUS_NOTCALLED,
|
G_ONCE_STATUS_NOTCALLED,
|
||||||
@ -367,6 +370,11 @@ extern void glib_dummy_decl (void);
|
|||||||
# define G_TRYLOCK(name) (TRUE)
|
# define G_TRYLOCK(name) (TRUE)
|
||||||
#endif /* !G_THREADS_ENABLED */
|
#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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_THREAD_H__ */
|
#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);
|
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*
|
static GTreeNode*
|
||||||
g_tree_node_new (gpointer key,
|
g_tree_node_new (gpointer key,
|
||||||
gpointer value)
|
gpointer value)
|
||||||
{
|
{
|
||||||
GTreeNode *node;
|
GTreeNode *node = g_slice_new (GTreeNode);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
node->balance = 0;
|
node->balance = 0;
|
||||||
node->left = NULL;
|
node->left = NULL;
|
||||||
@ -162,10 +139,7 @@ g_tree_node_destroy (GTreeNode *node,
|
|||||||
node->value = NULL;
|
node->value = NULL;
|
||||||
#endif /* ENABLE_GC_FRIENDLY */
|
#endif /* ENABLE_GC_FRIENDLY */
|
||||||
|
|
||||||
G_LOCK (g_tree_global);
|
g_slice_free (GTreeNode, node);
|
||||||
node->right = node_free_list;
|
|
||||||
node_free_list = node;
|
|
||||||
G_UNLOCK (g_tree_global);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -742,10 +716,7 @@ g_tree_node_remove (GTree *tree,
|
|||||||
garbage->value = NULL;
|
garbage->value = NULL;
|
||||||
#endif /* ENABLE_GC_FRIENDLY */
|
#endif /* ENABLE_GC_FRIENDLY */
|
||||||
|
|
||||||
G_LOCK (g_tree_global);
|
g_slice_free (GTreeNode, garbage);
|
||||||
garbage->right = node_free_list;
|
|
||||||
node_free_list = garbage;
|
|
||||||
G_UNLOCK (g_tree_global);
|
|
||||||
|
|
||||||
*removed = TRUE;
|
*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>
|
2005-10-03 Matthias Clasen <mclasen@redhat.com>
|
||||||
|
|
||||||
* glib-mkenums.in: Really fix #314890.
|
* glib-mkenums.in: Really fix #314890.
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
/* pre allocation configurations
|
/* pre allocation configurations
|
||||||
*/
|
*/
|
||||||
#define MAX_STACK_VALUES (16)
|
#define MAX_STACK_VALUES (16)
|
||||||
#define HANDLER_PRE_ALLOC (48)
|
|
||||||
|
|
||||||
#define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org"
|
#define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org"
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
@ -52,41 +51,6 @@ static volatile gpointer g_trap_instance_signals = NULL;
|
|||||||
#endif /* G_ENABLE_DEBUG */
|
#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 --- */
|
/* --- typedefs --- */
|
||||||
typedef struct _SignalNode SignalNode;
|
typedef struct _SignalNode SignalNode;
|
||||||
typedef struct _SignalKey SignalKey;
|
typedef struct _SignalKey SignalKey;
|
||||||
@ -232,10 +196,7 @@ struct _HandlerMatch
|
|||||||
{
|
{
|
||||||
Handler *handler;
|
Handler *handler;
|
||||||
HandlerMatch *next;
|
HandlerMatch *next;
|
||||||
union {
|
guint signal_id;
|
||||||
guint signal_id;
|
|
||||||
gpointer dummy;
|
|
||||||
} d;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -434,10 +395,10 @@ handler_match_prepend (HandlerMatch *list,
|
|||||||
* instead, we use GList* nodes, since they are exactly the size
|
* instead, we use GList* nodes, since they are exactly the size
|
||||||
* we need and are already cached. g_signal_init() asserts this.
|
* 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->handler = handler;
|
||||||
node->next = list;
|
node->next = list;
|
||||||
node->d.signal_id = signal_id;
|
node->signal_id = signal_id;
|
||||||
handler_ref (handler);
|
handler_ref (handler);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@ -448,8 +409,8 @@ handler_match_free1_R (HandlerMatch *node,
|
|||||||
{
|
{
|
||||||
HandlerMatch *next = node->next;
|
HandlerMatch *next = node->next;
|
||||||
|
|
||||||
handler_unref_R (node->d.signal_id, instance, node->handler);
|
handler_unref_R (node->signal_id, instance, node->handler);
|
||||||
g_list_free_1 ((GList*) node);
|
g_slice_free (HandlerMatch, node);
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
@ -541,9 +502,7 @@ handlers_find (gpointer instance,
|
|||||||
static inline Handler*
|
static inline Handler*
|
||||||
handler_new (gboolean after)
|
handler_new (gboolean after)
|
||||||
{
|
{
|
||||||
Handler *handler = g_generic_node_alloc (&g_handler_ts,
|
Handler *handler = g_slice_new (Handler);
|
||||||
sizeof (Handler),
|
|
||||||
HANDLER_PRE_ALLOC);
|
|
||||||
#ifndef G_DISABLE_CHECKS
|
#ifndef G_DISABLE_CHECKS
|
||||||
if (g_handler_sequential_number < 1)
|
if (g_handler_sequential_number < 1)
|
||||||
g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
|
g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
|
||||||
@ -624,7 +583,7 @@ handler_unref_R (guint signal_id,
|
|||||||
SIGNAL_UNLOCK ();
|
SIGNAL_UNLOCK ();
|
||||||
g_closure_unref (handler->closure);
|
g_closure_unref (handler->closure);
|
||||||
SIGNAL_LOCK ();
|
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 private_size;
|
||||||
guint16 n_preallocs;
|
guint16 n_preallocs;
|
||||||
GInstanceInitFunc instance_init;
|
GInstanceInitFunc instance_init;
|
||||||
GMemChunk *mem_chunk;
|
|
||||||
};
|
};
|
||||||
union _TypeData
|
union _TypeData
|
||||||
{
|
{
|
||||||
@ -976,7 +975,6 @@ type_data_make_W (TypeNode *node,
|
|||||||
data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
|
data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
|
||||||
#endif /* !DISABLE_MEM_POOLS */
|
#endif /* !DISABLE_MEM_POOLS */
|
||||||
data->instance.instance_init = info->instance_init;
|
data->instance.instance_init = info->instance_init;
|
||||||
data->instance.mem_chunk = NULL;
|
|
||||||
}
|
}
|
||||||
else if (node->is_classed) /* only classed */
|
else if (node->is_classed) /* only classed */
|
||||||
{
|
{
|
||||||
@ -1526,8 +1524,7 @@ g_type_create_instance (GType type)
|
|||||||
TypeNode *node;
|
TypeNode *node;
|
||||||
GTypeInstance *instance;
|
GTypeInstance *instance;
|
||||||
GTypeClass *class;
|
GTypeClass *class;
|
||||||
guint i;
|
guint i, total_size;
|
||||||
gsize total_instance_size;
|
|
||||||
|
|
||||||
node = lookup_type_node_I (type);
|
node = lookup_type_node_I (type);
|
||||||
if (!node || !node->is_instantiatable)
|
if (!node || !node->is_instantiatable)
|
||||||
@ -1545,35 +1542,12 @@ g_type_create_instance (GType type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
class = g_type_class_ref (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)
|
if (node->data->instance.n_preallocs)
|
||||||
{
|
instance = g_slice_alloc0 (total_size);
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
instance = g_malloc0 (total_instance_size); /* fine without read lock */
|
instance = g_malloc0 (total_size);
|
||||||
|
|
||||||
if (node->data->instance.private_size)
|
if (node->data->instance.private_size)
|
||||||
instance_real_class_set (instance, class);
|
instance_real_class_set (instance, class);
|
||||||
@ -1624,14 +1598,10 @@ g_type_free_instance (GTypeInstance *instance)
|
|||||||
|
|
||||||
instance->g_class = NULL;
|
instance->g_class = NULL;
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
memset (instance, 0xaa, type_total_instance_size_I (node)); /* debugging hack */
|
memset (instance, 0xaa, type_total_instance_size_I (node));
|
||||||
#endif
|
#endif
|
||||||
if (node->data->instance.n_preallocs)
|
if (node->data->instance.n_preallocs)
|
||||||
{
|
g_slice_free1 (type_total_instance_size_I (node), instance);
|
||||||
G_WRITE_LOCK (&type_rw_lock);
|
|
||||||
g_chunk_free (instance, node->data->instance.mem_chunk);
|
|
||||||
G_WRITE_UNLOCK (&type_rw_lock);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
g_free (instance);
|
g_free (instance);
|
||||||
|
|
||||||
@ -2045,10 +2015,9 @@ type_data_last_unref_Wm (GType type,
|
|||||||
|
|
||||||
node->data->common.ref_count = 0;
|
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);
|
/* destroy node->data->instance.mem_chunk */
|
||||||
node->data->instance.mem_chunk = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tdata = node->data;
|
tdata = node->data;
|
||||||
|
Loading…
Reference in New Issue
Block a user