+Tue Nov 1 16:24:20 2005 Tim Janik <timj@imendio.com>
+
+ * glib/gmem.[hc]: prepared deprecation of GMemChunk and GAllocator.
+ added g_slice_*() API to allocate and cache small bits of memory.
+ an actuall allocator implementation for g_slice_*() is still pending.
+
+ * glib/gthread.[hc]: changes from a patch by Matthias Clasen.
+ changed GRealThread list to use in-structure *next; fields instead
+ of GSList, in order for thread iteration to not depenend on g_slice_*()
+ indirectly.
+ _g_thread_mem_private_get():
+ _g_thread_mem_private_set(): added accessors for private memory,
+ needed because the ordinary GPrivate implementation relies on GArray
+ and GSList and therefore indirectly on working g_slice_*() allocations.
+
+ * glib/gthread.[hc]:
+ g_thread_foreach(): new public API function to loop over all existing threads.
+
+ * glib/gdataset.c:
+ * glib/gstring.c:
+ * glib/gcache.c:
+ * glib/garray.c:
+ * glib/gqueue.c:
+ * glib/gslist.c:
+ * glib/glist.c:
+ * glib/ghash.c:
+ * glib/gtree.c:
+ * glib/ghook.c:
+ * glib/gmain.c:
+ * glib/gnode.c:
+ removed GAllocator and free list usages and accompanying locks.
+ use g_slice_*() API to allocate and cache small bits of memory.
+
+ * glib/ghook.h: removed GMemChunk field from public API.
+
+ * glib/gslist.h:
+ * glib/glist.h: deprecate allocator API, provide _free1() for consistency.
+
+ * glib/gnode.h: deprecate allocator API.
+
+ * glib/gmain.c: reordered GPollRec fields so g_slice_free_chain() can
+ be used for poll rec lists.
+
+ * glib/grel.c: removed mem chunk usage, and allocated tuples via g_slice_*().
+ g_relation_destroy(): free all tuples from the all_tuples hash table,
+ this effectively maintains the life time track keeping of tuples.
+ g_relation_delete_tuple(): free tuples which are removed from the
+ all_tuples hash table. this fixes a temporary leak that was present
+ in the memchunk code until the destruction of the relation.
+
2005-10-29 Matthias Clasen <mclasen@redhat.com>
* tests/convert-test.c: Add some tests for conversions between
+Tue Nov 1 16:24:20 2005 Tim Janik <timj@imendio.com>
+
+ * glib/gmem.[hc]: prepared deprecation of GMemChunk and GAllocator.
+ added g_slice_*() API to allocate and cache small bits of memory.
+ an actuall allocator implementation for g_slice_*() is still pending.
+
+ * glib/gthread.[hc]: changes from a patch by Matthias Clasen.
+ changed GRealThread list to use in-structure *next; fields instead
+ of GSList, in order for thread iteration to not depenend on g_slice_*()
+ indirectly.
+ _g_thread_mem_private_get():
+ _g_thread_mem_private_set(): added accessors for private memory,
+ needed because the ordinary GPrivate implementation relies on GArray
+ and GSList and therefore indirectly on working g_slice_*() allocations.
+
+ * glib/gthread.[hc]:
+ g_thread_foreach(): new public API function to loop over all existing threads.
+
+ * glib/gdataset.c:
+ * glib/gstring.c:
+ * glib/gcache.c:
+ * glib/garray.c:
+ * glib/gqueue.c:
+ * glib/gslist.c:
+ * glib/glist.c:
+ * glib/ghash.c:
+ * glib/gtree.c:
+ * glib/ghook.c:
+ * glib/gmain.c:
+ * glib/gnode.c:
+ removed GAllocator and free list usages and accompanying locks.
+ use g_slice_*() API to allocate and cache small bits of memory.
+
+ * glib/ghook.h: removed GMemChunk field from public API.
+
+ * glib/gslist.h:
+ * glib/glist.h: deprecate allocator API, provide _free1() for consistency.
+
+ * glib/gnode.h: deprecate allocator API.
+
+ * glib/gmain.c: reordered GPollRec fields so g_slice_free_chain() can
+ be used for poll rec lists.
+
+ * glib/grel.c: removed mem chunk usage, and allocated tuples via g_slice_*().
+ g_relation_destroy(): free all tuples from the all_tuples hash table,
+ this effectively maintains the life time track keeping of tuples.
+ g_relation_delete_tuple(): free tuples which are removed from the
+ all_tuples hash table. this fixes a temporary leak that was present
+ in the memchunk code until the destruction of the relation.
+
2005-10-29 Matthias Clasen <mclasen@redhat.com>
* tests/convert-test.c: Add some tests for conversions between
+Tue Nov 1 16:24:20 2005 Tim Janik <timj@imendio.com>
+
+ * glib/gmem.[hc]: prepared deprecation of GMemChunk and GAllocator.
+ added g_slice_*() API to allocate and cache small bits of memory.
+ an actuall allocator implementation for g_slice_*() is still pending.
+
+ * glib/gthread.[hc]: changes from a patch by Matthias Clasen.
+ changed GRealThread list to use in-structure *next; fields instead
+ of GSList, in order for thread iteration to not depenend on g_slice_*()
+ indirectly.
+ _g_thread_mem_private_get():
+ _g_thread_mem_private_set(): added accessors for private memory,
+ needed because the ordinary GPrivate implementation relies on GArray
+ and GSList and therefore indirectly on working g_slice_*() allocations.
+
+ * glib/gthread.[hc]:
+ g_thread_foreach(): new public API function to loop over all existing threads.
+
+ * glib/gdataset.c:
+ * glib/gstring.c:
+ * glib/gcache.c:
+ * glib/garray.c:
+ * glib/gqueue.c:
+ * glib/gslist.c:
+ * glib/glist.c:
+ * glib/ghash.c:
+ * glib/gtree.c:
+ * glib/ghook.c:
+ * glib/gmain.c:
+ * glib/gnode.c:
+ removed GAllocator and free list usages and accompanying locks.
+ use g_slice_*() API to allocate and cache small bits of memory.
+
+ * glib/ghook.h: removed GMemChunk field from public API.
+
+ * glib/gslist.h:
+ * glib/glist.h: deprecate allocator API, provide _free1() for consistency.
+
+ * glib/gnode.h: deprecate allocator API.
+
+ * glib/gmain.c: reordered GPollRec fields so g_slice_free_chain() can
+ be used for poll rec lists.
+
+ * glib/grel.c: removed mem chunk usage, and allocated tuples via g_slice_*().
+ g_relation_destroy(): free all tuples from the all_tuples hash table,
+ this effectively maintains the life time track keeping of tuples.
+ g_relation_delete_tuple(): free tuples which are removed from the
+ all_tuples hash table. this fixes a temporary leak that was present
+ in the memchunk code until the destruction of the relation.
+
2005-10-29 Matthias Clasen <mclasen@redhat.com>
* tests/convert-test.c: Add some tests for conversions between
static void g_array_maybe_expand (GRealArray *array,
gint len);
-static GMemChunk *array_mem_chunk = NULL;
-G_LOCK_DEFINE_STATIC (array_mem_chunk);
-
GArray*
g_array_new (gboolean zero_terminated,
gboolean clear,
guint elt_size,
guint reserved_size)
{
- GRealArray *array;
-
- G_LOCK (array_mem_chunk);
- if (!array_mem_chunk)
- array_mem_chunk = g_mem_chunk_new ("array mem chunk",
- sizeof (GRealArray),
- 1024, G_ALLOC_AND_FREE);
-
- array = g_chunk_new (GRealArray, array_mem_chunk);
- G_UNLOCK (array_mem_chunk);
+ GRealArray *array = g_slice_new (GRealArray);
array->data = NULL;
array->len = 0;
else
segment = array->data;
- G_LOCK (array_mem_chunk);
- g_mem_chunk_free (array_mem_chunk, array);
- G_UNLOCK (array_mem_chunk);
+ g_slice_free1 (sizeof (GRealArray), array);
return segment;
}
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
gint len);
-static GMemChunk *ptr_array_mem_chunk = NULL;
-G_LOCK_DEFINE_STATIC (ptr_array_mem_chunk);
-
-
GPtrArray*
g_ptr_array_new (void)
{
GPtrArray*
g_ptr_array_sized_new (guint reserved_size)
{
- GRealPtrArray *array;
-
- G_LOCK (ptr_array_mem_chunk);
- if (!ptr_array_mem_chunk)
- ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk",
- sizeof (GRealPtrArray),
- 1024, G_ALLOC_AND_FREE);
-
- array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk);
- G_UNLOCK (ptr_array_mem_chunk);
+ GRealPtrArray *array = g_slice_new (GRealPtrArray);
array->pdata = NULL;
array->len = 0;
else
segment = array->pdata;
- G_LOCK (ptr_array_mem_chunk);
- g_mem_chunk_free (ptr_array_mem_chunk, array);
- G_UNLOCK (ptr_array_mem_chunk);
+ g_slice_free1 (sizeof (GRealPtrArray), array);
return segment;
}
GHashTable *value_table;
};
+static inline GCacheNode*
+g_cache_node_new (gpointer value)
+{
+ GCacheNode *node = g_slice_new (GCacheNode);
+ node->value = value;
+ node->ref_count = 1;
+ return node;
+}
-static GCacheNode* g_cache_node_new (gpointer value);
-static void g_cache_node_destroy (GCacheNode *node);
-
-
-static GMemChunk *node_mem_chunk = NULL;
-G_LOCK_DEFINE_STATIC (node_mem_chunk);
+static inline void
+g_cache_node_destroy (GCacheNode *node)
+{
+ g_slice_free (GCacheNode, node);
+}
GCache*
g_cache_new (GCacheNewFunc value_new_func,
g_return_val_if_fail (hash_value_func != NULL, NULL);
g_return_val_if_fail (key_equal_func != NULL, NULL);
- cache = g_new (GCache, 1);
+ cache = g_slice_new (GCache);
cache->value_new_func = value_new_func;
cache->value_destroy_func = value_destroy_func;
cache->key_dup_func = key_dup_func;
g_hash_table_destroy (cache->key_table);
g_hash_table_destroy (cache->value_table);
- g_free (cache);
+ g_slice_free (GCache, cache);
}
gpointer
g_hash_table_foreach (cache->key_table, func, user_data);
}
-
-static GCacheNode*
-g_cache_node_new (gpointer value)
-{
- GCacheNode *node;
-
- G_LOCK (node_mem_chunk);
- if (!node_mem_chunk)
- node_mem_chunk = g_mem_chunk_new ("cache node mem chunk", sizeof (GCacheNode),
- 1024, G_ALLOC_AND_FREE);
-
- node = g_chunk_new (GCacheNode, node_mem_chunk);
- G_UNLOCK (node_mem_chunk);
-
- node->value = value;
- node->ref_count = 1;
-
- return node;
-}
-
-static void
-g_cache_node_destroy (GCacheNode *node)
-{
- G_LOCK (node_mem_chunk);
- g_mem_chunk_free (node_mem_chunk, node);
- G_UNLOCK (node_mem_chunk);
-}
-
#define __G_CACHE_C__
#include "galiasdef.c"
/* --- defines --- */
#define G_QUARK_BLOCK_SIZE (512)
-#define G_DATA_MEM_CHUNK_PREALLOC (128)
#define G_DATA_CACHE_MAX (512)
-#define G_DATASET_MEM_CHUNK_PREALLOC (32)
/* datalist pointer modifications have to be done with the g_dataset_global mutex held */
#define G_DATALIST_GET_POINTER(datalist) \
static GHashTable *g_dataset_location_ht = NULL;
static GDataset *g_dataset_cached = NULL; /* should this be
threadspecific? */
-static GMemChunk *g_dataset_mem_chunk = NULL;
-static GMemChunk *g_data_mem_chunk = NULL;
static GData *g_data_cache = NULL;
static guint g_data_cache_length = 0;
g_data_cache_length++;
}
else
- g_mem_chunk_free (g_data_mem_chunk, prev);
+ g_slice_free (GData, prev);
}
}
if (dataset == g_dataset_cached)
g_dataset_cached = NULL;
g_hash_table_remove (g_dataset_location_ht, dataset_location);
- g_mem_chunk_free (g_dataset_mem_chunk, dataset);
+ g_slice_free (GDataset, dataset);
break;
}
g_data_cache_length++;
}
else
- g_mem_chunk_free (g_data_mem_chunk, list);
+ g_slice_free (GData, list);
return ret_data;
}
g_data_cache_length--;
}
else
- list = g_chunk_new (GData, g_data_mem_chunk);
+ list = g_slice_new (GData);
list->next = G_DATALIST_GET_POINTER (datalist);
list->id = key_id;
list->data = data;
dataset = g_dataset_lookup (dataset_location);
if (!dataset)
{
- dataset = g_chunk_new (GDataset, g_dataset_mem_chunk);
+ dataset = g_slice_new (GDataset);
dataset->location = dataset_location;
g_datalist_init (&dataset->datalist);
g_hash_table_insert (g_dataset_location_ht,
g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
g_dataset_cached = NULL;
- g_dataset_mem_chunk =
- g_mem_chunk_new ("GDataset MemChunk",
- sizeof (GDataset),
- sizeof (GDataset) * G_DATASET_MEM_CHUNK_PREALLOC,
- G_ALLOC_AND_FREE);
- g_data_mem_chunk =
- g_mem_chunk_new ("GData MemChunk",
- sizeof (GData),
- sizeof (GData) * G_DATA_MEM_CHUNK_PREALLOC,
- G_ALLOC_AND_FREE);
}
GQuark
gboolean notify);
-#ifndef DISABLE_MEM_POOLS
-G_LOCK_DEFINE_STATIC (g_hash_global);
-
-static GMemChunk *node_mem_chunk = NULL;
-static GHashNode *node_free_list = NULL;
-#endif
-
/**
* g_hash_table_new:
* @hash_func: a function to create a hash value from a key.
GHashTable *hash_table;
guint i;
- hash_table = g_new (GHashTable, 1);
+ hash_table = g_slice_new (GHashTable);
hash_table->size = HASH_TABLE_MIN_SIZE;
hash_table->nnodes = 0;
hash_table->hash_func = hash_func ? hash_func : g_direct_hash;
hash_table->value_destroy_func);
g_free (hash_table->nodes);
- g_free (hash_table);
+ g_slice_free (GHashTable, hash_table);
}
static inline GHashNode**
g_hash_node_new (gpointer key,
gpointer value)
{
- GHashNode *hash_node;
-
-#ifdef DISABLE_MEM_POOLS
- hash_node = g_new (GHashNode, 1);
-#else
- G_LOCK (g_hash_global);
- if (node_free_list)
- {
- hash_node = node_free_list;
- node_free_list = node_free_list->next;
- }
- else
- {
- if (!node_mem_chunk)
- node_mem_chunk = g_mem_chunk_new ("hash node mem chunk",
- sizeof (GHashNode),
- 1024, G_ALLOC_ONLY);
-
- hash_node = g_chunk_new (GHashNode, node_mem_chunk);
- }
- G_UNLOCK (g_hash_global);
-#endif
+ GHashNode *hash_node = g_slice_new (GHashNode);
hash_node->key = key;
hash_node->value = value;
hash_node->value = NULL;
#endif /* ENABLE_GC_FRIENDLY */
-#ifdef DISABLE_MEM_POOLS
- g_free (hash_node);
-#else
- G_LOCK (g_hash_global);
- hash_node->next = node_free_list;
- node_free_list = hash_node;
- G_UNLOCK (g_hash_global);
-#endif
+ g_slice_free (GHashNode, hash_node);
}
static void
GFreeFunc key_destroy_func,
GFreeFunc value_destroy_func)
{
-#ifdef DISABLE_MEM_POOLS
while (hash_node)
{
GHashNode *next = hash_node->next;
-
if (key_destroy_func)
key_destroy_func (hash_node->key);
if (value_destroy_func)
value_destroy_func (hash_node->value);
-
- g_free (hash_node);
+ g_slice_free (GHashNode, hash_node);
hash_node = next;
- }
-#else
- if (hash_node)
- {
- GHashNode *node = hash_node;
-
- while (node->next)
- {
- if (key_destroy_func)
- key_destroy_func (node->key);
- if (value_destroy_func)
- value_destroy_func (node->value);
-
-#ifdef ENABLE_GC_FRIENDLY
- node->key = NULL;
- node->value = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
-
- node = node->next;
- }
-
- if (key_destroy_func)
- key_destroy_func (node->key);
- if (value_destroy_func)
- value_destroy_func (node->value);
-
-#ifdef ENABLE_GC_FRIENDLY
- node->key = NULL;
- node->value = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
-
- G_LOCK (g_hash_global);
- node->next = node_free_list;
- node_free_list = hash_node;
- G_UNLOCK (g_hash_global);
}
-#endif
}
#define __G_HASH_C__
#include "galias.h"
-/* --- defines --- */
-#define G_HOOKS_PREALLOC (16)
-
-
/* --- functions --- */
static void
default_finalize_hook (GHookList *hook_list,
{
g_return_if_fail (hook_list != NULL);
g_return_if_fail (hook_size >= sizeof (GHook));
- g_return_if_fail (hook_size < 65536);
hook_list->seq_id = 1;
hook_list->hook_size = hook_size;
hook_list->is_setup = TRUE;
hook_list->hooks = NULL;
- hook_list->hook_memchunk = g_mem_chunk_new ("GHook Memchunk",
- hook_size,
- hook_size * G_HOOKS_PREALLOC,
- G_ALLOC_AND_FREE);
+ hook_list->dummy3 = NULL;
hook_list->finalize_hook = default_finalize_hook;
hook_list->dummy[0] = NULL;
hook_list->dummy[1] = NULL;
hook = hook_list->hooks;
if (!hook)
{
- g_mem_chunk_destroy (hook_list->hook_memchunk);
- hook_list->hook_memchunk = NULL;
+ /* destroy hook_list->hook_memchunk */
}
else
do
hook = tmp;
}
while (hook);
- if (hook_list->hook_memchunk)
- g_warning (G_STRLOC ": failed to clear hooklist, unconsolidated references on hooks left");
}
}
g_return_val_if_fail (hook_list != NULL, NULL);
g_return_val_if_fail (hook_list->is_setup, NULL);
- hook = g_chunk_new0 (GHook, hook_list->hook_memchunk);
+ hook = g_slice_alloc0 (hook_list->hook_size);
hook->data = NULL;
hook->next = NULL;
hook->prev = NULL;
g_return_if_fail (!G_HOOK_IN_CALL (hook));
hook_list->finalize_hook (hook_list, hook);
- g_chunk_free (hook, hook_list->hook_memchunk);
+ g_slice_free1 (hook_list->hook_size, hook);
}
void
GHook *hook)
{
g_return_if_fail (hook_list != NULL);
- g_return_if_fail (hook_list->hook_memchunk != NULL);
g_return_if_fail (hook != NULL);
g_return_if_fail (hook->ref_count > 0);
if (!hook_list->hooks)
{
- g_mem_chunk_destroy (hook_list->hook_memchunk);
- hook_list->hook_memchunk = NULL;
+ /* destroy hook_list->hook_memchunk */
}
}
else
guint hook_size : 16;
guint is_setup : 1;
GHook *hooks;
- GMemChunk *hook_memchunk;
+ gpointer dummy3;
GHookFinalizeFunc finalize_hook;
gpointer dummy[2];
};
#if IN_HEADER(__G_MEM_H__)
#if IN_FILE(__G_MEM_C__)
g_free
+g_malloc G_GNUC_MALLOC
+g_malloc0 G_GNUC_MALLOC
+g_mem_is_system_malloc
+g_mem_profile
+g_mem_set_vtable
+g_realloc
+g_try_malloc G_GNUC_MALLOC
+g_try_malloc0 G_GNUC_MALLOC
+g_try_realloc
+#ifndef G_DISABLE_DEPRECATED
+g_allocator_free
+g_allocator_new
g_mem_chunk_alloc
g_mem_chunk_alloc0
g_mem_chunk_clean
g_mem_chunk_new
g_mem_chunk_print
g_mem_chunk_reset
-g_malloc G_GNUC_MALLOC
-g_malloc0 G_GNUC_MALLOC
-g_mem_is_system_malloc
-g_mem_profile
-g_mem_set_vtable
-g_realloc
-g_allocator_free
-g_allocator_new
g_blow_chunks
-g_try_malloc G_GNUC_MALLOC
-g_try_malloc0 G_GNUC_MALLOC
-g_try_realloc
+#endif
#endif
#endif
g_static_rw_lock_writer_lock
g_static_rw_lock_writer_trylock
g_static_rw_lock_writer_unlock
+g_thread_foreach
#endif
#endif
#include "galias.h"
-#ifndef DISABLE_MEM_POOLS
-struct _GAllocator /* from gmem.c */
-{
- gchar *name;
- guint16 n_preallocs;
- guint is_unused : 1;
- guint type : 4;
- GAllocator *last;
- GMemChunk *mem_chunk;
- GList *free_lists; /* implementation specific */
-};
-
-static GAllocator *current_allocator = NULL;
-G_LOCK_DEFINE_STATIC (current_allocator);
-
-/* HOLDS: current_allocator_lock */
-static void
-g_list_validate_allocator (GAllocator *allocator)
-{
- g_return_if_fail (allocator != NULL);
- g_return_if_fail (allocator->is_unused == TRUE);
-
- if (allocator->type != G_ALLOCATOR_LIST)
- {
- allocator->type = G_ALLOCATOR_LIST;
- if (allocator->mem_chunk)
- {
- g_mem_chunk_destroy (allocator->mem_chunk);
- allocator->mem_chunk = NULL;
- }
- }
-
- if (!allocator->mem_chunk)
- {
- allocator->mem_chunk = g_mem_chunk_new (allocator->name,
- sizeof (GList),
- sizeof (GList) * allocator->n_preallocs,
- G_ALLOC_ONLY);
- allocator->free_lists = NULL;
- }
-
- allocator->is_unused = FALSE;
-}
-
-void
-g_list_push_allocator(GAllocator *allocator)
-{
- G_LOCK (current_allocator);
- g_list_validate_allocator (allocator);
- allocator->last = current_allocator;
- current_allocator = allocator;
- G_UNLOCK (current_allocator);
-}
-
-void
-g_list_pop_allocator (void)
-{
- G_LOCK (current_allocator);
- if (current_allocator)
- {
- GAllocator *allocator;
-
- allocator = current_allocator;
- current_allocator = allocator->last;
- allocator->last = NULL;
- allocator->is_unused = TRUE;
- }
- G_UNLOCK (current_allocator);
-}
-
-static inline GList*
-_g_list_alloc (void)
-{
- GList *list;
-
- G_LOCK (current_allocator);
- if (!current_allocator)
- {
- GAllocator *allocator = g_allocator_new ("GLib default GList allocator",
- 128);
- g_list_validate_allocator (allocator);
- allocator->last = NULL;
- current_allocator = allocator;
- }
- if (!current_allocator->free_lists)
- {
- list = g_chunk_new (GList, current_allocator->mem_chunk);
- list->data = NULL;
- }
- else
- {
- if (current_allocator->free_lists->data)
- {
- list = current_allocator->free_lists->data;
- current_allocator->free_lists->data = list->next;
- list->data = NULL;
- }
- else
- {
- list = current_allocator->free_lists;
- current_allocator->free_lists = list->next;
- }
- }
- G_UNLOCK (current_allocator);
- list->next = NULL;
- list->prev = NULL;
-
- return list;
-}
-
-GList*
-g_list_alloc (void)
-{
- return _g_list_alloc ();
-}
-
-void
-g_list_free (GList *list)
-{
- if (list)
- {
- GList *last_node = list;
-
-#ifdef ENABLE_GC_FRIENDLY
- while (last_node->next)
- {
- last_node->data = NULL;
- last_node->prev = NULL;
- last_node = last_node->next;
- }
- last_node->data = NULL;
- last_node->prev = NULL;
-#else /* !ENABLE_GC_FRIENDLY */
- list->data = list->next;
-#endif /* ENABLE_GC_FRIENDLY */
-
- G_LOCK (current_allocator);
- last_node->next = current_allocator->free_lists;
- current_allocator->free_lists = list;
- G_UNLOCK (current_allocator);
- }
-}
-
-static inline void
-_g_list_free_1 (GList *list)
-{
- if (list)
- {
- list->data = NULL;
+void g_list_push_allocator (gpointer dummy) { /* present for binary compat only */ }
+void g_list_pop_allocator (void) { /* present for binary compat only */ }
-#ifdef ENABLE_GC_FRIENDLY
- list->prev = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
+#define _g_list_alloc0() g_slice_new0 (GList)
+#define _g_list_free1(list) g_slice_free (GList, list)
- G_LOCK (current_allocator);
- list->next = current_allocator->free_lists;
- current_allocator->free_lists = list;
- G_UNLOCK (current_allocator);
- }
-}
-
-void
-g_list_free_1 (GList *list)
-{
- _g_list_free_1 (list);
-}
-
-#else /* DISABLE_MEM_POOLS */
-
-#define _g_list_alloc g_list_alloc
GList*
g_list_alloc (void)
{
- GList *list;
-
- list = g_new0 (GList, 1);
-
- return list;
+ return _g_list_alloc0 ();
}
void
g_list_free (GList *list)
{
- GList *last;
-
- while (list)
- {
- last = list;
- list = list->next;
- g_free (last);
- }
+ g_slice_free_chain (sizeof (GList), list, G_STRUCT_OFFSET (GList, next));
}
-#define _g_list_free_1 g_list_free_1
void
g_list_free_1 (GList *list)
{
- g_free (list);
+ _g_list_free1 (list);
}
-#endif
-
GList*
g_list_append (GList *list,
gpointer data)
GList *new_list;
GList *last;
- new_list = _g_list_alloc ();
+ new_list = _g_list_alloc0 ();
new_list->data = data;
if (list)
{
GList *new_list;
- new_list = _g_list_alloc ();
+ new_list = _g_list_alloc0 ();
new_list->data = data;
if (list)
if (!tmp_list)
return g_list_append (list, data);
- new_list = _g_list_alloc ();
+ new_list = _g_list_alloc0 ();
new_list->data = data;
if (tmp_list->prev)
if (list == tmp)
list = list->next;
- _g_list_free_1 (tmp);
+ _g_list_free1 (tmp);
break;
}
if (next)
next->prev = tmp->prev;
- _g_list_free_1 (tmp);
+ _g_list_free1 (tmp);
tmp = next;
}
}
GList *link)
{
list = _g_list_remove_link (list, link);
- _g_list_free_1 (link);
+ _g_list_free1 (link);
return list;
}
{
GList *last;
- new_list = _g_list_alloc ();
+ new_list = _g_list_alloc0 ();
new_list->data = list->data;
last = new_list;
list = list->next;
while (list)
{
- last->next = _g_list_alloc ();
+ last->next = _g_list_alloc0 ();
last->next->prev = last;
last = last->next;
last->data = list->data;
if (!list)
{
- new_list = _g_list_alloc ();
+ new_list = _g_list_alloc0 ();
new_list->data = data;
return new_list;
}
cmp = (*func) (data, tmp_list->data);
}
- new_list = _g_list_alloc ();
+ new_list = _g_list_alloc0 ();
new_list->data = data;
if ((!tmp_list->next) && (cmp > 0))
/* Doubly linked lists
*/
-void g_list_push_allocator (GAllocator *allocator);
-void g_list_pop_allocator (void);
GList* g_list_alloc (void);
void g_list_free (GList *list);
void g_list_free_1 (GList *list);
+#define g_list_free1 g_list_free_1
GList* g_list_append (GList *list,
gpointer data);
GList* g_list_prepend (GList *list,
#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL)
#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)
+#ifndef G_DISABLE_DEPRECATED
+void g_list_push_allocator (gpointer allocator);
+void g_list_pop_allocator (void);
+#endif
G_END_DECLS
#endif /* __G_LIST_H__ */
gint in_check_or_prepare;
GPollRec *poll_records;
- GPollRec *poll_free_list;
- GMemChunk *poll_chunk;
guint n_poll_records;
GPollFD *cached_poll_array;
guint cached_poll_array_size;
struct _GPollRec
{
- gint priority;
GPollFD *fd;
- GPollRec *next;
+ GPollRec *next; /* chaining via second pointer member allows use of g_slice_free_chain() */
+ gint priority;
};
#ifdef G_THREADS_ENABLED
return context;
}
-/* If DISABLE_MEM_POOLS is defined, then freeing the
- * mem chunk won't free the records, so we have to
- * do it manually. The conditionalization here is
- * an optimization; g_mem_chunk_free() is a no-op
- * when DISABLE_MEM_POOLS is set.
- */
-#ifdef DISABLE_MEM_POOLS
-static void
+static inline void
poll_rec_list_free (GMainContext *context,
GPollRec *list)
{
- while (list)
- {
- GPollRec *tmp_rec = list;
- list = list->next;
- g_chunk_free (tmp_rec, context->poll_chunk);
- }
+ g_slice_free_chain (sizeof (GPollRec), list, G_STRUCT_OFFSET (GPollRec, next));
}
-#endif /* DISABLE_MEM_POOLS */
/**
* g_main_context_unref:
g_ptr_array_free (context->pending_dispatches, TRUE);
g_free (context->cached_poll_array);
-#ifdef DISABLE_MEM_POLLS
poll_rec_list_free (context, context->poll_records);
- poll_rec_list_free (context, context->poll_free_list);
-#endif /* DISABLE_MEM_POOLS */
- if (context->poll_chunk)
- g_mem_chunk_destroy (context->poll_chunk);
-
#ifdef G_THREADS_ENABLED
if (g_thread_supported())
{
gint priority,
GPollFD *fd)
{
- GPollRec *lastrec, *pollrec, *newrec;
-
- if (!context->poll_chunk)
- context->poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY);
-
- if (context->poll_free_list)
- {
- newrec = context->poll_free_list;
- context->poll_free_list = newrec->next;
- }
- else
- newrec = g_chunk_new (GPollRec, context->poll_chunk);
+ GPollRec *lastrec, *pollrec;
+ GPollRec *newrec = g_slice_new (GPollRec);
/* This file descriptor may be checked before we ever poll */
fd->revents = 0;
else
context->poll_records = pollrec->next;
-#ifdef ENABLE_GC_FRIENDLY
- pollrec->fd = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
-
- pollrec->next = context->poll_free_list;
- context->poll_free_list = pollrec;
+ g_slice_free (GPollRec, pollrec);
context->n_poll_records--;
break;
#endif /* !G_DISABLE_CHECKS */
+/* --- memory slices --- */
+typedef struct {
+ gpointer dummy, next;
+} MemSlice;
+
+gpointer
+g_slice_alloc (guint block_size)
+{
+ return g_malloc (block_size);
+}
+
+gpointer
+g_slice_alloc0 (guint block_size)
+{
+ return g_malloc0 (block_size);
+}
+
+void
+g_slice_free1 (guint block_size,
+ gpointer mem_block)
+{
+ if (mem_block)
+ g_free (mem_block);
+}
+
+void
+g_slice_free_chain (guint block_size,
+ gpointer mem_chain,
+ guint next_offset)
+{
+ MemSlice *slice = mem_chain;
+ g_return_if_fail (next_offset == G_STRUCT_OFFSET (MemSlice, next));
+ g_return_if_fail (block_size >= sizeof (MemSlice));
+ while (slice)
+ {
+ MemSlice *current = slice;
+ slice = slice->next;
+ g_slice_free1 (block_size, current);
+ }
+}
/* --- MemChunks --- */
+#ifndef G_ALLOC_AND_FREE
+typedef struct _GAllocator GAllocator;
+typedef struct _GMemChunk GMemChunk;
+#define G_ALLOC_ONLY 1
+#define G_ALLOC_AND_FREE 2
+#endif
+
typedef struct _GFreeAtom GFreeAtom;
typedef struct _GMemArea GMemArea;
#endif /* DISABLE_MEM_POOLS */
-/* generic allocators
- */
-struct _GAllocator /* from gmem.c */
-{
- gchar *name;
- guint16 n_preallocs;
- guint is_unused : 1;
- guint type : 4;
- GAllocator *last;
- GMemChunk *mem_chunk;
- gpointer dummy; /* implementation specific */
-};
-
GAllocator*
g_allocator_new (const gchar *name,
guint n_preallocs)
{
- GAllocator *allocator;
-
- g_return_val_if_fail (name != NULL, NULL);
-
- allocator = g_new0 (GAllocator, 1);
- allocator->name = g_strdup (name);
- allocator->n_preallocs = CLAMP (n_preallocs, 1, 65535);
- allocator->is_unused = TRUE;
- allocator->type = 0;
- allocator->last = NULL;
- allocator->mem_chunk = NULL;
- allocator->dummy = NULL;
-
- return allocator;
+ static const struct _GAllocator {
+ gchar *name;
+ guint16 n_preallocs;
+ guint is_unused : 1;
+ guint type : 4;
+ GAllocator *last;
+ GMemChunk *mem_chunk;
+ gpointer free_list;
+ } dummy = {
+ "GAllocator is deprecated", 0, TRUE, 0, NULL, NULL, NULL,
+ };
+ /* some (broken) GAllocator uses depend on non-NULL allocators */
+ return (GAllocator*) &dummy;
}
void
g_allocator_free (GAllocator *allocator)
{
- g_return_if_fail (allocator != NULL);
- g_return_if_fail (allocator->is_unused == TRUE);
-
- g_free (allocator->name);
- if (allocator->mem_chunk)
- g_mem_chunk_destroy (allocator->mem_chunk);
-
- g_free (allocator);
}
void
G_BEGIN_DECLS
-typedef struct _GAllocator GAllocator;
-typedef struct _GMemChunk GMemChunk;
typedef struct _GMemVTable GMemVTable;
GLIB_VAR GMemVTable *glib_mem_profiler_table;
void g_mem_profile (void);
-
-/* Memchunk convenience functions
+/* slices - fast allocation/release of small memory blocks
*/
+gpointer g_slice_alloc (guint block_size);
+gpointer g_slice_alloc0 (guint block_size);
+void g_slice_free1 (guint block_size,
+ gpointer mem_block);
+void g_slice_free_chain (guint block_size,
+ gpointer mem_chain,
+ guint next_offset);
+#define g_slice_new(type) ((type*) g_slice_alloc (sizeof (type)))
+#define g_slice_new0(type) ((type*) g_slice_alloc0 (sizeof (type)))
+#define g_slice_free(type,mem) g_slice_free1 (sizeof (type), mem)
+
+
+/* deprecated memchunks and allocators */
+#if !defined G_DISABLE_DEPRECATED || 1
+typedef struct _GAllocator GAllocator;
+typedef struct _GMemChunk GMemChunk;
#define g_mem_chunk_create(type, pre_alloc, alloc_type) ( \
g_mem_chunk_new (#type " mem chunks (" #pre_alloc ")", \
sizeof (type), \
#define g_chunk_free(mem, mem_chunk) G_STMT_START { \
g_mem_chunk_free ((mem_chunk), (mem)); \
} G_STMT_END
-
-
-/* "g_mem_chunk_new" creates a new memory chunk.
- * Memory chunks are used to allocate pieces of memory which are
- * always the same size. Lists are a good example of such a data type.
- * The memory chunk allocates and frees blocks of memory as needed.
- * Just be sure to call "g_mem_chunk_free" and not "g_free" on data
- * allocated in a mem chunk. ("g_free" will most likely cause a seg
- * fault...somewhere).
- *
- * Oh yeah, GMemChunk is an opaque data type. (You don't really
- * want to know what's going on inside do you?)
- */
-
-/* ALLOC_ONLY MemChunks can only allocate memory. The free operation
- * is interpreted as a no op. ALLOC_ONLY MemChunks save 4 bytes per
- * atom. (They are also useful for lists which use MemChunk to allocate
- * memory but are also part of the MemChunk implementation).
- * ALLOC_AND_FREE MemChunks can allocate and free memory.
- */
-
#define G_ALLOC_ONLY 1
#define G_ALLOC_AND_FREE 2
-
GMemChunk* g_mem_chunk_new (const gchar *name,
gint atom_size,
gulong area_size,
void g_mem_chunk_reset (GMemChunk *mem_chunk);
void g_mem_chunk_print (GMemChunk *mem_chunk);
void g_mem_chunk_info (void);
-
-/* Ah yes...we have a "g_blow_chunks" function.
- * "g_blow_chunks" simply compresses all the chunks. This operation
- * consists of freeing every memory area that should be freed (but
- * which we haven't gotten around to doing yet). And, no,
- * "g_blow_chunks" doesn't follow the naming scheme, but it is a
- * much better name than "g_mem_chunk_clean_all" or something
- * similar.
- */
-void g_blow_chunks (void);
-
-
-/* Generic allocators
- */
-GAllocator* g_allocator_new (const gchar *name,
- guint n_preallocs);
-void g_allocator_free (GAllocator *allocator);
-
-/* internal */
-#define G_ALLOCATOR_LIST (1)
-#define G_ALLOCATOR_SLIST (2)
-#define G_ALLOCATOR_NODE (3)
-
+void g_blow_chunks (void);
+GAllocator*g_allocator_new (const gchar *name,
+ guint n_preallocs);
+void g_allocator_free (GAllocator *allocator);
+#define G_ALLOCATOR_LIST (1)
+#define G_ALLOCATOR_SLIST (2)
+#define G_ALLOCATOR_NODE (3)
+#endif /* G_DISABLE_DEPRECATED */
G_END_DECLS
#include "glib.h"
#include "galias.h"
-#ifndef DISABLE_MEM_POOLS
-/* node allocation
- */
-struct _GAllocator /* from gmem.c */
-{
- gchar *name;
- guint16 n_preallocs;
- guint is_unused : 1;
- guint type : 4;
- GAllocator *last;
- GMemChunk *mem_chunk;
- GNode *free_nodes; /* implementation specific */
-};
-
-G_LOCK_DEFINE_STATIC (current_allocator);
-static GAllocator *current_allocator = NULL;
-
-/* HOLDS: current_allocator_lock */
-static void
-g_node_validate_allocator (GAllocator *allocator)
-{
- g_return_if_fail (allocator != NULL);
- g_return_if_fail (allocator->is_unused == TRUE);
-
- if (allocator->type != G_ALLOCATOR_NODE)
- {
- allocator->type = G_ALLOCATOR_NODE;
- if (allocator->mem_chunk)
- {
- g_mem_chunk_destroy (allocator->mem_chunk);
- allocator->mem_chunk = NULL;
- }
- }
-
- if (!allocator->mem_chunk)
- {
- allocator->mem_chunk = g_mem_chunk_new (allocator->name,
- sizeof (GNode),
- sizeof (GNode) * allocator->n_preallocs,
- G_ALLOC_ONLY);
- allocator->free_nodes = NULL;
- }
-
- allocator->is_unused = FALSE;
-}
-
-void
-g_node_push_allocator (GAllocator *allocator)
-{
- G_LOCK (current_allocator);
- g_node_validate_allocator (allocator);
- allocator->last = current_allocator;
- current_allocator = allocator;
- G_UNLOCK (current_allocator);
-}
-
-void
-g_node_pop_allocator (void)
-{
- G_LOCK (current_allocator);
- if (current_allocator)
- {
- GAllocator *allocator;
-
- allocator = current_allocator;
- current_allocator = allocator->last;
- allocator->last = NULL;
- allocator->is_unused = TRUE;
- }
- G_UNLOCK (current_allocator);
-}
+void g_node_push_allocator (gpointer dummy) { /* present for binary compat only */ }
+void g_node_pop_allocator (void) { /* present for binary compat only */ }
+#define g_node_alloc0() g_slice_new0 (GNode)
+#define g_node_free(node) g_slice_free (GNode, node)
/* --- functions --- */
GNode*
g_node_new (gpointer data)
{
- GNode *node;
-
- G_LOCK (current_allocator);
- if (!current_allocator)
- {
- GAllocator *allocator = g_allocator_new ("GLib default GNode allocator",
- 128);
- g_node_validate_allocator (allocator);
- allocator->last = NULL;
- current_allocator = allocator;
- }
- if (!current_allocator->free_nodes)
- node = g_chunk_new (GNode, current_allocator->mem_chunk);
- else
- {
- node = current_allocator->free_nodes;
- current_allocator->free_nodes = node->next;
- }
- G_UNLOCK (current_allocator);
-
+ GNode *node = g_node_alloc0();
node->data = data;
- node->next = NULL;
- node->prev = NULL;
- node->parent = NULL;
- node->children = NULL;
-
return node;
}
static void
g_nodes_free (GNode *node)
{
- GNode *parent;
-
- parent = node;
- while (1)
- {
- if (parent->children)
- g_nodes_free (parent->children);
-
-#ifdef ENABLE_GC_FRIENDLY
- parent->data = NULL;
- parent->prev = NULL;
- parent->parent = NULL;
- parent->children = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
-
- if (parent->next)
- parent = parent->next;
- else
- break;
- }
-
- G_LOCK (current_allocator);
- parent->next = current_allocator->free_nodes;
- current_allocator->free_nodes = node;
- G_UNLOCK (current_allocator);
-}
-#else /* DISABLE_MEM_POOLS */
-
-GNode*
-g_node_new (gpointer data)
-{
- GNode *node;
-
- node = g_new0 (GNode, 1);
-
- node->data = data;
-
- return node;
-}
-
-static void
-g_nodes_free (GNode *root)
-{
- GNode *node, *next;
-
- node = root;
- while (node != NULL)
+ while (node)
{
- next = node->next;
- g_nodes_free (node->children);
- g_free (node);
+ GNode *next = node->next;
+ if (node->children)
+ g_nodes_free (node->children);
+ g_node_free (node);
node = next;
}
}
-#endif
void
g_node_destroy (GNode *root)
((GNode*) (node))->next == NULL)
#define G_NODE_IS_LEAF(node) (((GNode*) (node))->children == NULL)
-void g_node_push_allocator (GAllocator *allocator);
-void g_node_pop_allocator (void);
GNode* g_node_new (gpointer data);
void g_node_destroy (GNode *root);
void g_node_unlink (GNode *node);
#define g_node_first_child(node) ((node) ? \
((GNode*) (node))->children : NULL)
+#ifndef G_DISABLE_DEPRECATED
+void g_node_push_allocator (gpointer dummy);
+void g_node_pop_allocator (void);
+#endif
G_END_DECLS
#endif /* __G_NODE_H__ */
#include "glib.h"
#include "galias.h"
-
-G_LOCK_DEFINE_STATIC (queue_memchunk);
-static GMemChunk *queue_memchunk = NULL;
-static GTrashStack *free_queue_nodes = NULL;
-
/**
* g_queue_new:
*
GQueue*
g_queue_new (void)
{
- GQueue *queue;
-
- G_LOCK (queue_memchunk);
- queue = g_trash_stack_pop (&free_queue_nodes);
-
- if (!queue)
- {
- if (!queue_memchunk)
- queue_memchunk = g_mem_chunk_new ("GLib GQueue chunk",
- sizeof (GQueue),
- sizeof (GQueue) * 128,
- G_ALLOC_ONLY);
- queue = g_chunk_new (GQueue, queue_memchunk);
- }
- G_UNLOCK (queue_memchunk);
-
- queue->head = NULL;
- queue->tail = NULL;
- queue->length = 0;
-
- return queue;
+ return g_slice_new0 (GQueue);
}
/**
g_return_if_fail (queue != NULL);
g_list_free (queue->head);
-
-#ifdef ENABLE_GC_FRIENDLY
- queue->head = NULL;
- queue->tail = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
-
- G_LOCK (queue_memchunk);
- g_trash_stack_push (&free_queue_nodes, queue);
- G_UNLOCK (queue_memchunk);
+ g_slice_free (GQueue, queue);
}
/**
GHashTable *all_tuples;
GHashTable **hashed_tuple_tables;
- GMemChunk *tuple_chunk;
gint count;
};
GRelation* rel = g_new0 (GRelation, 1);
rel->fields = fields;
- rel->tuple_chunk = g_mem_chunk_new ("Relation Chunk",
- fields * sizeof (gpointer),
- fields * sizeof (gpointer) * 128,
- G_ALLOC_AND_FREE);
rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields));
rel->hashed_tuple_tables = g_new0 (GHashTable*, fields);
}
static void
+relation_delete_value_tuple (gpointer tuple_key,
+ gpointer tuple_value,
+ gpointer user_data)
+{
+ GRelation *relation = user_data;
+ gpointer *tuple = tuple_value;
+ g_slice_free1 (relation->fields * sizeof (gpointer), tuple);
+}
+
+static void
g_relation_free_array (gpointer key, gpointer value, gpointer user_data)
{
g_hash_table_destroy ((GHashTable*) value);
if (relation)
{
- g_hash_table_destroy (relation->all_tuples);
- g_mem_chunk_destroy (relation->tuple_chunk);
-
for (i = 0; i < relation->fields; i += 1)
{
if (relation->hashed_tuple_tables[i])
g_hash_table_destroy (relation->hashed_tuple_tables[i]);
}
}
+
+ g_hash_table_foreach (relation->all_tuples, relation_delete_value_tuple, relation);
+ g_hash_table_destroy (relation->all_tuples);
g_free (relation->hashed_tuple_tables);
g_free (relation);
g_relation_insert (GRelation *relation,
...)
{
- gpointer* tuple = g_chunk_new (gpointer, relation->tuple_chunk);
+ gpointer* tuple = g_slice_alloc (relation->fields * sizeof (gpointer));
va_list args;
gint i;
- va_start(args, relation);
+ va_start (args, relation);
for (i = 0; i < relation->fields; i += 1)
- tuple[i] = va_arg(args, gpointer);
+ tuple[i] = va_arg (args, gpointer);
- va_end(args);
+ va_end (args);
g_hash_table_insert (relation->all_tuples, tuple, tuple);
gpointer user_data)
{
gpointer *tuple = (gpointer*) tuple_value;
- GRelation *rel = (GRelation *) user_data;
+ GRelation *relation = (GRelation *) user_data;
gint j;
g_assert (tuple_key == tuple_value);
- for (j = 0; j < rel->fields; j += 1)
+ for (j = 0; j < relation->fields; j += 1)
{
- GHashTable *one_table = rel->hashed_tuple_tables[j];
+ GHashTable *one_table = relation->hashed_tuple_tables[j];
gpointer one_key;
GHashTable *per_key_table;
if (one_table == NULL)
continue;
- if (j == rel->current_field)
+ if (j == relation->current_field)
/* can't delete from the table we're foreaching in */
continue;
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
gboolean
g_relation_exists (GRelation *relation, ...)
{
- gpointer* tuple = g_chunk_new (gpointer, relation->tuple_chunk);
+ gpointer *tuple = g_slice_alloc (relation->fields * sizeof (gpointer));
va_list args;
gint i;
gboolean result;
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;
}
#include "galias.h"
-#ifndef DISABLE_MEM_POOLS
-struct _GAllocator /* from gmem.c */
-{
- gchar *name;
- guint16 n_preallocs;
- guint is_unused : 1;
- guint type : 4;
- GAllocator *last;
- GMemChunk *mem_chunk;
- GSList *free_lists; /* implementation specific */
-};
-
-G_LOCK_DEFINE_STATIC (current_allocator);
-static GAllocator *current_allocator = NULL;
-
-/* HOLDS: current_allocator_lock */
-static void
-g_slist_validate_allocator (GAllocator *allocator)
-{
- g_return_if_fail (allocator != NULL);
- g_return_if_fail (allocator->is_unused == TRUE);
-
- if (allocator->type != G_ALLOCATOR_SLIST)
- {
- allocator->type = G_ALLOCATOR_SLIST;
- if (allocator->mem_chunk)
- {
- g_mem_chunk_destroy (allocator->mem_chunk);
- allocator->mem_chunk = NULL;
- }
- }
-
- if (!allocator->mem_chunk)
- {
- allocator->mem_chunk = g_mem_chunk_new (allocator->name,
- sizeof (GSList),
- sizeof (GSList) * allocator->n_preallocs,
- G_ALLOC_ONLY);
- allocator->free_lists = NULL;
- }
-
- allocator->is_unused = FALSE;
-}
-
-void
-g_slist_push_allocator (GAllocator *allocator)
-{
- G_LOCK (current_allocator);
- g_slist_validate_allocator (allocator);
- allocator->last = current_allocator;
- current_allocator = allocator;
- G_UNLOCK (current_allocator);
-}
-
-void
-g_slist_pop_allocator (void)
-{
- G_LOCK (current_allocator);
- if (current_allocator)
- {
- GAllocator *allocator;
+void g_slist_push_allocator (gpointer dummy) { /* present for binary compat only */ }
+void g_slist_pop_allocator (void) { /* present for binary compat only */ }
- allocator = current_allocator;
- current_allocator = allocator->last;
- allocator->last = NULL;
- allocator->is_unused = TRUE;
- }
- G_UNLOCK (current_allocator);
-}
-
-static inline GSList*
-_g_slist_alloc (void)
-{
- GSList *list;
-
- G_LOCK (current_allocator);
- if (!current_allocator)
- {
- GAllocator *allocator = g_allocator_new ("GLib default GSList allocator",
- 128);
- g_slist_validate_allocator (allocator);
- allocator->last = NULL;
- current_allocator = allocator;
- }
- if (!current_allocator->free_lists)
- {
- list = g_chunk_new (GSList, current_allocator->mem_chunk);
- list->data = NULL;
- }
- else
- {
- if (current_allocator->free_lists->data)
- {
- list = current_allocator->free_lists->data;
- current_allocator->free_lists->data = list->next;
- list->data = NULL;
- }
- else
- {
- list = current_allocator->free_lists;
- current_allocator->free_lists = list->next;
- }
- }
- G_UNLOCK (current_allocator);
-
- list->next = NULL;
+#define _g_slist_alloc0() g_slice_new0 (GSList)
+#define _g_slist_free1(slist) g_slice_free (GSList, slist)
- return list;
-}
-
-GSList*
-g_slist_alloc (void)
-{
- return _g_slist_alloc ();
-}
-
-void
-g_slist_free (GSList *list)
-{
- if (list)
- {
- GSList *last_node = list;
-
-#ifdef ENABLE_GC_FRIENDLY
- while (last_node->next)
- {
- last_node->data = NULL;
- last_node = last_node->next;
- }
- last_node->data = NULL;
-#else /* !ENABLE_GC_FRIENDLY */
- list->data = list->next;
-#endif /* ENABLE_GC_FRIENDLY */
-
- G_LOCK (current_allocator);
- last_node->next = current_allocator->free_lists;
- current_allocator->free_lists = list;
- G_UNLOCK (current_allocator);
- }
-}
-
-static inline void
-_g_slist_free_1 (GSList *list)
-{
- if (list)
- {
- list->data = NULL;
- G_LOCK (current_allocator);
- list->next = current_allocator->free_lists;
- current_allocator->free_lists = list;
- G_UNLOCK (current_allocator);
- }
-}
-
-void
-g_slist_free_1 (GSList *list)
-{
- _g_slist_free_1 (list);
-}
-#else /* DISABLE_MEM_POOLS */
-
-#define _g_slist_alloc g_slist_alloc
GSList*
g_slist_alloc (void)
{
- GSList *list;
-
- list = g_new0 (GSList, 1);
-
- return list;
+ return _g_slist_alloc0 ();
}
void
-g_slist_free (GSList *list)
+g_slist_free (GSList *slist)
{
- GSList *last;
-
- while (list)
- {
- last = list;
- list = list->next;
- g_free (last);
- }
+ g_slice_free_chain (sizeof (GSList), slist, G_STRUCT_OFFSET (GSList, next));
}
-#define _g_slist_free_1 g_slist_free_1
void
-g_slist_free_1 (GSList *list)
+g_slist_free_1 (GSList *slist)
{
- g_free (list);
+ _g_slist_free1 (slist);
}
-#endif
-
GSList*
g_slist_append (GSList *list,
gpointer data)
GSList *new_list;
GSList *last;
- new_list = _g_slist_alloc ();
+ new_list = _g_slist_alloc0 ();
new_list->data = data;
if (list)
{
GSList *new_list;
- new_list = _g_slist_alloc ();
+ new_list = _g_slist_alloc0 ();
new_list->data = data;
new_list->next = list;
else if (position == 0)
return g_slist_prepend (list, data);
- new_list = _g_slist_alloc ();
+ new_list = _g_slist_alloc0 ();
new_list->data = data;
if (!list)
GSList *link)
{
list = _g_slist_remove_link (list, link);
- _g_slist_free_1 (link);
+ _g_slist_free1 (link);
return list;
}
{
GSList *last;
- new_list = _g_slist_alloc ();
+ new_list = _g_slist_alloc0 ();
new_list->data = list->data;
last = new_list;
list = list->next;
while (list)
{
- last->next = _g_slist_alloc ();
+ last->next = _g_slist_alloc0 ();
last = last->next;
last->data = list->data;
list = list->next;
if (!list)
{
- new_list = _g_slist_alloc ();
+ new_list = _g_slist_alloc0 ();
new_list->data = data;
return new_list;
}
cmp = (*func) (data, tmp_list->data);
}
- new_list = _g_slist_alloc ();
+ new_list = _g_slist_alloc0 ();
new_list->data = data;
if ((!tmp_list->next) && (cmp > 0))
/* Singly linked lists
*/
-void g_slist_push_allocator (GAllocator *allocator);
-void g_slist_pop_allocator (void);
GSList* g_slist_alloc (void);
void g_slist_free (GSList *list);
void g_slist_free_1 (GSList *list);
+#define g_slist_free1 g_slist_free_1
GSList* g_slist_append (GSList *list,
gpointer data);
GSList* g_slist_prepend (GSList *list,
guint n);
#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL)
+#ifndef G_DISABLE_DEPRECATED
+void g_slist_push_allocator (gpointer dummy);
+void g_slist_pop_allocator (void);
+#endif
G_END_DECLS
#endif /* __G_SLIST_H__ */
gsize default_size;
};
-G_LOCK_DEFINE_STATIC (string_mem_chunk);
-static GMemChunk *string_mem_chunk = NULL;
-
/* Hash Functions.
*/
GString*
g_string_sized_new (gsize dfl_size)
{
- GString *string;
-
- G_LOCK (string_mem_chunk);
- if (!string_mem_chunk)
- string_mem_chunk = g_mem_chunk_new ("string mem chunk",
- sizeof (GString),
- 1024, G_ALLOC_AND_FREE);
-
- string = g_chunk_new (GString, string_mem_chunk);
- G_UNLOCK (string_mem_chunk);
+ GString *string = g_slice_new (GString);
string->allocated_len = 0;
string->len = 0;
else
segment = string->str;
- G_LOCK (string_mem_chunk);
- g_mem_chunk_free (string_mem_chunk, string);
- G_UNLOCK (string_mem_chunk);
+ g_slice_free (GString, string);
return segment;
}
{
GThread thread;
gpointer private_data;
+ gpointer mem_private;
+ GRealThread *next;
gpointer retval;
GSystemThread system_thread;
};
static GMutex *g_once_mutex = NULL;
static GCond *g_once_cond = NULL;
static GPrivate *g_thread_specific_private = NULL;
-static GSList *g_thread_all_threads = NULL;
+static GRealThread *g_thread_all_threads = NULL;
static GSList *g_thread_free_indeces = NULL;
G_LOCK_DEFINE_STATIC (g_thread);
g_static_private_free (GStaticPrivate *private_key)
{
guint index = private_key->index;
- GSList *list;
+ GRealThread *thread;
if (!index)
return;
private_key->index = 0;
G_LOCK (g_thread);
- list = g_thread_all_threads;
- while (list)
+
+ thread = g_thread_all_threads;
+ while (thread)
{
- GRealThread *thread = list->data;
GArray *array = thread->private_data;
- list = list->next;
+ thread = thread->next;
if (array && index <= array->len)
{
it is, the structure is freed in g_thread_join */
if (!thread->thread.joinable)
{
+ GRealThread *t, *p;
+
G_LOCK (g_thread);
- g_thread_all_threads = g_slist_remove (g_thread_all_threads, data);
+ for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
+ {
+ if (t == thread)
+ {
+ if (p)
+ p->next = t->next;
+ else
+ g_thread_all_threads = t->next;
+ break;
+ }
+ }
G_UNLOCK (g_thread);
/* Just to make sure, this isn't used any more */
g_return_val_if_fail (priority >= G_THREAD_PRIORITY_LOW, NULL);
g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL);
- result = g_new (GRealThread, 1);
+ result = g_new0 (GRealThread, 1);
result->thread.joinable = joinable;
result->thread.priority = priority;
G_THREAD_UF (thread_create, (g_thread_create_proxy, result,
stack_size, joinable, bound, priority,
&result->system_thread, &local_error));
- g_thread_all_threads = g_slist_prepend (g_thread_all_threads, result);
+ result->next = g_thread_all_threads;
+ g_thread_all_threads = result;
G_UNLOCK (g_thread);
if (local_error)
g_thread_join (GThread* thread)
{
GRealThread* real = (GRealThread*) thread;
+ GRealThread *p, *t;
gpointer retval;
g_return_val_if_fail (thread, NULL);
retval = real->retval;
G_LOCK (g_thread);
- g_thread_all_threads = g_slist_remove (g_thread_all_threads, thread);
+ for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
+ {
+ if (t == (GRealThread*) thread)
+ {
+ if (p)
+ p->next = t->next;
+ else
+ g_thread_all_threads = t->next;
+ break;
+ }
+ }
G_UNLOCK (g_thread);
/* Just to make sure, this isn't used any more */
/* If no thread data is available, provide and set one. This
can happen for the main thread and for threads, that are not
created by GLib. */
- thread = g_new (GRealThread, 1);
+ thread = g_new0 (GRealThread, 1);
thread->thread.joinable = FALSE; /* This is a save guess */
thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is
just a guess */
g_private_set (g_thread_specific_private, thread);
G_LOCK (g_thread);
- g_thread_all_threads = g_slist_prepend (g_thread_all_threads, thread);
+ thread->next = g_thread_all_threads;
+ g_thread_all_threads = thread;
G_UNLOCK (g_thread);
}
g_static_mutex_free (&lock->mutex);
}
+/*
+ * Memory allocation can't use the regular GPrivate
+ * API, since that relies on GArray, which uses
+ * chunked memory.
+ */
+gpointer
+_g_thread_mem_private_get (GThread *thread)
+{
+ GRealThread *real_thread = (GRealThread*) thread;
+
+ return real_thread->mem_private;
+}
+
+void
+_g_thread_mem_private_set (GThread *thread,
+ gpointer data)
+{
+ GRealThread *real_thread = (GRealThread*) thread;
+
+ real_thread->mem_private = data;
+}
+
+/**
+ * g_thread_foreach
+ * @thread_func: function to call for all GThread structures
+ * @user_data: second argument to @thread_func
+ * Call @thread_func on all existing GThread structures. Note that
+ * threads may decide to exit while @thread_func is running, so
+ * without intimate knowledge about the lifetime of foreign threads,
+ * @thread_func shouldn't access the GThread* pointer passed in as
+ * first argument. However, @thread_func will not be called for threads
+ * which are known to have exited already.
+ * Due to thread lifetime checks, this function has an execution complexity
+ * which is quadratic in the number of existing threads.
+ */
+void
+g_thread_foreach (GFunc thread_func,
+ gpointer user_data)
+{
+ GSList *slist = NULL;
+ GRealThread *thread;
+ g_return_if_fail (thread_func != NULL);
+ /* snapshot the list of threads for iteration */
+ G_LOCK (g_thread);
+ for (thread = g_thread_all_threads; thread; thread = thread->next)
+ slist = g_slist_prepend (slist, thread);
+ G_UNLOCK (g_thread);
+ /* walk the list, skipping non-existant threads */
+ while (slist)
+ {
+ GSList *node = slist;
+ slist = node->next;
+ /* check whether the current thread still exists */
+ G_LOCK (g_thread);
+ for (thread = g_thread_all_threads; thread; thread = thread->next)
+ if (thread == node->data)
+ break;
+ G_UNLOCK (g_thread);
+ if (thread)
+ thread_func (thread, user_data);
+ g_slist_free_1 (node);
+ }
+}
+
#define __G_THREAD_C__
#include "galiasdef.c"
void g_static_rw_lock_writer_unlock (GStaticRWLock* lock);
void g_static_rw_lock_free (GStaticRWLock* lock);
+void g_thread_foreach (GFunc thread_func,
+ gpointer user_data);
+
typedef enum
{
G_ONCE_STATUS_NOTCALLED,
# define G_TRYLOCK(name) (TRUE)
#endif /* !G_THREADS_ENABLED */
+/* --- internal API --- */
+gpointer _g_thread_mem_private_get (GThread *thread);
+void _g_thread_mem_private_set (GThread *thread,
+ gpointer data);
+
G_END_DECLS
#endif /* __G_THREAD_H__ */
static void g_tree_node_check (GTreeNode *node);
-G_LOCK_DEFINE_STATIC (g_tree_global);
-static GMemChunk *node_mem_chunk = NULL;
-static GTreeNode *node_free_list = NULL;
-
-
static GTreeNode*
g_tree_node_new (gpointer key,
gpointer value)
{
- GTreeNode *node;
-
- G_LOCK (g_tree_global);
- if (node_free_list)
- {
- node = node_free_list;
- node_free_list = node->right;
- }
- else
- {
- if (!node_mem_chunk)
- node_mem_chunk = g_mem_chunk_new ("GLib GTreeNode mem chunk",
- sizeof (GTreeNode),
- 1024,
- G_ALLOC_ONLY);
-
- node = g_chunk_new (GTreeNode, node_mem_chunk);
- }
- G_UNLOCK (g_tree_global);
+ GTreeNode *node = g_slice_new (GTreeNode);
node->balance = 0;
node->left = NULL;
node->value = NULL;
#endif /* ENABLE_GC_FRIENDLY */
- G_LOCK (g_tree_global);
- node->right = node_free_list;
- node_free_list = node;
- G_UNLOCK (g_tree_global);
+ g_slice_free (GTreeNode, node);
}
}
garbage->value = NULL;
#endif /* ENABLE_GC_FRIENDLY */
- G_LOCK (g_tree_global);
- garbage->right = node_free_list;
- node_free_list = garbage;
- G_UNLOCK (g_tree_global);
+ g_slice_free (GTreeNode, garbage);
*removed = TRUE;
}
+Tue Nov 1 17:07:43 2005 Tim Janik <timj@imendio.com>
+
+ * gsignal.c: allocate signal handlers and handler match structures
+ via the new g_slice_*() API (get's rid of GList allocation hack).
+
+ * gtype.c: got rid of per-type memchunks. if GTypeInfo.n_preallocs
+ is > 0, objects are allocated via g_slice_*() instead of g_malloc().
+
2005-10-03 Matthias Clasen <mclasen@redhat.com>
* glib-mkenums.in: Really fix #314890.
/* pre allocation configurations
*/
#define MAX_STACK_VALUES (16)
-#define HANDLER_PRE_ALLOC (48)
#define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org"
#ifdef G_ENABLE_DEBUG
#endif /* G_ENABLE_DEBUG */
-/* --- generic allocation --- */
-/* we special case allocations generically by replacing
- * these functions with more speed/memory aware variants
- */
-#ifndef DISABLE_MEM_POOLS
-static inline gpointer
-g_generic_node_alloc (GTrashStack **trash_stack_p,
- guint sizeof_node,
- guint nodes_pre_alloc)
-{
- gpointer node = g_trash_stack_pop (trash_stack_p);
-
- if (!node)
- {
- guint8 *block;
-
- nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
- block = g_malloc (sizeof_node * nodes_pre_alloc);
- while (--nodes_pre_alloc)
- {
- g_trash_stack_push (trash_stack_p, block);
- block += sizeof_node;
- }
- node = block;
- }
-
- return node;
-}
-#define g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node)
-#else /* !DISABLE_MEM_POOLS */
-#define g_generic_node_alloc(t,sizeof_node,p) g_malloc (sizeof_node)
-#define g_generic_node_free(t,node) g_free (node)
-#endif /* !DISABLE_MEM_POOLS */
-
-
/* --- typedefs --- */
typedef struct _SignalNode SignalNode;
typedef struct _SignalKey SignalKey;
{
Handler *handler;
HandlerMatch *next;
- union {
- guint signal_id;
- gpointer dummy;
- } d;
+ guint signal_id;
};
typedef struct
* instead, we use GList* nodes, since they are exactly the size
* we need and are already cached. g_signal_init() asserts this.
*/
- node = (HandlerMatch*) g_list_alloc ();
+ node = g_slice_new (HandlerMatch);
node->handler = handler;
node->next = list;
- node->d.signal_id = signal_id;
+ node->signal_id = signal_id;
handler_ref (handler);
return node;
{
HandlerMatch *next = node->next;
- handler_unref_R (node->d.signal_id, instance, node->handler);
- g_list_free_1 ((GList*) node);
+ handler_unref_R (node->signal_id, instance, node->handler);
+ g_slice_free (HandlerMatch, node);
return next;
}
static inline Handler*
handler_new (gboolean after)
{
- Handler *handler = g_generic_node_alloc (&g_handler_ts,
- sizeof (Handler),
- HANDLER_PRE_ALLOC);
+ Handler *handler = g_slice_new (Handler);
#ifndef G_DISABLE_CHECKS
if (g_handler_sequential_number < 1)
g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
SIGNAL_UNLOCK ();
g_closure_unref (handler->closure);
SIGNAL_LOCK ();
- g_generic_node_free (&g_handler_ts, handler);
+ g_slice_free (Handler, handler);
}
}
guint16 private_size;
guint16 n_preallocs;
GInstanceInitFunc instance_init;
- GMemChunk *mem_chunk;
};
union _TypeData
{
data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
#endif /* !DISABLE_MEM_POOLS */
data->instance.instance_init = info->instance_init;
- data->instance.mem_chunk = NULL;
}
else if (node->is_classed) /* only classed */
{
TypeNode *node;
GTypeInstance *instance;
GTypeClass *class;
- guint i;
- gsize total_instance_size;
+ guint i, total_size;
node = lookup_type_node_I (type);
if (!node || !node->is_instantiatable)
}
class = g_type_class_ref (type);
+ total_size = type_total_instance_size_I (node);
- total_instance_size = type_total_instance_size_I (node);
-
if (node->data->instance.n_preallocs)
- {
- G_WRITE_LOCK (&type_rw_lock);
- if (!node->data->instance.mem_chunk)
- {
- /* If there isn't private data, the compiler will have already
- * added the necessary padding, but in the private data case, we
- * have to pad ourselves to ensure proper alignment of all the
- * atoms in the slab.
- */
- gsize atom_size = total_instance_size;
- if (node->data->instance.private_size)
- atom_size = ALIGN_STRUCT (atom_size);
-
- node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
- atom_size,
- (atom_size *
- node->data->instance.n_preallocs),
- G_ALLOC_AND_FREE);
- }
-
- instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
- G_WRITE_UNLOCK (&type_rw_lock);
- }
+ instance = g_slice_alloc0 (total_size);
else
- instance = g_malloc0 (total_instance_size); /* fine without read lock */
+ instance = g_malloc0 (total_size);
if (node->data->instance.private_size)
instance_real_class_set (instance, class);
instance->g_class = NULL;
#ifdef G_ENABLE_DEBUG
- memset (instance, 0xaa, type_total_instance_size_I (node)); /* debugging hack */
-#endif
+ memset (instance, 0xaa, type_total_instance_size_I (node));
+#endif
if (node->data->instance.n_preallocs)
- {
- G_WRITE_LOCK (&type_rw_lock);
- g_chunk_free (instance, node->data->instance.mem_chunk);
- G_WRITE_UNLOCK (&type_rw_lock);
- }
+ g_slice_free1 (type_total_instance_size_I (node), instance);
else
g_free (instance);
-
+
g_type_class_unref (class);
}
node->data->common.ref_count = 0;
- if (node->is_instantiatable && node->data->instance.mem_chunk)
+ if (node->is_instantiatable)
{
- g_mem_chunk_destroy (node->data->instance.mem_chunk);
- node->data->instance.mem_chunk = NULL;
+ /* destroy node->data->instance.mem_chunk */
}
tdata = node->data;