This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mono / utils / mono-hash.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* 
28  * MT safe
29  */
30
31 /*
32  * Imported in mono cvs from version 1.32 of gnome cvs.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include <glib.h>
40 #include <mono/os/gc_wrapper.h>
41 #include "mono-hash.h"
42
43 #define HASH_TABLE_MIN_SIZE 11
44 #define HASH_TABLE_MAX_SIZE 13845163
45
46
47 typedef struct _MonoGHashNode      MonoGHashNode;
48
49 struct _MonoGHashNode
50 {
51   gpointer   key;
52   gpointer   value;
53   MonoGHashNode *next;
54 };
55
56 struct _MonoGHashTable
57 {
58   gint             size;
59   gint             nnodes;
60   MonoGHashNode      **nodes;
61   GHashFunc        hash_func;
62   GEqualFunc       key_equal_func;
63   GDestroyNotify   key_destroy_func;
64   GDestroyNotify   value_destroy_func;
65 };
66
67 #define G_HASH_TABLE_RESIZE(hash_table)                         \
68    G_STMT_START {                                               \
69      if ((hash_table->size >= 3 * hash_table->nnodes &&         \
70           hash_table->size > HASH_TABLE_MIN_SIZE) ||            \
71          (3 * hash_table->size <= hash_table->nnodes &&         \
72           hash_table->size < HASH_TABLE_MAX_SIZE))              \
73            g_hash_table_resize (hash_table);                    \
74    } G_STMT_END
75
76 static void             g_hash_table_resize       (MonoGHashTable         *hash_table);
77 static MonoGHashNode**  g_hash_table_lookup_node  (MonoGHashTable     *hash_table,
78                                                    gconstpointer   key);
79 static MonoGHashNode*   g_hash_node_new           (gpointer        key,
80                                                    gpointer        value);
81 static void             g_hash_node_destroy       (MonoGHashNode          *hash_node,
82                                                    GDestroyNotify  key_destroy_func,
83                                                    GDestroyNotify  value_destroy_func);
84 static void             g_hash_nodes_destroy      (MonoGHashNode          *hash_node,
85                                                   GDestroyNotify   key_destroy_func,
86                                                   GDestroyNotify   value_destroy_func);
87 static guint g_hash_table_foreach_remove_or_steal (MonoGHashTable     *hash_table,
88                                                    GHRFunc         func,
89                                                    gpointer        user_data,
90                                                    gboolean        notify);
91
92
93 G_LOCK_DEFINE_STATIC (g_hash_global);
94
95 #if !HAVE_BOEHM_GC
96 static GMemChunk *node_mem_chunk = NULL;
97 #endif
98 static MonoGHashNode *node_free_list = NULL;
99
100 /**
101  * g_hash_table_new:
102  * @hash_func: a function to create a hash value from a key.
103  *   Hash values are used to determine where keys are stored within the
104  *   #GHashTable data structure. The g_direct_hash(), g_int_hash() and 
105  *   g_str_hash() functions are provided for some common types of keys. 
106  *   If hash_func is %NULL, g_direct_hash() is used.
107  * @key_equal_func: a function to check two keys for equality.  This is
108  *   used when looking up keys in the #GHashTable.  The g_direct_equal(),
109  *   g_int_equal() and g_str_equal() functions are provided for the most
110  *   common types of keys. If @key_equal_func is %NULL, keys are compared
111  *   directly in a similar fashion to g_direct_equal(), but without the
112  *   overhead of a function call.
113  *
114  * Creates a new #GHashTable.
115  * 
116  * Return value: a new #GHashTable.
117  **/
118 MonoGHashTable*
119 mono_g_hash_table_new (GHashFunc    hash_func,
120                   GEqualFunc   key_equal_func)
121 {
122   return mono_g_hash_table_new_full (hash_func, key_equal_func, NULL, NULL);
123 }
124
125
126 /**
127  * g_hash_table_new_full:
128  * @hash_func: a function to create a hash value from a key.
129  * @key_equal_func: a function to check two keys for equality.
130  * @key_destroy_func: a function to free the memory allocated for the key 
131  *   used when removing the entry from the #GHashTable or %NULL if you 
132  *   don't want to supply such a function.
133  * @value_destroy_func: a function to free the memory allocated for the 
134  *   value used when removing the entry from the #GHashTable or %NULL if 
135  *   you don't want to supply such a function.
136  * 
137  * Creates a new #GHashTable like g_hash_table_new() and allows to specify
138  * functions to free the memory allocated for the key and value that get 
139  * called when removing the entry from the #GHashTable.
140  * 
141  * Return value: a new #GHashTable.
142  **/
143 MonoGHashTable*
144 mono_g_hash_table_new_full (GHashFunc       hash_func,
145                        GEqualFunc      key_equal_func,
146                        GDestroyNotify  key_destroy_func,
147                        GDestroyNotify  value_destroy_func)
148 {
149   MonoGHashTable *hash_table;
150   
151 #if HAVE_BOEHM_GC
152   hash_table = GC_MALLOC (sizeof (MonoGHashTable));
153 #else
154   hash_table = g_new (MonoGHashTable, 1);
155 #endif
156   hash_table->size               = HASH_TABLE_MIN_SIZE;
157   hash_table->nnodes             = 0;
158   hash_table->hash_func          = hash_func ? hash_func : g_direct_hash;
159   hash_table->key_equal_func     = key_equal_func == g_direct_equal ? NULL : key_equal_func;
160   hash_table->key_destroy_func   = key_destroy_func;
161   hash_table->value_destroy_func = value_destroy_func;
162 #if HAVE_BOEHM_GC
163   hash_table->nodes              = GC_MALLOC (sizeof (MonoGHashNode*) * hash_table->size);
164 #else
165   hash_table->nodes              = g_new0 (MonoGHashNode*, hash_table->size);
166 #endif
167   
168   return hash_table;
169 }
170
171 /**
172  * g_hash_table_destroy:
173  * @hash_table: a #GHashTable.
174  * 
175  * Destroys the #GHashTable. If keys and/or values are dynamically 
176  * allocated, you should either free them first or create the #GHashTable
177  * using g_hash_table_new_full(). In the latter case the destroy functions 
178  * you supplied will be called on all keys and values before destroying 
179  * the #GHashTable.
180  **/
181 void
182 mono_g_hash_table_destroy (MonoGHashTable *hash_table)
183 {
184   guint i;
185   
186   g_return_if_fail (hash_table != NULL);
187   
188   for (i = 0; i < hash_table->size; i++)
189     g_hash_nodes_destroy (hash_table->nodes[i], 
190                           hash_table->key_destroy_func,
191                           hash_table->value_destroy_func);
192
193 #if HAVE_BOEHM_GC
194 #else
195   g_free (hash_table->nodes);
196   g_free (hash_table);
197 #endif
198 }
199
200 static inline MonoGHashNode**
201 g_hash_table_lookup_node (MonoGHashTable        *hash_table,
202                           gconstpointer  key)
203 {
204   MonoGHashNode **node;
205   
206   node = &hash_table->nodes
207     [(* hash_table->hash_func) (key) % hash_table->size];
208   
209   /* Hash table lookup needs to be fast.
210    *  We therefore remove the extra conditional of testing
211    *  whether to call the key_equal_func or not from
212    *  the inner loop.
213    */
214   if (hash_table->key_equal_func)
215     while (*node && !(*hash_table->key_equal_func) ((*node)->key, key))
216       node = &(*node)->next;
217   else
218     while (*node && (*node)->key != key)
219       node = &(*node)->next;
220   
221   return node;
222 }
223
224 /**
225  * g_hash_table_lookup:
226  * @hash_table: a #GHashTable.
227  * @key: the key to look up.
228  * 
229  * Looks up a key in a #GHashTable.
230  * 
231  * Return value: the associated value, or %NULL if the key is not found.
232  **/
233 gpointer
234 mono_g_hash_table_lookup (MonoGHashTable          *hash_table,
235                      gconstpointer key)
236 {
237   MonoGHashNode *node;
238   
239   g_return_val_if_fail (hash_table != NULL, NULL);
240   
241   node = *g_hash_table_lookup_node (hash_table, key);
242   
243   return node ? node->value : NULL;
244 }
245
246 /**
247  * g_hash_table_lookup_extended:
248  * @hash_table: a #GHashTable.
249  * @lookup_key: the key to look up.
250  * @orig_key: returns the original key.
251  * @value: returns the value associated with the key.
252  * 
253  * Looks up a key in the #GHashTable, returning the original key and the
254  * associated value and a #gboolean which is %TRUE if the key was found. This 
255  * is useful if you need to free the memory allocated for the original key, 
256  * for example before calling g_hash_table_remove().
257  * 
258  * Return value: %TRUE if the key was found in the #GHashTable.
259  **/
260 gboolean
261 mono_g_hash_table_lookup_extended (MonoGHashTable    *hash_table,
262                               gconstpointer  lookup_key,
263                               gpointer      *orig_key,
264                               gpointer      *value)
265 {
266   MonoGHashNode *node;
267   
268   g_return_val_if_fail (hash_table != NULL, FALSE);
269   
270   node = *g_hash_table_lookup_node (hash_table, lookup_key);
271   
272   if (node)
273     {
274       if (orig_key)
275         *orig_key = node->key;
276       if (value)
277         *value = node->value;
278       return TRUE;
279     }
280   else
281     return FALSE;
282 }
283
284 static inline MonoGHashNode*
285 g_hash_node_new (gpointer key,
286                  gpointer value)
287 {
288   MonoGHashNode *hash_node = NULL;
289
290 #if HAVE_BOEHM_GC
291   if (node_free_list) {
292           G_LOCK (g_hash_global);
293
294           if (node_free_list) {
295                   hash_node = node_free_list;
296                   node_free_list = node_free_list->next;
297           }
298           G_UNLOCK (g_hash_global);
299   }
300   if (!hash_node)
301       hash_node = GC_MALLOC (sizeof (MonoGHashNode));
302 #else
303   G_LOCK (g_hash_global);
304   if (node_free_list)
305     {
306       hash_node = node_free_list;
307       node_free_list = node_free_list->next;
308     }
309   else
310     {
311       if (!node_mem_chunk)
312         node_mem_chunk = g_mem_chunk_new ("hash node mem chunk",
313                                           sizeof (MonoGHashNode),
314                                           1024, G_ALLOC_ONLY);
315       
316       hash_node = g_chunk_new (MonoGHashNode, node_mem_chunk);
317     }
318   G_UNLOCK (g_hash_global);
319 #endif
320   
321   hash_node->key = key;
322   hash_node->value = value;
323   hash_node->next = NULL;
324   
325   return hash_node;
326 }
327
328 /**
329  * g_hash_table_insert:
330  * @hash_table: a #GHashTable.
331  * @key: a key to insert.
332  * @value: the value to associate with the key.
333  * 
334  * Inserts a new key and value into a #GHashTable.
335  * 
336  * If the key already exists in the #GHashTable its current value is replaced
337  * with the new value. If you supplied a @value_destroy_func when creating the 
338  * #GHashTable, the old value is freed using that function. If you supplied
339  * a @key_destroy_func when creating the #GHashTable, the passed key is freed 
340  * using that function.
341  **/
342 void
343 mono_g_hash_table_insert (MonoGHashTable *hash_table,
344                      gpointer    key,
345                      gpointer    value)
346 {
347   MonoGHashNode **node;
348   
349   g_return_if_fail (hash_table != NULL);
350   
351   node = g_hash_table_lookup_node (hash_table, key);
352   
353   if (*node)
354     {
355       /* do not reset node->key in this place, keeping
356        * the old key is the intended behaviour. 
357        * g_hash_table_replace() can be used instead.
358        */
359
360       /* free the passed key */
361       if (hash_table->key_destroy_func)
362         hash_table->key_destroy_func (key);
363       
364       if (hash_table->value_destroy_func)
365         hash_table->value_destroy_func ((*node)->value);
366
367       (*node)->value = value;
368     }
369   else
370     {
371       *node = g_hash_node_new (key, value);
372       hash_table->nnodes++;
373       G_HASH_TABLE_RESIZE (hash_table);
374     }
375 }
376
377 /**
378  * g_hash_table_replace:
379  * @hash_table: a #GHashTable.
380  * @key: a key to insert.
381  * @value: the value to associate with the key.
382  * 
383  * Inserts a new key and value into a #GHashTable similar to 
384  * g_hash_table_insert(). The difference is that if the key already exists 
385  * in the #GHashTable, it gets replaced by the new key. If you supplied a 
386  * @value_destroy_func when creating the #GHashTable, the old value is freed 
387  * using that function. If you supplied a @key_destroy_func when creating the 
388  * #GHashTable, the old key is freed using that function. 
389  **/
390 void
391 mono_g_hash_table_replace (MonoGHashTable *hash_table,
392                       gpointer    key,
393                       gpointer    value)
394 {
395   MonoGHashNode **node;
396   
397   g_return_if_fail (hash_table != NULL);
398   
399   node = g_hash_table_lookup_node (hash_table, key);
400   
401   if (*node)
402     {
403       if (hash_table->key_destroy_func)
404         hash_table->key_destroy_func ((*node)->key);
405       
406       if (hash_table->value_destroy_func)
407         hash_table->value_destroy_func ((*node)->value);
408
409       (*node)->key   = key;
410       (*node)->value = value;
411     }
412   else
413     {
414       *node = g_hash_node_new (key, value);
415       hash_table->nnodes++;
416       G_HASH_TABLE_RESIZE (hash_table);
417     }
418 }
419
420 /**
421  * g_hash_table_remove:
422  * @hash_table: a #GHashTable.
423  * @key: the key to remove.
424  * 
425  * Removes a key and its associated value from a #GHashTable.
426  *
427  * If the #GHashTable was created using g_hash_table_new_full(), the
428  * key and value are freed using the supplied destroy functions, otherwise
429  * you have to make sure that any dynamically allocated values are freed 
430  * yourself.
431  * 
432  * Return value: %TRUE if the key was found and removed from the #GHashTable.
433  **/
434 gboolean
435 mono_g_hash_table_remove (MonoGHashTable           *hash_table,
436                      gconstpointer  key)
437 {
438   MonoGHashNode **node, *dest;
439   
440   g_return_val_if_fail (hash_table != NULL, FALSE);
441   
442   node = g_hash_table_lookup_node (hash_table, key);
443   if (*node)
444     {
445       dest = *node;
446       (*node) = dest->next;
447       g_hash_node_destroy (dest, 
448                            hash_table->key_destroy_func,
449                            hash_table->value_destroy_func);
450       hash_table->nnodes--;
451   
452       G_HASH_TABLE_RESIZE (hash_table);
453
454       return TRUE;
455     }
456
457   return FALSE;
458 }
459
460 /**
461  * g_hash_table_steal:
462  * @hash_table: a #GHashTable.
463  * @key: the key to remove.
464  * 
465  * Removes a key and its associated value from a #GHashTable without
466  * calling the key and value destroy functions.
467  *
468  * Return value: %TRUE if the key was found and removed from the #GHashTable.
469  **/
470 gboolean
471 mono_g_hash_table_steal (MonoGHashTable    *hash_table,
472                     gconstpointer  key)
473 {
474   MonoGHashNode **node, *dest;
475   
476   g_return_val_if_fail (hash_table != NULL, FALSE);
477   
478   node = g_hash_table_lookup_node (hash_table, key);
479   if (*node)
480     {
481       dest = *node;
482       (*node) = dest->next;
483       g_hash_node_destroy (dest, NULL, NULL);
484       hash_table->nnodes--;
485   
486       G_HASH_TABLE_RESIZE (hash_table);
487
488       return TRUE;
489     }
490
491   return FALSE;
492 }
493
494 /**
495  * g_hash_table_foreach_remove:
496  * @hash_table: a #GHashTable.
497  * @func: the function to call for each key/value pair.
498  * @user_data: user data to pass to the function.
499  * 
500  * Calls the given function for each key/value pair in the #GHashTable.
501  * If the function returns %TRUE, then the key/value pair is removed from the
502  * #GHashTable. If you supplied key or value destroy functions when creating
503  * the #GHashTable, they are used to free the memory allocated for the removed
504  * keys and values.
505  * 
506  * Return value: the number of key/value pairs removed.
507  **/
508 guint
509 mono_g_hash_table_foreach_remove (MonoGHashTable        *hash_table,
510                              GHRFunc     func,
511                              gpointer    user_data)
512 {
513   g_return_val_if_fail (hash_table != NULL, 0);
514   g_return_val_if_fail (func != NULL, 0);
515   
516   return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, TRUE);
517 }
518
519 /**
520  * g_hash_table_foreach_steal:
521  * @hash_table: a #GHashTable.
522  * @func: the function to call for each key/value pair.
523  * @user_data: user data to pass to the function.
524  * 
525  * Calls the given function for each key/value pair in the #GHashTable.
526  * If the function returns %TRUE, then the key/value pair is removed from the
527  * #GHashTable, but no key or value destroy functions are called.
528  * 
529  * Return value: the number of key/value pairs removed.
530  **/
531 guint
532 mono_g_hash_table_foreach_steal (MonoGHashTable *hash_table,
533                             GHRFunc     func,
534                             gpointer    user_data)
535 {
536   g_return_val_if_fail (hash_table != NULL, 0);
537   g_return_val_if_fail (func != NULL, 0);
538   
539   return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, FALSE);
540 }
541
542 static guint
543 g_hash_table_foreach_remove_or_steal (MonoGHashTable *hash_table,
544                                       GHRFunc     func,
545                                       gpointer    user_data,
546                                       gboolean    notify)
547 {
548   MonoGHashNode *node, *prev;
549   guint i;
550   guint deleted = 0;
551   
552   for (i = 0; i < hash_table->size; i++)
553     {
554     restart:
555       
556       prev = NULL;
557       
558       for (node = hash_table->nodes[i]; node; prev = node, node = node->next)
559         {
560           if ((* func) (node->key, node->value, user_data))
561             {
562               deleted += 1;
563               
564               hash_table->nnodes -= 1;
565               
566               if (prev)
567                 {
568                   prev->next = node->next;
569                   g_hash_node_destroy (node,
570                                        notify ? hash_table->key_destroy_func : NULL,
571                                        notify ? hash_table->value_destroy_func : NULL);
572                   node = prev;
573                 }
574               else
575                 {
576                   hash_table->nodes[i] = node->next;
577                   g_hash_node_destroy (node,
578                                        notify ? hash_table->key_destroy_func : NULL,
579                                        notify ? hash_table->value_destroy_func : NULL);
580                   goto restart;
581                 }
582             }
583         }
584     }
585   
586   G_HASH_TABLE_RESIZE (hash_table);
587   
588   return deleted;
589 }
590
591 /**
592  * g_hash_table_foreach:
593  * @hash_table: a #GHashTable.
594  * @func: the function to call for each key/value pair.
595  * @user_data: user data to pass to the function.
596  * 
597  * Calls the given function for each of the key/value pairs in the
598  * #GHashTable.  The function is passed the key and value of each
599  * pair, and the given @user_data parameter.  The hash table may not
600  * be modified while iterating over it (you can't add/remove
601  * items). To remove all items matching a predicate, use
602  * g_hash_table_remove().
603  **/
604 void
605 mono_g_hash_table_foreach (MonoGHashTable *hash_table,
606                       GHFunc      func,
607                       gpointer    user_data)
608 {
609   MonoGHashNode *node;
610   gint i;
611   
612   g_return_if_fail (hash_table != NULL);
613   g_return_if_fail (func != NULL);
614   
615   for (i = 0; i < hash_table->size; i++)
616     for (node = hash_table->nodes[i]; node; node = node->next)
617       (* func) (node->key, node->value, user_data);
618 }
619
620 /**
621  * g_hash_table_size:
622  * @hash_table: a #GHashTable.
623  * 
624  * Returns the number of elements contained in the #GHashTable.
625  * 
626  * Return value: the number of key/value pairs in the #GHashTable.
627  **/
628 guint
629 mono_g_hash_table_size (MonoGHashTable *hash_table)
630 {
631   g_return_val_if_fail (hash_table != NULL, 0);
632   
633   return hash_table->nnodes;
634 }
635
636 /**
637  * mono_g_hash_table_remap:
638  * 
639  *  Calls the given function for each key-value pair in the hash table, 
640  * and replaces the value stored in the hash table by the value returned by 
641  * the function.
642  * 
643  **/
644 void        
645 mono_g_hash_table_remap (MonoGHashTable *hash_table,
646                                                  MonoGRemapperFunc func,
647                                                  gpointer user_data)
648 {
649   MonoGHashNode *node;
650   gint i;
651   
652   g_return_if_fail (hash_table != NULL);
653   g_return_if_fail (func != NULL);
654   
655   for (i = 0; i < hash_table->size; i++)
656     for (node = hash_table->nodes[i]; node; node = node->next)
657       node->value = (* func) (node->key, node->value, user_data);
658 }
659
660 static void
661 g_hash_table_resize (MonoGHashTable *hash_table)
662 {
663   MonoGHashNode **new_nodes;
664   MonoGHashNode *node;
665   MonoGHashNode *next;
666   guint hash_val;
667   gint new_size;
668   gint i;
669
670   new_size = g_spaced_primes_closest (hash_table->nnodes);
671   new_size = CLAMP (new_size, HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE);
672  
673 #if HAVE_BOEHM_GC
674   new_nodes              = GC_MALLOC (sizeof (MonoGHashNode*) * new_size);
675 #else
676   new_nodes              = g_new0 (MonoGHashNode*, new_size);
677 #endif
678   
679   for (i = 0; i < hash_table->size; i++)
680     for (node = hash_table->nodes[i]; node; node = next)
681       {
682         next = node->next;
683
684         hash_val = (* hash_table->hash_func) (node->key) % new_size;
685
686         node->next = new_nodes[hash_val];
687         new_nodes[hash_val] = node;
688       }
689   
690 #if HAVE_BOEHM_GC
691 #else
692   g_free (hash_table->nodes);
693 #endif
694   hash_table->nodes = new_nodes;
695   hash_table->size = new_size;
696 }
697
698 static void
699 g_hash_node_destroy (MonoGHashNode      *hash_node,
700                      GDestroyNotify  key_destroy_func,
701                      GDestroyNotify  value_destroy_func)
702 {
703   if (key_destroy_func)
704     key_destroy_func (hash_node->key);
705   if (value_destroy_func)
706     value_destroy_func (hash_node->value);
707   
708   hash_node->key = NULL;
709   hash_node->value = NULL;
710
711   G_LOCK (g_hash_global);
712   hash_node->next = node_free_list;
713   node_free_list = hash_node;
714   G_UNLOCK (g_hash_global);
715 }
716
717 static void
718 g_hash_nodes_destroy (MonoGHashNode *hash_node,
719                       GFreeFunc  key_destroy_func,
720                       GFreeFunc  value_destroy_func)
721 {
722   if (hash_node)
723     {
724       MonoGHashNode *node = hash_node;
725   
726       while (node->next)
727         {
728           if (key_destroy_func)
729             key_destroy_func (node->key);
730           if (value_destroy_func)
731             value_destroy_func (node->value);
732
733           node->key = NULL;
734           node->value = NULL;
735
736           node = node->next;
737         }
738
739   if (key_destroy_func)
740     key_destroy_func (node->key);
741   if (value_destroy_func)
742     value_destroy_func (node->value);
743
744       node->key = NULL;
745       node->value = NULL;
746  
747       G_LOCK (g_hash_global);
748       node->next = node_free_list;
749       node_free_list = hash_node;
750       G_UNLOCK (g_hash_global);
751     }
752 }