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:
Tim Janik 2005-11-01 18:10:31 +00:00 committed by Tim Janik
parent 3a042a8959
commit 0cba1b531d
28 changed files with 518 additions and 1063 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
} }

View File

@ -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"

View File

@ -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

View File

@ -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__

View File

@ -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

View File

@ -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];
}; };

View File

@ -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

View File

@ -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))

View File

@ -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__ */

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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__ */

View File

@ -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);
} }
/** /**

View File

@ -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;
} }

View File

@ -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))

View File

@ -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__ */

View File

@ -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;
} }

View File

@ -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"

View File

@ -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__ */

View File

@ -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;
} }

View File

@ -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.

View File

@ -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);
} }
} }

View File

@ -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;