removed the GListAllocator type and its g_*_allocator_*() function
authorTim Janik <timj@gtk.org>
Tue, 24 Nov 1998 12:18:22 +0000 (12:18 +0000)
committerTim Janik <timj@src.gnome.org>
Tue, 24 Nov 1998 12:18:22 +0000 (12:18 +0000)
Tue Nov 24 09:40:00 1998  Tim Janik  <timj@gtk.org>

        * glib.h: removed the GListAllocator type and its g_*_allocator_*()
        function variants (which weren't working anyways) in favour of a
        generic GAllocator type. new functions:
        g_allocator_new, g_allocator_free, g_slist_push_allocator,
        g_slist_pop_allocator, g_list_push_allocator, g_list_pop_allocator,
        g_node_push_allocator and g_node_pop_allocator.

        * gstring.c: removed bogus slist allocator code.
        * gtree.c: maintain own list of free tree nodes and don't waste
        GSLists for that, removed bogus slist allocator code.
        * glist.c: use GAllocators for node allocation.
        * gslist.c: use GAllocators for node allocation.
        * gnode.c: use GAllocators for node allocation.

        * gdataset.c: cleanups wrt automatic initialization.

24 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdataset.c
glib.h
glib/gdataset.c
glib/glib.h
glib/glist.c
glib/gmem.c
glib/gnode.c
glib/gslist.c
glib/gstring.c
glib/gtree.c
glist.c
gmem.c
gnode.c
gslist.c
gstring.c
gtree.c

index f13b2a6..4d0a13f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+Tue Nov 24 09:40:00 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h: removed the GListAllocator type and its g_*_allocator_*()
+       function variants (which weren't working anyways) in favour of a
+       generic GAllocator type. new functions:
+       g_allocator_new, g_allocator_free, g_slist_push_allocator,
+       g_slist_pop_allocator, g_list_push_allocator, g_list_pop_allocator,
+       g_node_push_allocator and g_node_pop_allocator.
+
+       * gstring.c: removed bogus slist allocator code.
+       * gtree.c: maintain own list of free tree nodes and don't waste
+       GSLists for that, removed bogus slist allocator code.
+       * glist.c: use GAllocators for node allocation.
+       * gslist.c: use GAllocators for node allocation.
+       * gnode.c: use GAllocators for node allocation.
+
+       * gdataset.c: cleanups wrt automatic initialization.
+
 Mon Nov 23 10:03:58 1998  Owen Taylor  <otaylor@gtk.org>
 
        * glib.h garray.[ch]: added g_array_insert_vals() to
index f13b2a6..4d0a13f 100644 (file)
@@ -1,3 +1,21 @@
+Tue Nov 24 09:40:00 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h: removed the GListAllocator type and its g_*_allocator_*()
+       function variants (which weren't working anyways) in favour of a
+       generic GAllocator type. new functions:
+       g_allocator_new, g_allocator_free, g_slist_push_allocator,
+       g_slist_pop_allocator, g_list_push_allocator, g_list_pop_allocator,
+       g_node_push_allocator and g_node_pop_allocator.
+
+       * gstring.c: removed bogus slist allocator code.
+       * gtree.c: maintain own list of free tree nodes and don't waste
+       GSLists for that, removed bogus slist allocator code.
+       * glist.c: use GAllocators for node allocation.
+       * gslist.c: use GAllocators for node allocation.
+       * gnode.c: use GAllocators for node allocation.
+
+       * gdataset.c: cleanups wrt automatic initialization.
+
 Mon Nov 23 10:03:58 1998  Owen Taylor  <otaylor@gtk.org>
 
        * glib.h garray.[ch]: added g_array_insert_vals() to
index f13b2a6..4d0a13f 100644 (file)
@@ -1,3 +1,21 @@
+Tue Nov 24 09:40:00 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h: removed the GListAllocator type and its g_*_allocator_*()
+       function variants (which weren't working anyways) in favour of a
+       generic GAllocator type. new functions:
+       g_allocator_new, g_allocator_free, g_slist_push_allocator,
+       g_slist_pop_allocator, g_list_push_allocator, g_list_pop_allocator,
+       g_node_push_allocator and g_node_pop_allocator.
+
+       * gstring.c: removed bogus slist allocator code.
+       * gtree.c: maintain own list of free tree nodes and don't waste
+       GSLists for that, removed bogus slist allocator code.
+       * glist.c: use GAllocators for node allocation.
+       * gslist.c: use GAllocators for node allocation.
+       * gnode.c: use GAllocators for node allocation.
+
+       * gdataset.c: cleanups wrt automatic initialization.
+
 Mon Nov 23 10:03:58 1998  Owen Taylor  <otaylor@gtk.org>
 
        * glib.h garray.[ch]: added g_array_insert_vals() to
index f13b2a6..4d0a13f 100644 (file)
@@ -1,3 +1,21 @@
+Tue Nov 24 09:40:00 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h: removed the GListAllocator type and its g_*_allocator_*()
+       function variants (which weren't working anyways) in favour of a
+       generic GAllocator type. new functions:
+       g_allocator_new, g_allocator_free, g_slist_push_allocator,
+       g_slist_pop_allocator, g_list_push_allocator, g_list_pop_allocator,
+       g_node_push_allocator and g_node_pop_allocator.
+
+       * gstring.c: removed bogus slist allocator code.
+       * gtree.c: maintain own list of free tree nodes and don't waste
+       GSLists for that, removed bogus slist allocator code.
+       * glist.c: use GAllocators for node allocation.
+       * gslist.c: use GAllocators for node allocation.
+       * gnode.c: use GAllocators for node allocation.
+
+       * gdataset.c: cleanups wrt automatic initialization.
+
 Mon Nov 23 10:03:58 1998  Owen Taylor  <otaylor@gtk.org>
 
        * glib.h garray.[ch]: added g_array_insert_vals() to
index f13b2a6..4d0a13f 100644 (file)
@@ -1,3 +1,21 @@
+Tue Nov 24 09:40:00 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h: removed the GListAllocator type and its g_*_allocator_*()
+       function variants (which weren't working anyways) in favour of a
+       generic GAllocator type. new functions:
+       g_allocator_new, g_allocator_free, g_slist_push_allocator,
+       g_slist_pop_allocator, g_list_push_allocator, g_list_pop_allocator,
+       g_node_push_allocator and g_node_pop_allocator.
+
+       * gstring.c: removed bogus slist allocator code.
+       * gtree.c: maintain own list of free tree nodes and don't waste
+       GSLists for that, removed bogus slist allocator code.
+       * glist.c: use GAllocators for node allocation.
+       * gslist.c: use GAllocators for node allocation.
+       * gnode.c: use GAllocators for node allocation.
+
+       * gdataset.c: cleanups wrt automatic initialization.
+
 Mon Nov 23 10:03:58 1998  Owen Taylor  <otaylor@gtk.org>
 
        * glib.h garray.[ch]: added g_array_insert_vals() to
index f13b2a6..4d0a13f 100644 (file)
@@ -1,3 +1,21 @@
+Tue Nov 24 09:40:00 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h: removed the GListAllocator type and its g_*_allocator_*()
+       function variants (which weren't working anyways) in favour of a
+       generic GAllocator type. new functions:
+       g_allocator_new, g_allocator_free, g_slist_push_allocator,
+       g_slist_pop_allocator, g_list_push_allocator, g_list_pop_allocator,
+       g_node_push_allocator and g_node_pop_allocator.
+
+       * gstring.c: removed bogus slist allocator code.
+       * gtree.c: maintain own list of free tree nodes and don't waste
+       GSLists for that, removed bogus slist allocator code.
+       * glist.c: use GAllocators for node allocation.
+       * gslist.c: use GAllocators for node allocation.
+       * gnode.c: use GAllocators for node allocation.
+
+       * gdataset.c: cleanups wrt automatic initialization.
+
 Mon Nov 23 10:03:58 1998  Owen Taylor  <otaylor@gtk.org>
 
        * glib.h garray.[ch]: added g_array_insert_vals() to
index f13b2a6..4d0a13f 100644 (file)
@@ -1,3 +1,21 @@
+Tue Nov 24 09:40:00 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h: removed the GListAllocator type and its g_*_allocator_*()
+       function variants (which weren't working anyways) in favour of a
+       generic GAllocator type. new functions:
+       g_allocator_new, g_allocator_free, g_slist_push_allocator,
+       g_slist_pop_allocator, g_list_push_allocator, g_list_pop_allocator,
+       g_node_push_allocator and g_node_pop_allocator.
+
+       * gstring.c: removed bogus slist allocator code.
+       * gtree.c: maintain own list of free tree nodes and don't waste
+       GSLists for that, removed bogus slist allocator code.
+       * glist.c: use GAllocators for node allocation.
+       * gslist.c: use GAllocators for node allocation.
+       * gnode.c: use GAllocators for node allocation.
+
+       * gdataset.c: cleanups wrt automatic initialization.
+
 Mon Nov 23 10:03:58 1998  Owen Taylor  <otaylor@gtk.org>
 
        * glib.h garray.[ch]: added g_array_insert_vals() to
index f13b2a6..4d0a13f 100644 (file)
@@ -1,3 +1,21 @@
+Tue Nov 24 09:40:00 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h: removed the GListAllocator type and its g_*_allocator_*()
+       function variants (which weren't working anyways) in favour of a
+       generic GAllocator type. new functions:
+       g_allocator_new, g_allocator_free, g_slist_push_allocator,
+       g_slist_pop_allocator, g_list_push_allocator, g_list_pop_allocator,
+       g_node_push_allocator and g_node_pop_allocator.
+
+       * gstring.c: removed bogus slist allocator code.
+       * gtree.c: maintain own list of free tree nodes and don't waste
+       GSLists for that, removed bogus slist allocator code.
+       * glist.c: use GAllocators for node allocation.
+       * gslist.c: use GAllocators for node allocation.
+       * gnode.c: use GAllocators for node allocation.
+
+       * gdataset.c: cleanups wrt automatic initialization.
+
 Mon Nov 23 10:03:58 1998  Owen Taylor  <otaylor@gtk.org>
 
        * glib.h garray.[ch]: added g_array_insert_vals() to
index c62a8cd..7dafc21 100644 (file)
@@ -57,19 +57,19 @@ static inline void  g_data_set_internal             (GData          **datalist,
                                                         GDestroyNotify   destroy_func,
                                                         GDataset        *dataset);
 static void            g_data_initialize               (void);
-static inline GQuark   g_quark_new                     (const gchar    *string);
+static inline GQuark   g_quark_new                     (gchar          *string);
 
 
 /* --- variables --- */
-static GHashTable   *g_quark_ht = NULL;
-static gchar       **g_quarks = NULL;
-static GQuark        g_quark_seq_id = 0;
 static GHashTable   *g_dataset_location_ht = NULL;
 static GDataset     *g_dataset_cached = NULL;
 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;
+static GHashTable   *g_quark_ht = NULL;
+static gchar       **g_quarks = NULL;
+static GQuark        g_quark_seq_id = 0;
 
 
 /* --- functions --- */
@@ -109,6 +109,9 @@ g_datalist_clear (GData **datalist)
 {
   g_return_if_fail (datalist != NULL);
   
+  if (!g_dataset_location_ht)
+    g_data_initialize ();
+
   while (*datalist)
     g_datalist_clear_i (datalist);
 }
@@ -174,9 +177,6 @@ g_data_set_internal (GData    **datalist,
 {
   register GData *list;
   
-  if (!g_dataset_location_ht)
-    g_data_initialize ();
-  
   list = *datalist;
   if (!data)
     {
@@ -201,7 +201,7 @@ g_data_set_internal (GData    **datalist,
                }
              
              /* the GData struct *must* already be unlinked
-              * when invoking the destroy function
+              * when invoking the destroy function.
               * we use (data==NULL && destroy_func!=NULL) as
               * a special hint combination to "steal"
               * data without destroy notification
@@ -326,6 +326,9 @@ g_datalist_id_set_data_full (GData    **datalist,
       else
        return;
     }
+
+  if (!g_dataset_location_ht)
+    g_data_initialize ();
   
   g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
 }
@@ -352,7 +355,7 @@ g_datalist_id_remove_no_notify (GData       **datalist,
 {
   g_return_if_fail (datalist != NULL);
 
-  if (key_id)
+  if (key_id && g_dataset_location_ht)
     g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
 }
 
@@ -407,14 +410,17 @@ g_dataset_foreach (gconstpointer    dataset_location,
   
   g_return_if_fail (dataset_location != NULL);
   g_return_if_fail (func != NULL);
-  
-  dataset = g_dataset_lookup (dataset_location);
-  if (dataset)
+
+  if (g_dataset_location_ht)
     {
-      register GData *list;
-      
-      for (list = dataset->datalist; list; list = list->next)
-       func (list->id, list->data, user_data);
+      dataset = g_dataset_lookup (dataset_location);
+      if (dataset)
+       {
+         register GData *list;
+         
+         for (list = dataset->datalist; list; list = list->next)
+           func (list->id, list->data, user_data);
+       }
     }
 }
 
@@ -443,22 +449,20 @@ g_datalist_init (GData **datalist)
 static void
 g_data_initialize (void)
 {
-  if (!g_dataset_location_ht)
-    {
-      g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
-      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);
-    }
+  g_return_if_fail (g_dataset_location_ht == NULL);
+
+  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
@@ -479,10 +483,14 @@ g_quark_from_string (const gchar *string)
   
   g_return_val_if_fail (string != NULL, 0);
   
-  if (!g_quark_ht)
-    g_data_initialize ();
+  if (g_quark_ht)
+    quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
+  else
+    {
+      g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
+      quark = 0;
+    }
   
-  quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
   if (!quark)
     quark = g_quark_new (g_strdup (string));
   
@@ -496,12 +504,16 @@ g_quark_from_static_string (const gchar *string)
   
   g_return_val_if_fail (string != NULL, 0);
   
-  if (!g_quark_ht)
-    g_data_initialize ();
-  
-  quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
+  if (g_quark_ht)
+    quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
+  else
+    {
+      g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
+      quark = 0;
+    }
+
   if (!quark)
-    quark = g_quark_new (string);
+    quark = g_quark_new ((gchar*) string);
   
   return quark;
 }
@@ -516,19 +528,17 @@ g_quark_to_string (GQuark quark)
 }
 
 static inline GQuark
-g_quark_new (const gchar *string)
+g_quark_new (gchar *string)
 {
   GQuark quark;
   
   if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
-    g_quarks = g_realloc (g_quarks,
-                         (g_quark_seq_id + G_QUARK_BLOCK_SIZE) * sizeof (gchar*));
-  
+    g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
   
-  g_quarks[g_quark_seq_id] = (gchar*) string;
+  g_quarks[g_quark_seq_id] = string;
   g_quark_seq_id++;
   quark = g_quark_seq_id;
-  g_hash_table_insert (g_quark_ht, (gchar*) string, GUINT_TO_POINTER (quark));
+  g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
   
   return quark;
 }
diff --git a/glib.h b/glib.h
index 2e4982e..0442020 100644 (file)
--- a/glib.h
+++ b/glib.h
@@ -695,6 +695,7 @@ GUTILS_C_VAR const guint glib_binary_age;
 /* Forward declarations of glib types.
  */
 
+typedef struct _GAllocator     GAllocator;
 typedef struct _GArray         GArray;
 typedef struct _GByteArray     GByteArray;
 typedef struct _GCache         GCache;
@@ -705,7 +706,6 @@ typedef struct _GHashTable  GHashTable;
 typedef struct _GHook          GHook;
 typedef struct _GHookList      GHookList;
 typedef struct _GList          GList;
-typedef struct _GListAllocator GListAllocator;
 typedef struct _GMemChunk      GMemChunk;
 typedef struct _GNode          GNode;
 typedef struct _GPtrArray      GPtrArray;
@@ -865,6 +865,8 @@ struct _GDebugKey
 
 /* 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);
@@ -913,6 +915,8 @@ gpointer g_list_nth_data    (GList          *list,
 
 /* 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);
@@ -957,14 +961,6 @@ gpointer g_slist_nth_data  (GSList         *list,
 #define g_slist_next(slist)    ((slist) ? (((GSList *)(slist))->next) : NULL)
 
 
-/* List Allocators
- */
-GListAllocator* g_list_allocator_new  (void);
-void           g_list_allocator_free (GListAllocator* allocator);
-GListAllocator* g_slist_set_allocator (GListAllocator* allocator);
-GListAllocator* g_list_set_allocator  (GListAllocator* allocator);
-
-
 /* Hash tables
  */
 GHashTable* g_hash_table_new           (GHashFunc       hash_func,
@@ -1053,6 +1049,8 @@ struct _GNode
                                 ((GNode*) (node))->next == NULL)
 #define         G_NODE_IS_LEAF(node)   (((GNode*) (node))->children == NULL)
 
+void     g_node_push_allocator  (GAllocator       *allocator);
+void     g_node_pop_allocator   (void);
 GNode*  g_node_new             (gpointer          data);
 void    g_node_destroy         (GNode            *root);
 void    g_node_unlink          (GNode            *node);
@@ -1363,6 +1361,16 @@ void      g_free        (gpointer  mem);
 void    g_mem_profile (void);
 void    g_mem_check   (gpointer  mem);
 
+/* Generic allocators
+ */
+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)
+
 
 /* "g_mem_chunk_new" creates a new memory chunk.
  * Memory chunks are used to allocate pieces of memory which are
index c62a8cd..7dafc21 100644 (file)
@@ -57,19 +57,19 @@ static inline void  g_data_set_internal             (GData          **datalist,
                                                         GDestroyNotify   destroy_func,
                                                         GDataset        *dataset);
 static void            g_data_initialize               (void);
-static inline GQuark   g_quark_new                     (const gchar    *string);
+static inline GQuark   g_quark_new                     (gchar          *string);
 
 
 /* --- variables --- */
-static GHashTable   *g_quark_ht = NULL;
-static gchar       **g_quarks = NULL;
-static GQuark        g_quark_seq_id = 0;
 static GHashTable   *g_dataset_location_ht = NULL;
 static GDataset     *g_dataset_cached = NULL;
 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;
+static GHashTable   *g_quark_ht = NULL;
+static gchar       **g_quarks = NULL;
+static GQuark        g_quark_seq_id = 0;
 
 
 /* --- functions --- */
@@ -109,6 +109,9 @@ g_datalist_clear (GData **datalist)
 {
   g_return_if_fail (datalist != NULL);
   
+  if (!g_dataset_location_ht)
+    g_data_initialize ();
+
   while (*datalist)
     g_datalist_clear_i (datalist);
 }
@@ -174,9 +177,6 @@ g_data_set_internal (GData    **datalist,
 {
   register GData *list;
   
-  if (!g_dataset_location_ht)
-    g_data_initialize ();
-  
   list = *datalist;
   if (!data)
     {
@@ -201,7 +201,7 @@ g_data_set_internal (GData    **datalist,
                }
              
              /* the GData struct *must* already be unlinked
-              * when invoking the destroy function
+              * when invoking the destroy function.
               * we use (data==NULL && destroy_func!=NULL) as
               * a special hint combination to "steal"
               * data without destroy notification
@@ -326,6 +326,9 @@ g_datalist_id_set_data_full (GData    **datalist,
       else
        return;
     }
+
+  if (!g_dataset_location_ht)
+    g_data_initialize ();
   
   g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
 }
@@ -352,7 +355,7 @@ g_datalist_id_remove_no_notify (GData       **datalist,
 {
   g_return_if_fail (datalist != NULL);
 
-  if (key_id)
+  if (key_id && g_dataset_location_ht)
     g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
 }
 
@@ -407,14 +410,17 @@ g_dataset_foreach (gconstpointer    dataset_location,
   
   g_return_if_fail (dataset_location != NULL);
   g_return_if_fail (func != NULL);
-  
-  dataset = g_dataset_lookup (dataset_location);
-  if (dataset)
+
+  if (g_dataset_location_ht)
     {
-      register GData *list;
-      
-      for (list = dataset->datalist; list; list = list->next)
-       func (list->id, list->data, user_data);
+      dataset = g_dataset_lookup (dataset_location);
+      if (dataset)
+       {
+         register GData *list;
+         
+         for (list = dataset->datalist; list; list = list->next)
+           func (list->id, list->data, user_data);
+       }
     }
 }
 
@@ -443,22 +449,20 @@ g_datalist_init (GData **datalist)
 static void
 g_data_initialize (void)
 {
-  if (!g_dataset_location_ht)
-    {
-      g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
-      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);
-    }
+  g_return_if_fail (g_dataset_location_ht == NULL);
+
+  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
@@ -479,10 +483,14 @@ g_quark_from_string (const gchar *string)
   
   g_return_val_if_fail (string != NULL, 0);
   
-  if (!g_quark_ht)
-    g_data_initialize ();
+  if (g_quark_ht)
+    quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
+  else
+    {
+      g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
+      quark = 0;
+    }
   
-  quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
   if (!quark)
     quark = g_quark_new (g_strdup (string));
   
@@ -496,12 +504,16 @@ g_quark_from_static_string (const gchar *string)
   
   g_return_val_if_fail (string != NULL, 0);
   
-  if (!g_quark_ht)
-    g_data_initialize ();
-  
-  quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
+  if (g_quark_ht)
+    quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
+  else
+    {
+      g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
+      quark = 0;
+    }
+
   if (!quark)
-    quark = g_quark_new (string);
+    quark = g_quark_new ((gchar*) string);
   
   return quark;
 }
@@ -516,19 +528,17 @@ g_quark_to_string (GQuark quark)
 }
 
 static inline GQuark
-g_quark_new (const gchar *string)
+g_quark_new (gchar *string)
 {
   GQuark quark;
   
   if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
-    g_quarks = g_realloc (g_quarks,
-                         (g_quark_seq_id + G_QUARK_BLOCK_SIZE) * sizeof (gchar*));
-  
+    g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
   
-  g_quarks[g_quark_seq_id] = (gchar*) string;
+  g_quarks[g_quark_seq_id] = string;
   g_quark_seq_id++;
   quark = g_quark_seq_id;
-  g_hash_table_insert (g_quark_ht, (gchar*) string, GUINT_TO_POINTER (quark));
+  g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
   
   return quark;
 }
index 2e4982e..0442020 100644 (file)
@@ -695,6 +695,7 @@ GUTILS_C_VAR const guint glib_binary_age;
 /* Forward declarations of glib types.
  */
 
+typedef struct _GAllocator     GAllocator;
 typedef struct _GArray         GArray;
 typedef struct _GByteArray     GByteArray;
 typedef struct _GCache         GCache;
@@ -705,7 +706,6 @@ typedef struct _GHashTable  GHashTable;
 typedef struct _GHook          GHook;
 typedef struct _GHookList      GHookList;
 typedef struct _GList          GList;
-typedef struct _GListAllocator GListAllocator;
 typedef struct _GMemChunk      GMemChunk;
 typedef struct _GNode          GNode;
 typedef struct _GPtrArray      GPtrArray;
@@ -865,6 +865,8 @@ struct _GDebugKey
 
 /* 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);
@@ -913,6 +915,8 @@ gpointer g_list_nth_data    (GList          *list,
 
 /* 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);
@@ -957,14 +961,6 @@ gpointer g_slist_nth_data  (GSList         *list,
 #define g_slist_next(slist)    ((slist) ? (((GSList *)(slist))->next) : NULL)
 
 
-/* List Allocators
- */
-GListAllocator* g_list_allocator_new  (void);
-void           g_list_allocator_free (GListAllocator* allocator);
-GListAllocator* g_slist_set_allocator (GListAllocator* allocator);
-GListAllocator* g_list_set_allocator  (GListAllocator* allocator);
-
-
 /* Hash tables
  */
 GHashTable* g_hash_table_new           (GHashFunc       hash_func,
@@ -1053,6 +1049,8 @@ struct _GNode
                                 ((GNode*) (node))->next == NULL)
 #define         G_NODE_IS_LEAF(node)   (((GNode*) (node))->children == NULL)
 
+void     g_node_push_allocator  (GAllocator       *allocator);
+void     g_node_pop_allocator   (void);
 GNode*  g_node_new             (gpointer          data);
 void    g_node_destroy         (GNode            *root);
 void    g_node_unlink          (GNode            *node);
@@ -1363,6 +1361,16 @@ void      g_free        (gpointer  mem);
 void    g_mem_profile (void);
 void    g_mem_check   (gpointer  mem);
 
+/* Generic allocators
+ */
+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)
+
 
 /* "g_mem_chunk_new" creates a new memory chunk.
  * Memory chunks are used to allocate pieces of memory which are
index ee9ad69..ab69826 100644 (file)
 #include "glib.h"
 
 
-typedef struct _GRealListAllocator GRealListAllocator;
-
-struct _GRealListAllocator
+struct _GAllocator /* from gmem.c */
 {
-  GMemChunk *list_mem_chunk;
-  GList            *free_list;
+  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;
 
-static GRealListAllocator *default_allocator = NULL;
-static GRealListAllocator *current_allocator = NULL;
+void
+g_list_push_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;
+       }
+    }
 
-GListAllocator*
-g_list_allocator_new (void)
-{
-  GRealListAllocator* allocator = g_new (GRealListAllocator, 1);
-  
-  allocator->list_mem_chunk = NULL;
-  allocator->free_list = NULL;
-  
-  return (GListAllocator*) allocator;
-}
+  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;
+    }
 
-void
-g_list_allocator_free (GListAllocator* fallocator)
-{
-  GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
-  
-  if (allocator && allocator->list_mem_chunk)
-    g_mem_chunk_destroy (allocator->list_mem_chunk);
-  if (allocator)
-    g_free (allocator);
+  allocator->is_unused = FALSE;
+  allocator->last = current_allocator;
+  current_allocator = allocator;
 }
 
-GListAllocator*
-g_list_set_allocator (GListAllocator* fallocator)
+void
+g_list_pop_allocator (void)
 {
-  GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
-  GRealListAllocator* old_allocator = current_allocator;
-  
-  if (allocator)
-    current_allocator = allocator;
-  else
+  if (current_allocator)
     {
-      if (!default_allocator)
-       default_allocator = (GRealListAllocator*) g_list_allocator_new ();
-      current_allocator = default_allocator;
+      GAllocator *allocator;
+
+      allocator = current_allocator;
+      current_allocator = allocator->last;
+      allocator->last = NULL;
+      allocator->is_unused = TRUE;
     }
-  
-  if (!current_allocator->list_mem_chunk)
-    current_allocator->list_mem_chunk = g_mem_chunk_new ("list mem chunk",
-                                                        sizeof (GList),
-                                                        1024,
-                                                        G_ALLOC_ONLY);
-  
-  return (GListAllocator*) (old_allocator == default_allocator ? NULL : old_allocator);
 }
 
-
 GList*
 g_list_alloc (void)
 {
-  GList *new_list;
-  
-  g_list_set_allocator (NULL);
-  if (current_allocator->free_list)
+  GList *list;
+
+  if (!current_allocator)
+    g_list_push_allocator (g_allocator_new ("GLib default GList allocator", 1024));
+
+  if (!current_allocator->free_lists)
     {
-      new_list = current_allocator->free_list;
-      current_allocator->free_list = current_allocator->free_list->next;
+      list = g_chunk_new (GList, current_allocator->mem_chunk);
+      list->data = NULL;
     }
   else
     {
-      new_list = g_chunk_new (GList, current_allocator->list_mem_chunk);
+      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;
+       }
     }
+  list->next = NULL;
+  list->prev = NULL;
   
-  new_list->data = NULL;
-  new_list->next = NULL;
-  new_list->prev = NULL;
-  
-  return new_list;
+  return list;
 }
 
 void
 g_list_free (GList *list)
 {
-  GList *last;
-
   if (list)
     {
-      last = g_list_last (list);
-      last->next = current_allocator->free_list;
-      current_allocator->free_list = list;
+      list->data = list->next;
+      list->next = current_allocator->free_lists;
+      current_allocator->free_lists = list;
     }
 }
 
@@ -120,8 +125,9 @@ g_list_free_1 (GList *list)
 {
   if (list)
     {
-      list->next = current_allocator->free_list;
-      current_allocator->free_list = list;
+      list->data = NULL;
+      list->next = current_allocator->free_lists;
+      current_allocator->free_lists = list;
     }
 }
 
index cd7f47e..c29ee66 100644 (file)
@@ -894,3 +894,49 @@ g_mem_chunk_area_search (GMemArea *a,
     }
   return -1;
 }
+
+/* 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;
+}
+
+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);
+}
index dea428d..9f6e544 100644 (file)
  */
 #include "glib.h"
 
+/* 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 */
+};
+
+static GAllocator *current_allocator = NULL;
+
+void
+g_node_push_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;
+       }
+    }
 
-#define        KEEP_NODES      (1024)
+  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;
+  allocator->last = current_allocator;
+  current_allocator = allocator;
+}
+
+void
+g_node_pop_allocator (void)
+{
+  if (current_allocator)
+    {
+      GAllocator *allocator;
 
-/* --- variables --- */
-static GMemChunk       *g_tree_node_chunk = NULL;
-static GNode           *free_nodes = NULL;
-static guint           n_free_nodes = 0;
+      allocator = current_allocator;
+      current_allocator = allocator->last;
+      allocator->last = NULL;
+      allocator->is_unused = TRUE;
+    }
+}
 
 
 /* --- functions --- */
 GNode*
 g_node_new (gpointer data)
 {
-  register GNode *node;
-  
-  if (!g_tree_node_chunk)
-    g_tree_node_chunk = g_mem_chunk_create (GNode, 1024, G_ALLOC_AND_FREE);
-  
-  if (n_free_nodes)
+  GNode *node;
+
+  if (!current_allocator)
+    g_node_push_allocator (g_allocator_new ("GLib default GNode allocator", 1024));
+
+  if (!current_allocator->free_nodes)
+    node = g_chunk_new (GNode, current_allocator->mem_chunk);
+  else
     {
-      node = free_nodes;
-      free_nodes = free_nodes->next;
-      n_free_nodes--;
+      node = current_allocator->free_nodes;
+      current_allocator->free_nodes = node->next;
     }
-  else
-    node = g_chunk_new (GNode, g_tree_node_chunk);
   
   node->data = data;
   node->next = NULL;
@@ -59,29 +108,23 @@ g_node_new (gpointer data)
 }
 
 static void
-g_node_free (GNode *parent)
+g_nodes_free (GNode *node)
 {
-  GNode *node;
+  GNode *parent;
 
-  node = parent->children;
-  
-  while (node)
+  parent = node;
+  while (1)
     {
-      register GNode *free_node;
-
-      free_node = node;
-      node = free_node->next;
-      g_node_free (free_node);
+      if (parent->children)
+       g_nodes_free (parent->children);
+      if (parent->next)
+       parent = parent->next;
+      else
+       break;
     }
 
-  if (n_free_nodes < KEEP_NODES)
-    {
-      parent->next = free_nodes;
-      free_nodes = parent;
-      n_free_nodes++;
-    }
-  else
-    g_chunk_free (parent, g_tree_node_chunk);
+  parent->next = current_allocator->free_nodes;
+  current_allocator->free_nodes = node;
 }
 
 void
@@ -92,7 +135,7 @@ g_node_destroy (GNode *root)
   if (!G_NODE_IS_ROOT (root))
     g_node_unlink (root);
   
-  g_node_free (root);
+  g_nodes_free (root);
 }
 
 void
index 6a76d22..4efe2a5 100644 (file)
 #include "glib.h"
 
 
-typedef struct _GRealListAllocator GRealListAllocator;
-
-struct _GRealListAllocator
+struct _GAllocator /* from gmem.c */
 {
-  GMemChunk *list_mem_chunk;
-  GSList    *free_list;
+  gchar         *name;
+  guint16        n_preallocs;
+  guint          is_unused : 1;
+  guint          type : 4;
+  GAllocator    *last;
+  GMemChunk     *mem_chunk;
+  GSList        *free_lists; /* implementation specific */
 };
 
+static GAllocator       *current_allocator = NULL;
 
-static GRealListAllocator *default_allocator = NULL;
-static GRealListAllocator *current_allocator = NULL;
-
-GListAllocator*
-g_slist_set_allocator (GListAllocator* fallocator)
+void
+g_slist_push_allocator (GAllocator *allocator)
 {
-  GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
-  GRealListAllocator* old_allocator = current_allocator;
+  g_return_if_fail (allocator != NULL);
+  g_return_if_fail (allocator->is_unused == TRUE);
 
-  if (allocator)
-    current_allocator = allocator;
-  else
+  if (allocator->type != G_ALLOCATOR_SLIST)
     {
-      if (!default_allocator)
-       default_allocator = (GRealListAllocator*) g_list_allocator_new ();
-      current_allocator = default_allocator;
+      allocator->type = G_ALLOCATOR_SLIST;
+      if (allocator->mem_chunk)
+       {
+         g_mem_chunk_destroy (allocator->mem_chunk);
+         allocator->mem_chunk = NULL;
+       }
     }
 
-  if (!current_allocator->list_mem_chunk)
-    current_allocator->list_mem_chunk = g_mem_chunk_new ("slist mem chunk",
-                                                        sizeof (GSList),
-                                                        1024,
-                                                        G_ALLOC_ONLY);
+  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;
+    }
 
-  return (GListAllocator*) (old_allocator == default_allocator ? NULL : old_allocator);
+  allocator->is_unused = FALSE;
+  allocator->last = current_allocator;
+  current_allocator = allocator;
 }
 
+void
+g_slist_pop_allocator (void)
+{
+  if (current_allocator)
+    {
+      GAllocator *allocator;
+
+      allocator = current_allocator;
+      current_allocator = allocator->last;
+      allocator->last = NULL;
+      allocator->is_unused = TRUE;
+    }
+}
 
 GSList*
 g_slist_alloc (void)
 {
-  GSList *new_list;
+  GSList *list;
+
+  if (!current_allocator)
+    g_slist_push_allocator (g_allocator_new ("GLib default GSList allocator", 1024));
 
-  g_slist_set_allocator (NULL);
-  if (current_allocator->free_list)
+  if (!current_allocator->free_lists)
     {
-      new_list = current_allocator->free_list;
-      current_allocator->free_list = current_allocator->free_list->next;
+      list = g_chunk_new (GSList, current_allocator->mem_chunk);
+      list->data = NULL;
     }
   else
     {
-      new_list = g_chunk_new (GSList, current_allocator->list_mem_chunk);
+      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;
+       }
     }
+  list->next = NULL;
 
-  new_list->data = NULL;
-  new_list->next = NULL;
-
-  return new_list;
+  return list;
 }
 
 void
 g_slist_free (GSList *list)
 {
-  GSList *last;
-
   if (list)
     {
-      last = g_slist_last (list);
-      last->next = current_allocator->free_list;
-      current_allocator->free_list = list;
+      list->data = list->next;
+      list->next = current_allocator->free_lists;
+      current_allocator->free_lists = list;
     }
 }
 
@@ -96,8 +124,9 @@ g_slist_free_1 (GSList *list)
 {
   if (list)
     {
-      list->next = current_allocator->free_list;
-      current_allocator->free_list = list;
+      list->data = NULL;
+      list->next = current_allocator->free_lists;
+      current_allocator->free_lists = list;
     }
 }
 
index 39e43e2..fa84fe7 100644 (file)
@@ -106,14 +106,10 @@ g_string_chunk_free (GStringChunk *fchunk)
 
   if (chunk->storage_list)
     {
-      GListAllocator *tmp_allocator = g_slist_set_allocator (NULL);
-
       for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
        g_free (tmp_list->data);
 
       g_slist_free (chunk->storage_list);
-
-      g_slist_set_allocator (tmp_allocator);
     }
 
   if (chunk->const_table)
@@ -134,7 +130,6 @@ g_string_chunk_insert (GStringChunk *fchunk,
 
   if ((chunk->storage_next + len + 1) > chunk->this_size)
     {
-      GListAllocator *tmp_allocator = g_slist_set_allocator (NULL);
       gint new_size = chunk->default_size;
 
       while (new_size < len+1)
@@ -145,8 +140,6 @@ g_string_chunk_insert (GStringChunk *fchunk,
 
       chunk->this_size = new_size;
       chunk->storage_next = 0;
-
-      g_slist_set_allocator (tmp_allocator);
     }
 
   pos = ((char*)chunk->storage_list->data) + chunk->storage_next;
index 0d7f78c..4d9e98a 100644 (file)
@@ -79,7 +79,51 @@ static void       g_tree_node_check                 (GTreeNode      *node);
 
 
 static GMemChunk *node_mem_chunk = NULL;
-static GSList *node_free_list = NULL;
+static GTreeNode *node_free_list = NULL;
+
+
+static GTreeNode*
+g_tree_node_new (gpointer key,
+                gpointer value)
+{
+  GTreeNode *node;
+
+  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);
+    }
+
+  node->balance = 0;
+  node->left = NULL;
+  node->right = NULL;
+  node->key = key;
+  node->value = value;
+
+  return node;
+}
+
+static void
+g_tree_node_destroy (GTreeNode *node)
+{
+  if (node)
+    {
+      g_tree_node_destroy (node->right);
+      g_tree_node_destroy (node->left);
+      node->right = node_free_list;
+      node_free_list = node;
+    }
+}
 
 
 GTree*
@@ -230,55 +274,6 @@ g_tree_nnodes (GTree *tree)
   return 0;
 }
 
-
-static GTreeNode*
-g_tree_node_new (gpointer key,
-                gpointer value)
-{
-  GTreeNode *node;
-  GSList *tmp_list;
-
-  if (node_free_list)
-    {
-      tmp_list = node_free_list;
-      node_free_list = node_free_list->next;
-
-      node = tmp_list->data;
-
-      {
-       GListAllocator *tmp_allocator = g_list_set_allocator (NULL);
-       g_slist_free_1 (tmp_list);
-       g_list_set_allocator (tmp_allocator);
-      }
-    }
-  else
-    {
-      if (!node_mem_chunk)
-       node_mem_chunk = g_mem_chunk_new ("tree node mem chunk", sizeof (GTreeNode), 1024, G_ALLOC_ONLY);
-
-      node = g_chunk_new (GTreeNode, node_mem_chunk);
-    }
-
-  node->balance = 0;
-  node->left = NULL;
-  node->right = NULL;
-  node->key = key;
-  node->value = value;
-
-  return node;
-}
-
-static void
-g_tree_node_destroy (GTreeNode *node)
-{
-  if (node)
-    {
-      node_free_list = g_slist_prepend (node_free_list, node);
-      g_tree_node_destroy (node->right);
-      g_tree_node_destroy (node->left);
-    }
-}
-
 static GTreeNode*
 g_tree_node_insert (GTreeNode    *node,
                    GCompareFunc  compare,
@@ -352,7 +347,6 @@ g_tree_node_remove (GTreeNode    *node,
                    GCompareFunc  compare,
                    gpointer      key)
 {
-  GTreeNode *garbage;
   GTreeNode *new_root;
   gint old_balance;
   gint cmp;
@@ -363,6 +357,8 @@ g_tree_node_remove (GTreeNode    *node,
   cmp = (* compare) (key, node->key);
   if (cmp == 0)
     {
+      GTreeNode *garbage;
+
       garbage = node;
 
       if (!node->right)
@@ -379,7 +375,8 @@ g_tree_node_remove (GTreeNode    *node,
          node = g_tree_node_restore_right_balance (new_root, old_balance);
        }
 
-      node_free_list = g_slist_prepend (node_free_list, garbage);
+      garbage->right = node_free_list;
+      node_free_list = garbage;
     }
   else if (cmp < 0)
     {
diff --git a/glist.c b/glist.c
index ee9ad69..ab69826 100644 (file)
--- a/glist.c
+++ b/glist.c
 #include "glib.h"
 
 
-typedef struct _GRealListAllocator GRealListAllocator;
-
-struct _GRealListAllocator
+struct _GAllocator /* from gmem.c */
 {
-  GMemChunk *list_mem_chunk;
-  GList            *free_list;
+  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;
 
-static GRealListAllocator *default_allocator = NULL;
-static GRealListAllocator *current_allocator = NULL;
+void
+g_list_push_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;
+       }
+    }
 
-GListAllocator*
-g_list_allocator_new (void)
-{
-  GRealListAllocator* allocator = g_new (GRealListAllocator, 1);
-  
-  allocator->list_mem_chunk = NULL;
-  allocator->free_list = NULL;
-  
-  return (GListAllocator*) allocator;
-}
+  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;
+    }
 
-void
-g_list_allocator_free (GListAllocator* fallocator)
-{
-  GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
-  
-  if (allocator && allocator->list_mem_chunk)
-    g_mem_chunk_destroy (allocator->list_mem_chunk);
-  if (allocator)
-    g_free (allocator);
+  allocator->is_unused = FALSE;
+  allocator->last = current_allocator;
+  current_allocator = allocator;
 }
 
-GListAllocator*
-g_list_set_allocator (GListAllocator* fallocator)
+void
+g_list_pop_allocator (void)
 {
-  GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
-  GRealListAllocator* old_allocator = current_allocator;
-  
-  if (allocator)
-    current_allocator = allocator;
-  else
+  if (current_allocator)
     {
-      if (!default_allocator)
-       default_allocator = (GRealListAllocator*) g_list_allocator_new ();
-      current_allocator = default_allocator;
+      GAllocator *allocator;
+
+      allocator = current_allocator;
+      current_allocator = allocator->last;
+      allocator->last = NULL;
+      allocator->is_unused = TRUE;
     }
-  
-  if (!current_allocator->list_mem_chunk)
-    current_allocator->list_mem_chunk = g_mem_chunk_new ("list mem chunk",
-                                                        sizeof (GList),
-                                                        1024,
-                                                        G_ALLOC_ONLY);
-  
-  return (GListAllocator*) (old_allocator == default_allocator ? NULL : old_allocator);
 }
 
-
 GList*
 g_list_alloc (void)
 {
-  GList *new_list;
-  
-  g_list_set_allocator (NULL);
-  if (current_allocator->free_list)
+  GList *list;
+
+  if (!current_allocator)
+    g_list_push_allocator (g_allocator_new ("GLib default GList allocator", 1024));
+
+  if (!current_allocator->free_lists)
     {
-      new_list = current_allocator->free_list;
-      current_allocator->free_list = current_allocator->free_list->next;
+      list = g_chunk_new (GList, current_allocator->mem_chunk);
+      list->data = NULL;
     }
   else
     {
-      new_list = g_chunk_new (GList, current_allocator->list_mem_chunk);
+      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;
+       }
     }
+  list->next = NULL;
+  list->prev = NULL;
   
-  new_list->data = NULL;
-  new_list->next = NULL;
-  new_list->prev = NULL;
-  
-  return new_list;
+  return list;
 }
 
 void
 g_list_free (GList *list)
 {
-  GList *last;
-
   if (list)
     {
-      last = g_list_last (list);
-      last->next = current_allocator->free_list;
-      current_allocator->free_list = list;
+      list->data = list->next;
+      list->next = current_allocator->free_lists;
+      current_allocator->free_lists = list;
     }
 }
 
@@ -120,8 +125,9 @@ g_list_free_1 (GList *list)
 {
   if (list)
     {
-      list->next = current_allocator->free_list;
-      current_allocator->free_list = list;
+      list->data = NULL;
+      list->next = current_allocator->free_lists;
+      current_allocator->free_lists = list;
     }
 }
 
diff --git a/gmem.c b/gmem.c
index cd7f47e..c29ee66 100644 (file)
--- a/gmem.c
+++ b/gmem.c
@@ -894,3 +894,49 @@ g_mem_chunk_area_search (GMemArea *a,
     }
   return -1;
 }
+
+/* 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;
+}
+
+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);
+}
diff --git a/gnode.c b/gnode.c
index dea428d..9f6e544 100644 (file)
--- a/gnode.c
+++ b/gnode.c
  */
 #include "glib.h"
 
+/* 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 */
+};
+
+static GAllocator *current_allocator = NULL;
+
+void
+g_node_push_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;
+       }
+    }
 
-#define        KEEP_NODES      (1024)
+  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;
+  allocator->last = current_allocator;
+  current_allocator = allocator;
+}
+
+void
+g_node_pop_allocator (void)
+{
+  if (current_allocator)
+    {
+      GAllocator *allocator;
 
-/* --- variables --- */
-static GMemChunk       *g_tree_node_chunk = NULL;
-static GNode           *free_nodes = NULL;
-static guint           n_free_nodes = 0;
+      allocator = current_allocator;
+      current_allocator = allocator->last;
+      allocator->last = NULL;
+      allocator->is_unused = TRUE;
+    }
+}
 
 
 /* --- functions --- */
 GNode*
 g_node_new (gpointer data)
 {
-  register GNode *node;
-  
-  if (!g_tree_node_chunk)
-    g_tree_node_chunk = g_mem_chunk_create (GNode, 1024, G_ALLOC_AND_FREE);
-  
-  if (n_free_nodes)
+  GNode *node;
+
+  if (!current_allocator)
+    g_node_push_allocator (g_allocator_new ("GLib default GNode allocator", 1024));
+
+  if (!current_allocator->free_nodes)
+    node = g_chunk_new (GNode, current_allocator->mem_chunk);
+  else
     {
-      node = free_nodes;
-      free_nodes = free_nodes->next;
-      n_free_nodes--;
+      node = current_allocator->free_nodes;
+      current_allocator->free_nodes = node->next;
     }
-  else
-    node = g_chunk_new (GNode, g_tree_node_chunk);
   
   node->data = data;
   node->next = NULL;
@@ -59,29 +108,23 @@ g_node_new (gpointer data)
 }
 
 static void
-g_node_free (GNode *parent)
+g_nodes_free (GNode *node)
 {
-  GNode *node;
+  GNode *parent;
 
-  node = parent->children;
-  
-  while (node)
+  parent = node;
+  while (1)
     {
-      register GNode *free_node;
-
-      free_node = node;
-      node = free_node->next;
-      g_node_free (free_node);
+      if (parent->children)
+       g_nodes_free (parent->children);
+      if (parent->next)
+       parent = parent->next;
+      else
+       break;
     }
 
-  if (n_free_nodes < KEEP_NODES)
-    {
-      parent->next = free_nodes;
-      free_nodes = parent;
-      n_free_nodes++;
-    }
-  else
-    g_chunk_free (parent, g_tree_node_chunk);
+  parent->next = current_allocator->free_nodes;
+  current_allocator->free_nodes = node;
 }
 
 void
@@ -92,7 +135,7 @@ g_node_destroy (GNode *root)
   if (!G_NODE_IS_ROOT (root))
     g_node_unlink (root);
   
-  g_node_free (root);
+  g_nodes_free (root);
 }
 
 void
index 6a76d22..4efe2a5 100644 (file)
--- a/gslist.c
+++ b/gslist.c
 #include "glib.h"
 
 
-typedef struct _GRealListAllocator GRealListAllocator;
-
-struct _GRealListAllocator
+struct _GAllocator /* from gmem.c */
 {
-  GMemChunk *list_mem_chunk;
-  GSList    *free_list;
+  gchar         *name;
+  guint16        n_preallocs;
+  guint          is_unused : 1;
+  guint          type : 4;
+  GAllocator    *last;
+  GMemChunk     *mem_chunk;
+  GSList        *free_lists; /* implementation specific */
 };
 
+static GAllocator       *current_allocator = NULL;
 
-static GRealListAllocator *default_allocator = NULL;
-static GRealListAllocator *current_allocator = NULL;
-
-GListAllocator*
-g_slist_set_allocator (GListAllocator* fallocator)
+void
+g_slist_push_allocator (GAllocator *allocator)
 {
-  GRealListAllocator* allocator = (GRealListAllocator *) fallocator;
-  GRealListAllocator* old_allocator = current_allocator;
+  g_return_if_fail (allocator != NULL);
+  g_return_if_fail (allocator->is_unused == TRUE);
 
-  if (allocator)
-    current_allocator = allocator;
-  else
+  if (allocator->type != G_ALLOCATOR_SLIST)
     {
-      if (!default_allocator)
-       default_allocator = (GRealListAllocator*) g_list_allocator_new ();
-      current_allocator = default_allocator;
+      allocator->type = G_ALLOCATOR_SLIST;
+      if (allocator->mem_chunk)
+       {
+         g_mem_chunk_destroy (allocator->mem_chunk);
+         allocator->mem_chunk = NULL;
+       }
     }
 
-  if (!current_allocator->list_mem_chunk)
-    current_allocator->list_mem_chunk = g_mem_chunk_new ("slist mem chunk",
-                                                        sizeof (GSList),
-                                                        1024,
-                                                        G_ALLOC_ONLY);
+  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;
+    }
 
-  return (GListAllocator*) (old_allocator == default_allocator ? NULL : old_allocator);
+  allocator->is_unused = FALSE;
+  allocator->last = current_allocator;
+  current_allocator = allocator;
 }
 
+void
+g_slist_pop_allocator (void)
+{
+  if (current_allocator)
+    {
+      GAllocator *allocator;
+
+      allocator = current_allocator;
+      current_allocator = allocator->last;
+      allocator->last = NULL;
+      allocator->is_unused = TRUE;
+    }
+}
 
 GSList*
 g_slist_alloc (void)
 {
-  GSList *new_list;
+  GSList *list;
+
+  if (!current_allocator)
+    g_slist_push_allocator (g_allocator_new ("GLib default GSList allocator", 1024));
 
-  g_slist_set_allocator (NULL);
-  if (current_allocator->free_list)
+  if (!current_allocator->free_lists)
     {
-      new_list = current_allocator->free_list;
-      current_allocator->free_list = current_allocator->free_list->next;
+      list = g_chunk_new (GSList, current_allocator->mem_chunk);
+      list->data = NULL;
     }
   else
     {
-      new_list = g_chunk_new (GSList, current_allocator->list_mem_chunk);
+      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;
+       }
     }
+  list->next = NULL;
 
-  new_list->data = NULL;
-  new_list->next = NULL;
-
-  return new_list;
+  return list;
 }
 
 void
 g_slist_free (GSList *list)
 {
-  GSList *last;
-
   if (list)
     {
-      last = g_slist_last (list);
-      last->next = current_allocator->free_list;
-      current_allocator->free_list = list;
+      list->data = list->next;
+      list->next = current_allocator->free_lists;
+      current_allocator->free_lists = list;
     }
 }
 
@@ -96,8 +124,9 @@ g_slist_free_1 (GSList *list)
 {
   if (list)
     {
-      list->next = current_allocator->free_list;
-      current_allocator->free_list = list;
+      list->data = NULL;
+      list->next = current_allocator->free_lists;
+      current_allocator->free_lists = list;
     }
 }
 
index 39e43e2..fa84fe7 100644 (file)
--- a/gstring.c
+++ b/gstring.c
@@ -106,14 +106,10 @@ g_string_chunk_free (GStringChunk *fchunk)
 
   if (chunk->storage_list)
     {
-      GListAllocator *tmp_allocator = g_slist_set_allocator (NULL);
-
       for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
        g_free (tmp_list->data);
 
       g_slist_free (chunk->storage_list);
-
-      g_slist_set_allocator (tmp_allocator);
     }
 
   if (chunk->const_table)
@@ -134,7 +130,6 @@ g_string_chunk_insert (GStringChunk *fchunk,
 
   if ((chunk->storage_next + len + 1) > chunk->this_size)
     {
-      GListAllocator *tmp_allocator = g_slist_set_allocator (NULL);
       gint new_size = chunk->default_size;
 
       while (new_size < len+1)
@@ -145,8 +140,6 @@ g_string_chunk_insert (GStringChunk *fchunk,
 
       chunk->this_size = new_size;
       chunk->storage_next = 0;
-
-      g_slist_set_allocator (tmp_allocator);
     }
 
   pos = ((char*)chunk->storage_list->data) + chunk->storage_next;
diff --git a/gtree.c b/gtree.c
index 0d7f78c..4d9e98a 100644 (file)
--- a/gtree.c
+++ b/gtree.c
@@ -79,7 +79,51 @@ static void       g_tree_node_check                 (GTreeNode      *node);
 
 
 static GMemChunk *node_mem_chunk = NULL;
-static GSList *node_free_list = NULL;
+static GTreeNode *node_free_list = NULL;
+
+
+static GTreeNode*
+g_tree_node_new (gpointer key,
+                gpointer value)
+{
+  GTreeNode *node;
+
+  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);
+    }
+
+  node->balance = 0;
+  node->left = NULL;
+  node->right = NULL;
+  node->key = key;
+  node->value = value;
+
+  return node;
+}
+
+static void
+g_tree_node_destroy (GTreeNode *node)
+{
+  if (node)
+    {
+      g_tree_node_destroy (node->right);
+      g_tree_node_destroy (node->left);
+      node->right = node_free_list;
+      node_free_list = node;
+    }
+}
 
 
 GTree*
@@ -230,55 +274,6 @@ g_tree_nnodes (GTree *tree)
   return 0;
 }
 
-
-static GTreeNode*
-g_tree_node_new (gpointer key,
-                gpointer value)
-{
-  GTreeNode *node;
-  GSList *tmp_list;
-
-  if (node_free_list)
-    {
-      tmp_list = node_free_list;
-      node_free_list = node_free_list->next;
-
-      node = tmp_list->data;
-
-      {
-       GListAllocator *tmp_allocator = g_list_set_allocator (NULL);
-       g_slist_free_1 (tmp_list);
-       g_list_set_allocator (tmp_allocator);
-      }
-    }
-  else
-    {
-      if (!node_mem_chunk)
-       node_mem_chunk = g_mem_chunk_new ("tree node mem chunk", sizeof (GTreeNode), 1024, G_ALLOC_ONLY);
-
-      node = g_chunk_new (GTreeNode, node_mem_chunk);
-    }
-
-  node->balance = 0;
-  node->left = NULL;
-  node->right = NULL;
-  node->key = key;
-  node->value = value;
-
-  return node;
-}
-
-static void
-g_tree_node_destroy (GTreeNode *node)
-{
-  if (node)
-    {
-      node_free_list = g_slist_prepend (node_free_list, node);
-      g_tree_node_destroy (node->right);
-      g_tree_node_destroy (node->left);
-    }
-}
-
 static GTreeNode*
 g_tree_node_insert (GTreeNode    *node,
                    GCompareFunc  compare,
@@ -352,7 +347,6 @@ g_tree_node_remove (GTreeNode    *node,
                    GCompareFunc  compare,
                    gpointer      key)
 {
-  GTreeNode *garbage;
   GTreeNode *new_root;
   gint old_balance;
   gint cmp;
@@ -363,6 +357,8 @@ g_tree_node_remove (GTreeNode    *node,
   cmp = (* compare) (key, node->key);
   if (cmp == 0)
     {
+      GTreeNode *garbage;
+
       garbage = node;
 
       if (!node->right)
@@ -379,7 +375,8 @@ g_tree_node_remove (GTreeNode    *node,
          node = g_tree_node_restore_right_balance (new_root, old_balance);
        }
 
-      node_free_list = g_slist_prepend (node_free_list, garbage);
+      garbage->right = node_free_list;
+      node_free_list = garbage;
     }
   else if (cmp < 0)
     {