b25f6f5356e3236e231bf4c9930474e5b99eaa12
[platform/upstream/glib.git] / glib / gdataset.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * gdataset.c: Generic dataset mechanism, similar to GtkObject data.
5  * Copyright (C) 1998 Tim Janik
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 /*
23  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
24  * file for a list of people on the GLib Team.  See the ChangeLog
25  * files for a list of changes.  These files are distributed with
26  * GLib at ftp://ftp.gtk.org/pub/gtk/.
27  */
28
29 /*
30  * MT safe ; except for g_data*_foreach()
31  */
32
33 #include "config.h"
34
35 #include <string.h>
36
37 #include "gdataset.h"
38
39 #include "gdatasetprivate.h"
40 #include "ghash.h"
41 #include "gquark.h"
42 #include "gtestutils.h"
43 #include "gthread.h"
44 #include "glib_trace.h"
45
46 /**
47  * SECTION: datasets
48  * @title: Datasets
49  * @short_description: associate groups of data elements with
50  *                     particular memory locations
51  *
52  * Datasets associate groups of data elements with particular memory
53  * locations. These are useful if you need to associate data with a
54  * structure returned from an external library. Since you cannot modify
55  * the structure, you use its location in memory as the key into a
56  * dataset, where you can associate any number of data elements with it.
57  *
58  * There are two forms of most of the dataset functions. The first form
59  * uses strings to identify the data elements associated with a
60  * location. The second form uses #GQuark identifiers, which are
61  * created with a call to g_quark_from_string() or
62  * g_quark_from_static_string(). The second form is quicker, since it
63  * does not require looking up the string in the hash table of #GQuark
64  * identifiers.
65  *
66  * There is no function to create a dataset. It is automatically
67  * created as soon as you add elements to it.
68  *
69  * To add data elements to a dataset use g_dataset_id_set_data(),
70  * g_dataset_id_set_data_full(), g_dataset_set_data() and
71  * g_dataset_set_data_full().
72  *
73  * To get data elements from a dataset use g_dataset_id_get_data() and
74  * g_dataset_get_data().
75  *
76  * To iterate over all data elements in a dataset use
77  * g_dataset_foreach() (not thread-safe).
78  *
79  * To remove data elements from a dataset use
80  * g_dataset_id_remove_data() and g_dataset_remove_data().
81  *
82  * To destroy a dataset, use g_dataset_destroy().
83  **/
84
85 /**
86  * SECTION: datalist
87  * @title: Keyed Data Lists
88  * @short_description: lists of data elements which are accessible by a
89  *                     string or GQuark identifier
90  *
91  * Keyed data lists provide lists of arbitrary data elements which can
92  * be accessed either with a string or with a #GQuark corresponding to
93  * the string.
94  *
95  * The #GQuark methods are quicker, since the strings have to be
96  * converted to #GQuarks anyway.
97  *
98  * Data lists are used for associating arbitrary data with #GObjects,
99  * using g_object_set_data() and related functions.
100  *
101  * To create a datalist, use g_datalist_init().
102  *
103  * To add data elements to a datalist use g_datalist_id_set_data(),
104  * g_datalist_id_set_data_full(), g_datalist_set_data() and
105  * g_datalist_set_data_full().
106  *
107  * To get data elements from a datalist use g_datalist_id_get_data()
108  * and g_datalist_get_data().
109  *
110  * To iterate over all data elements in a datalist use
111  * g_datalist_foreach() (not thread-safe).
112  *
113  * To remove data elements from a datalist use
114  * g_datalist_id_remove_data() and g_datalist_remove_data().
115  *
116  * To remove all data elements from a datalist, use g_datalist_clear().
117  **/
118
119 /**
120  * GData:
121  *
122  * The #GData struct is an opaque data structure to represent a <link
123  * linkend="glib-Keyed-Data-Lists">Keyed Data List</link>. It should
124  * only be accessed via the following functions.
125  **/
126
127 /**
128  * GDestroyNotify:
129  * @data: the data element.
130  *
131  * Specifies the type of function which is called when a data element
132  * is destroyed. It is passed the pointer to the data element and
133  * should free any memory and resources allocated for it.
134  **/
135
136 /* --- defines --- */
137 #define G_QUARK_BLOCK_SIZE                      (512)
138
139 /* datalist pointer accesses have to be carried out atomically */
140 #define G_DATALIST_GET_POINTER(datalist)                                                \
141   ((GData*) ((gsize) g_atomic_pointer_get (datalist) & ~(gsize) G_DATALIST_FLAGS_MASK))
142
143 #define G_DATALIST_SET_POINTER(datalist, pointer)       G_STMT_START {                  \
144   gpointer _oldv, _newv;                                                                \
145   do {                                                                                  \
146     _oldv = g_atomic_pointer_get (datalist);                                            \
147     _newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK) | (gsize) pointer);     \
148   } while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, _oldv, _newv));   \
149 } G_STMT_END
150
151 /* --- structures --- */
152 typedef struct _GDataset GDataset;
153 struct _GData
154 {
155   GData *next;
156   GQuark id;
157   gpointer data;
158   GDestroyNotify destroy_func;
159 };
160
161 struct _GDataset
162 {
163   gconstpointer location;
164   GData        *datalist;
165 };
166
167
168 /* --- prototypes --- */
169 static inline GDataset* g_dataset_lookup                (gconstpointer    dataset_location);
170 static inline void      g_datalist_clear_i              (GData          **datalist);
171 static void             g_dataset_destroy_internal      (GDataset        *dataset);
172 static inline gpointer  g_data_set_internal             (GData          **datalist,
173                                                          GQuark           key_id,
174                                                          gpointer         data,
175                                                          GDestroyNotify   destroy_func,
176                                                          GDataset        *dataset);
177 static void             g_data_initialize               (void);
178 static inline GQuark    g_quark_new                     (gchar          *string);
179
180
181 /* --- variables --- */
182 G_LOCK_DEFINE_STATIC (g_dataset_global);
183 static GHashTable   *g_dataset_location_ht = NULL;
184 static GDataset     *g_dataset_cached = NULL; /* should this be
185                                                  threadspecific? */
186 G_LOCK_DEFINE_STATIC (g_quark_global);
187 static GHashTable   *g_quark_ht = NULL;
188 static gchar       **g_quarks = NULL;
189 static GQuark        g_quark_seq_id = 0;
190
191 /* --- functions --- */
192
193 /* HOLDS: g_dataset_global_lock */
194 static inline void
195 g_datalist_clear_i (GData **datalist)
196 {
197   register GData *list;
198   
199   /* unlink *all* items before walking their destructors
200    */
201   list = G_DATALIST_GET_POINTER (datalist);
202   G_DATALIST_SET_POINTER (datalist, NULL);
203   
204   while (list)
205     {
206       register GData *prev;
207       
208       prev = list;
209       list = prev->next;
210       
211       if (prev->destroy_func)
212         {
213           G_UNLOCK (g_dataset_global);
214           prev->destroy_func (prev->data);
215           G_LOCK (g_dataset_global);
216         }
217       
218       g_slice_free (GData, prev);
219     }
220 }
221
222 /**
223  * g_datalist_clear:
224  * @datalist: a datalist.
225  *
226  * Frees all the data elements of the datalist. The data elements'
227  * destroy functions are called if they have been set.
228  **/
229 void
230 g_datalist_clear (GData **datalist)
231 {
232   g_return_if_fail (datalist != NULL);
233   
234   G_LOCK (g_dataset_global);
235   if (!g_dataset_location_ht)
236     g_data_initialize ();
237
238   while (G_DATALIST_GET_POINTER (datalist))
239     g_datalist_clear_i (datalist);
240   G_UNLOCK (g_dataset_global);
241 }
242
243 /* HOLDS: g_dataset_global_lock */
244 static inline GDataset*
245 g_dataset_lookup (gconstpointer dataset_location)
246 {
247   register GDataset *dataset;
248   
249   if (g_dataset_cached && g_dataset_cached->location == dataset_location)
250     return g_dataset_cached;
251   
252   dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
253   if (dataset)
254     g_dataset_cached = dataset;
255   
256   return dataset;
257 }
258
259 /* HOLDS: g_dataset_global_lock */
260 static void
261 g_dataset_destroy_internal (GDataset *dataset)
262 {
263   register gconstpointer dataset_location;
264   
265   dataset_location = dataset->location;
266   while (dataset)
267     {
268       if (!dataset->datalist)
269         {
270           if (dataset == g_dataset_cached)
271             g_dataset_cached = NULL;
272           g_hash_table_remove (g_dataset_location_ht, dataset_location);
273           g_slice_free (GDataset, dataset);
274           break;
275         }
276       
277       g_datalist_clear_i (&dataset->datalist);
278       dataset = g_dataset_lookup (dataset_location);
279     }
280 }
281
282 /**
283  * g_dataset_destroy:
284  * @dataset_location: the location identifying the dataset.
285  *
286  * Destroys the dataset, freeing all memory allocated, and calling any
287  * destroy functions set for data elements.
288  **/
289 void
290 g_dataset_destroy (gconstpointer  dataset_location)
291 {
292   g_return_if_fail (dataset_location != NULL);
293   
294   G_LOCK (g_dataset_global);
295   if (g_dataset_location_ht)
296     {
297       register GDataset *dataset;
298
299       dataset = g_dataset_lookup (dataset_location);
300       if (dataset)
301         g_dataset_destroy_internal (dataset);
302     }
303   G_UNLOCK (g_dataset_global);
304 }
305
306 /* HOLDS: g_dataset_global_lock */
307 static inline gpointer
308 g_data_set_internal (GData        **datalist,
309                      GQuark         key_id,
310                      gpointer       data,
311                      GDestroyNotify destroy_func,
312                      GDataset      *dataset)
313 {
314   register GData *list;
315   
316   list = G_DATALIST_GET_POINTER (datalist);
317   if (!data)
318     {
319       register GData *prev;
320       
321       prev = NULL;
322       while (list)
323         {
324           if (list->id == key_id)
325             {
326               gpointer ret_data = NULL;
327
328               if (prev)
329                 prev->next = list->next;
330               else
331                 {
332                   G_DATALIST_SET_POINTER (datalist, list->next);
333                   
334                   /* the dataset destruction *must* be done
335                    * prior to invocation of the data destroy function
336                    */
337                   if (!list->next && dataset)
338                     g_dataset_destroy_internal (dataset);
339                 }
340               
341               /* the GData struct *must* already be unlinked
342                * when invoking the destroy function.
343                * we use (data==NULL && destroy_func!=NULL) as
344                * a special hint combination to "steal"
345                * data without destroy notification
346                */
347               if (list->destroy_func && !destroy_func)
348                 {
349                   G_UNLOCK (g_dataset_global);
350                   list->destroy_func (list->data);
351                   G_LOCK (g_dataset_global);
352                 }
353               else
354                 ret_data = list->data;
355               
356               g_slice_free (GData, list);
357               
358               return ret_data;
359             }
360           
361           prev = list;
362           list = list->next;
363         }
364     }
365   else
366     {
367       while (list)
368         {
369           if (list->id == key_id)
370             {
371               if (!list->destroy_func)
372                 {
373                   list->data = data;
374                   list->destroy_func = destroy_func;
375                 }
376               else
377                 {
378                   register GDestroyNotify dfunc;
379                   register gpointer ddata;
380                   
381                   dfunc = list->destroy_func;
382                   ddata = list->data;
383                   list->data = data;
384                   list->destroy_func = destroy_func;
385                   
386                   /* we need to have updated all structures prior to
387                    * invocation of the destroy function
388                    */
389                   G_UNLOCK (g_dataset_global);
390                   dfunc (ddata);
391                   G_LOCK (g_dataset_global);
392                 }
393               
394               return NULL;
395             }
396           
397           list = list->next;
398         }
399       
400       list = g_slice_new (GData);
401       list->next = G_DATALIST_GET_POINTER (datalist);
402       list->id = key_id;
403       list->data = data;
404       list->destroy_func = destroy_func;
405       G_DATALIST_SET_POINTER (datalist, list);
406     }
407
408   return NULL;
409 }
410
411 /**
412  * g_dataset_id_set_data_full:
413  * @dataset_location: the location identifying the dataset.
414  * @key_id: the #GQuark id to identify the data element.
415  * @data: the data element.
416  * @destroy_func: the function to call when the data element is
417  *                removed. This function will be called with the data
418  *                element and can be used to free any memory allocated
419  *                for it.
420  *
421  * Sets the data element associated with the given #GQuark id, and also
422  * the function to call when the data element is destroyed. Any
423  * previous data with the same key is removed, and its destroy function
424  * is called.
425  **/
426 /**
427  * g_dataset_set_data_full:
428  * @l: the location identifying the dataset.
429  * @k: the string to identify the data element.
430  * @d: the data element.
431  * @f: the function to call when the data element is removed. This
432  *     function will be called with the data element and can be used to
433  *     free any memory allocated for it.
434  *
435  * Sets the data corresponding to the given string identifier, and the
436  * function to call when the data element is destroyed.
437  **/
438 /**
439  * g_dataset_id_set_data:
440  * @l: the location identifying the dataset.
441  * @k: the #GQuark id to identify the data element.
442  * @d: the data element.
443  *
444  * Sets the data element associated with the given #GQuark id. Any
445  * previous data with the same key is removed, and its destroy function
446  * is called.
447  **/
448 /**
449  * g_dataset_set_data:
450  * @l: the location identifying the dataset.
451  * @k: the string to identify the data element.
452  * @d: the data element.
453  *
454  * Sets the data corresponding to the given string identifier.
455  **/
456 /**
457  * g_dataset_id_remove_data:
458  * @l: the location identifying the dataset.
459  * @k: the #GQuark id identifying the data element.
460  *
461  * Removes a data element from a dataset. The data element's destroy
462  * function is called if it has been set.
463  **/
464 /**
465  * g_dataset_remove_data:
466  * @l: the location identifying the dataset.
467  * @k: the string identifying the data element.
468  *
469  * Removes a data element corresponding to a string. Its destroy
470  * function is called if it has been set.
471  **/
472 void
473 g_dataset_id_set_data_full (gconstpointer  dataset_location,
474                             GQuark         key_id,
475                             gpointer       data,
476                             GDestroyNotify destroy_func)
477 {
478   register GDataset *dataset;
479   
480   g_return_if_fail (dataset_location != NULL);
481   if (!data)
482     g_return_if_fail (destroy_func == NULL);
483   if (!key_id)
484     {
485       if (data)
486         g_return_if_fail (key_id > 0);
487       else
488         return;
489     }
490   
491   G_LOCK (g_dataset_global);
492   if (!g_dataset_location_ht)
493     g_data_initialize ();
494  
495   dataset = g_dataset_lookup (dataset_location);
496   if (!dataset)
497     {
498       dataset = g_slice_new (GDataset);
499       dataset->location = dataset_location;
500       g_datalist_init (&dataset->datalist);
501       g_hash_table_insert (g_dataset_location_ht, 
502                            (gpointer) dataset->location,
503                            dataset);
504     }
505   
506   g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
507   G_UNLOCK (g_dataset_global);
508 }
509
510 /**
511  * g_datalist_id_set_data_full:
512  * @datalist: a datalist.
513  * @key_id: the #GQuark to identify the data element.
514  * @data: the data element or %NULL to remove any previous element
515  *        corresponding to @key_id.
516  * @destroy_func: the function to call when the data element is
517  *                removed. This function will be called with the data
518  *                element and can be used to free any memory allocated
519  *                for it. If @data is %NULL, then @destroy_func must
520  *                also be %NULL.
521  *
522  * Sets the data corresponding to the given #GQuark id, and the
523  * function to be called when the element is removed from the datalist.
524  * Any previous data with the same key is removed, and its destroy
525  * function is called.
526  **/
527 /**
528  * g_datalist_set_data_full:
529  * @dl: a datalist.
530  * @k: the string to identify the data element.
531  * @d: the data element, or %NULL to remove any previous element
532  *     corresponding to @k.
533  * @f: the function to call when the data element is removed. This
534  *     function will be called with the data element and can be used to
535  *     free any memory allocated for it. If @d is %NULL, then @f must
536  *     also be %NULL.
537  *
538  * Sets the data element corresponding to the given string identifier,
539  * and the function to be called when the data element is removed.
540  **/
541 /**
542  * g_datalist_id_set_data:
543  * @dl: a datalist.
544  * @q: the #GQuark to identify the data element.
545  * @d: the data element, or %NULL to remove any previous element
546  *     corresponding to @q.
547  *
548  * Sets the data corresponding to the given #GQuark id. Any previous
549  * data with the same key is removed, and its destroy function is
550  * called.
551  **/
552 /**
553  * g_datalist_set_data:
554  * @dl: a datalist.
555  * @k: the string to identify the data element.
556  * @d: the data element, or %NULL to remove any previous element
557  *     corresponding to @k.
558  *
559  * Sets the data element corresponding to the given string identifier.
560  **/
561 /**
562  * g_datalist_id_remove_data:
563  * @dl: a datalist.
564  * @q: the #GQuark identifying the data element.
565  *
566  * Removes an element, using its #GQuark identifier.
567  **/
568 /**
569  * g_datalist_remove_data:
570  * @dl: a datalist.
571  * @k: the string identifying the data element.
572  *
573  * Removes an element using its string identifier. The data element's
574  * destroy function is called if it has been set.
575  **/
576 void
577 g_datalist_id_set_data_full (GData        **datalist,
578                              GQuark         key_id,
579                              gpointer       data,
580                              GDestroyNotify destroy_func)
581 {
582   g_return_if_fail (datalist != NULL);
583   if (!data)
584     g_return_if_fail (destroy_func == NULL);
585   if (!key_id)
586     {
587       if (data)
588         g_return_if_fail (key_id > 0);
589       else
590         return;
591     }
592
593   G_LOCK (g_dataset_global);
594   if (!g_dataset_location_ht)
595     g_data_initialize ();
596   
597   g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
598   G_UNLOCK (g_dataset_global);
599 }
600
601 /**
602  * g_dataset_id_remove_no_notify:
603  * @dataset_location: the location identifying the dataset.
604  * @key_id: the #GQuark ID identifying the data element.
605  * @Returns: the data previously stored at @key_id, or %NULL if none.
606  *
607  * Removes an element, without calling its destroy notification
608  * function.
609  **/
610 /**
611  * g_dataset_remove_no_notify:
612  * @l: the location identifying the dataset.
613  * @k: the string identifying the data element.
614  *
615  * Removes an element, without calling its destroy notifier.
616  **/
617 gpointer
618 g_dataset_id_remove_no_notify (gconstpointer  dataset_location,
619                                GQuark         key_id)
620 {
621   gpointer ret_data = NULL;
622
623   g_return_val_if_fail (dataset_location != NULL, NULL);
624   
625   G_LOCK (g_dataset_global);
626   if (key_id && g_dataset_location_ht)
627     {
628       GDataset *dataset;
629   
630       dataset = g_dataset_lookup (dataset_location);
631       if (dataset)
632         ret_data = g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
633     } 
634   G_UNLOCK (g_dataset_global);
635
636   return ret_data;
637 }
638
639 /**
640  * g_datalist_id_remove_no_notify:
641  * @datalist: a datalist.
642  * @key_id: the #GQuark identifying a data element.
643  * @Returns: the data previously stored at @key_id, or %NULL if none.
644  *
645  * Removes an element, without calling its destroy notification
646  * function.
647  **/
648 /**
649  * g_datalist_remove_no_notify:
650  * @dl: a datalist.
651  * @k: the string identifying the data element.
652  *
653  * Removes an element, without calling its destroy notifier.
654  **/
655 gpointer
656 g_datalist_id_remove_no_notify (GData   **datalist,
657                                 GQuark    key_id)
658 {
659   gpointer ret_data = NULL;
660
661   g_return_val_if_fail (datalist != NULL, NULL);
662
663   G_LOCK (g_dataset_global);
664   if (key_id && g_dataset_location_ht)
665     ret_data = g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
666   G_UNLOCK (g_dataset_global);
667
668   return ret_data;
669 }
670
671 /**
672  * g_dataset_id_get_data:
673  * @dataset_location: the location identifying the dataset.
674  * @key_id: the #GQuark id to identify the data element.
675  * @Returns: the data element corresponding to the #GQuark, or %NULL if
676  *           it is not found.
677  *
678  * Gets the data element corresponding to a #GQuark.
679  **/
680 /**
681  * g_dataset_get_data:
682  * @l: the location identifying the dataset.
683  * @k: the string identifying the data element.
684  * @Returns: the data element corresponding to the string, or %NULL if
685  *           it is not found.
686  *
687  * Gets the data element corresponding to a string.
688  **/
689 gpointer
690 g_dataset_id_get_data (gconstpointer  dataset_location,
691                        GQuark         key_id)
692 {
693   g_return_val_if_fail (dataset_location != NULL, NULL);
694   
695   G_LOCK (g_dataset_global);
696   if (key_id && g_dataset_location_ht)
697     {
698       register GDataset *dataset;
699       
700       dataset = g_dataset_lookup (dataset_location);
701       if (dataset)
702         {
703           register GData *list;
704           
705           for (list = dataset->datalist; list; list = list->next)
706             if (list->id == key_id)
707               {
708                 G_UNLOCK (g_dataset_global);
709                 return list->data;
710               }
711         }
712     }
713   G_UNLOCK (g_dataset_global);
714  
715   return NULL;
716 }
717
718 /**
719  * g_datalist_id_get_data:
720  * @datalist: a datalist.
721  * @key_id: the #GQuark identifying a data element.
722  * @Returns: the data element, or %NULL if it is not found.
723  *
724  * Retrieves the data element corresponding to @key_id.
725  **/
726 /**
727  * g_datalist_get_data:
728  * @dl: a datalist.
729  * @k: the string identifying a data element.
730  * @Returns: the data element, or %NULL if it is not found.
731  *
732  * Gets a data element, using its string identifer. This is slower than
733  * g_datalist_id_get_data() because the string is first converted to a
734  * #GQuark.
735  **/
736 gpointer
737 g_datalist_id_get_data (GData    **datalist,
738                         GQuark     key_id)
739 {
740   gpointer data = NULL;
741   g_return_val_if_fail (datalist != NULL, NULL);
742   if (key_id)
743     {
744       register GData *list;
745       G_LOCK (g_dataset_global);
746       for (list = G_DATALIST_GET_POINTER (datalist); list; list = list->next)
747         if (list->id == key_id)
748           {
749             data = list->data;
750             break;
751           }
752       G_UNLOCK (g_dataset_global);
753     }
754   return data;
755 }
756
757 /**
758  * GDataForeachFunc:
759  * @key_id: the #GQuark id to identifying the data element.
760  * @data: the data element.
761  * @user_data: user data passed to g_dataset_foreach().
762  *
763  * Specifies the type of function passed to g_dataset_foreach(). It is
764  * called with each #GQuark id and associated data element, together
765  * with the @user_data parameter supplied to g_dataset_foreach().
766  **/
767
768 /**
769  * g_dataset_foreach:
770  * @dataset_location: the location identifying the dataset.
771  * @func: the function to call for each data element.
772  * @user_data: user data to pass to the function.
773  *
774  * Calls the given function for each data element which is associated
775  * with the given location. Note that this function is NOT thread-safe.
776  * So unless @datalist can be protected from any modifications during
777  * invocation of this function, it should not be called.
778  **/
779 void
780 g_dataset_foreach (gconstpointer    dataset_location,
781                    GDataForeachFunc func,
782                    gpointer         user_data)
783 {
784   register GDataset *dataset;
785   
786   g_return_if_fail (dataset_location != NULL);
787   g_return_if_fail (func != NULL);
788
789   G_LOCK (g_dataset_global);
790   if (g_dataset_location_ht)
791     {
792       dataset = g_dataset_lookup (dataset_location);
793       G_UNLOCK (g_dataset_global);
794       if (dataset)
795         {
796           register GData *list, *next;
797           
798           for (list = dataset->datalist; list; list = next)
799             {
800               next = list->next;
801               func (list->id, list->data, user_data);
802             }
803         }
804     }
805   else
806     {
807       G_UNLOCK (g_dataset_global);
808     }
809 }
810
811 /**
812  * g_datalist_foreach:
813  * @datalist: a datalist.
814  * @func: the function to call for each data element.
815  * @user_data: user data to pass to the function.
816  *
817  * Calls the given function for each data element of the datalist. The
818  * function is called with each data element's #GQuark id and data,
819  * together with the given @user_data parameter. Note that this
820  * function is NOT thread-safe. So unless @datalist can be protected
821  * from any modifications during invocation of this function, it should
822  * not be called.
823  **/
824 void
825 g_datalist_foreach (GData          **datalist,
826                     GDataForeachFunc func,
827                     gpointer         user_data)
828 {
829   register GData *list, *next;
830
831   g_return_if_fail (datalist != NULL);
832   g_return_if_fail (func != NULL);
833   
834   for (list = G_DATALIST_GET_POINTER (datalist); list; list = next)
835     {
836       next = list->next;
837       func (list->id, list->data, user_data);
838     }
839 }
840
841 /**
842  * g_datalist_init:
843  * @datalist: a pointer to a pointer to a datalist.
844  *
845  * Resets the datalist to %NULL. It does not free any memory or call
846  * any destroy functions.
847  **/
848 void
849 g_datalist_init (GData **datalist)
850 {
851   g_return_if_fail (datalist != NULL);
852
853   g_atomic_pointer_set (datalist, NULL);
854 }
855
856 /**
857  * g_datalist_set_flags:
858  * @datalist: pointer to the location that holds a list
859  * @flags: the flags to turn on. The values of the flags are
860  *   restricted by %G_DATALIST_FLAGS_MASK (currently
861  *   3; giving two possible boolean flags).
862  *   A value for @flags that doesn't fit within the mask is
863  *   an error.
864  * 
865  * Turns on flag values for a data list. This function is used
866  * to keep a small number of boolean flags in an object with
867  * a data list without using any additional space. It is
868  * not generally useful except in circumstances where space
869  * is very tight. (It is used in the base #GObject type, for
870  * example.)
871  *
872  * Since: 2.8
873  **/
874 void
875 g_datalist_set_flags (GData **datalist,
876                       guint   flags)
877 {
878   gpointer oldvalue;
879   g_return_if_fail (datalist != NULL);
880   g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
881   
882   do
883     {
884       oldvalue = g_atomic_pointer_get (datalist);
885     }
886   while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
887                                                  (gpointer) ((gsize) oldvalue | flags)));
888 }
889
890 /**
891  * g_datalist_unset_flags:
892  * @datalist: pointer to the location that holds a list
893  * @flags: the flags to turn off. The values of the flags are
894  *   restricted by %G_DATALIST_FLAGS_MASK (currently
895  *   3: giving two possible boolean flags).
896  *   A value for @flags that doesn't fit within the mask is
897  *   an error.
898  * 
899  * Turns off flag values for a data list. See g_datalist_unset_flags()
900  *
901  * Since: 2.8
902  **/
903 void
904 g_datalist_unset_flags (GData **datalist,
905                         guint   flags)
906 {
907   gpointer oldvalue;
908   g_return_if_fail (datalist != NULL);
909   g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
910   
911   do
912     {
913       oldvalue = g_atomic_pointer_get (datalist);
914     }
915   while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
916                                                  (gpointer) ((gsize) oldvalue & ~(gsize) flags)));
917 }
918
919 /**
920  * g_datalist_get_flags:
921  * @datalist: pointer to the location that holds a list
922  * 
923  * Gets flags values packed in together with the datalist.
924  * See g_datalist_set_flags().
925  * 
926  * Return value: the flags of the datalist
927  *
928  * Since: 2.8
929  **/
930 guint
931 g_datalist_get_flags (GData **datalist)
932 {
933   g_return_val_if_fail (datalist != NULL, 0);
934   
935   return G_DATALIST_GET_FLAGS (datalist); /* atomic macro */
936 }
937
938 /* HOLDS: g_dataset_global_lock */
939 static void
940 g_data_initialize (void)
941 {
942   g_return_if_fail (g_dataset_location_ht == NULL);
943
944   g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
945   g_dataset_cached = NULL;
946 }
947
948 /**
949  * SECTION: quarks
950  * @title: Quarks
951  * @short_description: a 2-way association between a string and a
952  *                     unique integer identifier
953  *
954  * Quarks are associations between strings and integer identifiers.
955  * Given either the string or the #GQuark identifier it is possible to
956  * retrieve the other.
957  *
958  * Quarks are used for both <link
959  * linkend="glib-datasets">Datasets</link> and <link
960  * linkend="glib-keyed-data-lists">Keyed Data Lists</link>.
961  *
962  * To create a new quark from a string, use g_quark_from_string() or
963  * g_quark_from_static_string().
964  *
965  * To find the string corresponding to a given #GQuark, use
966  * g_quark_to_string().
967  *
968  * To find the #GQuark corresponding to a given string, use
969  * g_quark_try_string().
970  *
971  * Another use for the string pool maintained for the quark functions
972  * is string interning, using g_intern_string() or
973  * g_intern_static_string(). An interned string is a canonical
974  * representation for a string. One important advantage of interned
975  * strings is that they can be compared for equality by a simple
976  * pointer comparision, rather than using strcmp().
977  **/
978
979 /**
980  * GQuark:
981  *
982  * A GQuark is a non-zero integer which uniquely identifies a
983  * particular string. A GQuark value of zero is associated to %NULL.
984  **/
985
986 /**
987  * g_quark_try_string:
988  * @string: a string.
989  * @Returns: the #GQuark associated with the string, or 0 if @string is
990  *           %NULL or there is no #GQuark associated with it.
991  *
992  * Gets the #GQuark associated with the given string, or 0 if string is
993  * %NULL or it has no associated #GQuark.
994  *
995  * If you want the GQuark to be created if it doesn't already exist,
996  * use g_quark_from_string() or g_quark_from_static_string().
997  **/
998 GQuark
999 g_quark_try_string (const gchar *string)
1000 {
1001   GQuark quark = 0;
1002   g_return_val_if_fail (string != NULL, 0);
1003   
1004   G_LOCK (g_quark_global);
1005   if (g_quark_ht)
1006     quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1007   G_UNLOCK (g_quark_global);
1008   
1009   return quark;
1010 }
1011
1012 #define QUARK_STRING_BLOCK_SIZE (4096 - sizeof (gsize))
1013 static char *quark_block = NULL;
1014 static int quark_block_offset = 0;
1015
1016 /* HOLDS: g_quark_global_lock */
1017 static char *
1018 quark_strdup(const gchar *string)
1019 {
1020   gchar *copy;
1021   gsize len;
1022
1023   len = strlen (string) + 1;
1024
1025   /* For strings longer than half the block size, fall back
1026      to strdup so that we fill our blocks at least 50%. */
1027   if (len > QUARK_STRING_BLOCK_SIZE / 2)
1028     return g_strdup (string);
1029
1030   if (quark_block == NULL ||
1031       QUARK_STRING_BLOCK_SIZE - quark_block_offset < len)
1032     {
1033       quark_block = g_malloc (QUARK_STRING_BLOCK_SIZE);
1034       quark_block_offset = 0;
1035     }
1036
1037   copy = quark_block + quark_block_offset;
1038   memcpy (copy, string, len);
1039   quark_block_offset += len;
1040
1041   return copy;
1042 }
1043
1044 /* HOLDS: g_quark_global_lock */
1045 static inline GQuark
1046 g_quark_from_string_internal (const gchar *string, 
1047                               gboolean     duplicate)
1048 {
1049   GQuark quark = 0;
1050   
1051   if (g_quark_ht)
1052     quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1053   
1054   if (!quark)
1055     {
1056       quark = g_quark_new (duplicate ? quark_strdup (string) : (gchar *)string);
1057       TRACE(GLIB_QUARK_NEW(string, quark));
1058     }
1059
1060   return quark;
1061 }
1062
1063 /**
1064  * g_quark_from_string:
1065  * @string: a string.
1066  * @Returns: the #GQuark identifying the string, or 0 if @string is
1067  *           %NULL.
1068  *
1069  * Gets the #GQuark identifying the given string. If the string does
1070  * not currently have an associated #GQuark, a new #GQuark is created,
1071  * using a copy of the string.
1072  **/
1073 GQuark
1074 g_quark_from_string (const gchar *string)
1075 {
1076   GQuark quark;
1077   
1078   if (!string)
1079     return 0;
1080   
1081   G_LOCK (g_quark_global);
1082   quark = g_quark_from_string_internal (string, TRUE);
1083   G_UNLOCK (g_quark_global);
1084   
1085   return quark;
1086 }
1087
1088 /**
1089  * g_quark_from_static_string:
1090  * @string: a string.
1091  * @Returns: the #GQuark identifying the string, or 0 if @string is
1092  *           %NULL.
1093  *
1094  * Gets the #GQuark identifying the given (static) string. If the
1095  * string does not currently have an associated #GQuark, a new #GQuark
1096  * is created, linked to the given string.
1097  *
1098  * Note that this function is identical to g_quark_from_string() except
1099  * that if a new #GQuark is created the string itself is used rather
1100  * than a copy. This saves memory, but can only be used if the string
1101  * will <emphasis>always</emphasis> exist. It can be used with
1102  * statically allocated strings in the main program, but not with
1103  * statically allocated memory in dynamically loaded modules, if you
1104  * expect to ever unload the module again (e.g. do not use this
1105  * function in GTK+ theme engines).
1106  **/
1107 GQuark
1108 g_quark_from_static_string (const gchar *string)
1109 {
1110   GQuark quark;
1111   
1112   if (!string)
1113     return 0;
1114   
1115   G_LOCK (g_quark_global);
1116   quark = g_quark_from_string_internal (string, FALSE);
1117   G_UNLOCK (g_quark_global);
1118
1119   return quark;
1120 }
1121
1122 /**
1123  * g_quark_to_string:
1124  * @quark: a #GQuark.
1125  * @Returns: the string associated with the #GQuark.
1126  *
1127  * Gets the string associated with the given #GQuark.
1128  **/
1129 G_CONST_RETURN gchar*
1130 g_quark_to_string (GQuark quark)
1131 {
1132   gchar* result = NULL;
1133
1134   G_LOCK (g_quark_global);
1135   if (quark < g_quark_seq_id)
1136     result = g_quarks[quark];
1137   G_UNLOCK (g_quark_global);
1138
1139   return result;
1140 }
1141
1142 /* HOLDS: g_quark_global_lock */
1143 static inline GQuark
1144 g_quark_new (gchar *string)
1145 {
1146   GQuark quark;
1147   
1148   if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
1149     g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
1150   if (!g_quark_ht)
1151     {
1152       g_assert (g_quark_seq_id == 0);
1153       g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
1154       g_quarks[g_quark_seq_id++] = NULL;
1155     }
1156
1157   quark = g_quark_seq_id++;
1158   g_quarks[quark] = string;
1159   g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
1160   
1161   return quark;
1162 }
1163
1164 /**
1165  * g_intern_string:
1166  * @string: a string
1167  * 
1168  * Returns a canonical representation for @string. Interned strings can
1169  * be compared for equality by comparing the pointers, instead of using strcmp().
1170  * 
1171  * Returns: a canonical representation for the string
1172  *
1173  * Since: 2.10
1174  */
1175 G_CONST_RETURN gchar*
1176 g_intern_string (const gchar *string)
1177 {
1178   const gchar *result;
1179   GQuark quark;
1180
1181   if (!string)
1182     return NULL;
1183
1184   G_LOCK (g_quark_global);
1185   quark = g_quark_from_string_internal (string, TRUE);
1186   result = g_quarks[quark];
1187   G_UNLOCK (g_quark_global);
1188
1189   return result;
1190 }
1191
1192 /**
1193  * g_intern_static_string:
1194  * @string: a static string
1195  * 
1196  * Returns a canonical representation for @string. Interned strings can
1197  * be compared for equality by comparing the pointers, instead of using strcmp().
1198  * g_intern_static_string() does not copy the string, therefore @string must
1199  * not be freed or modified. 
1200  * 
1201  * Returns: a canonical representation for the string
1202  *
1203  * Since: 2.10
1204  */
1205 G_CONST_RETURN gchar*
1206 g_intern_static_string (const gchar *string)
1207 {
1208   GQuark quark;
1209   const gchar *result;
1210
1211   if (!string)
1212     return NULL;
1213
1214   G_LOCK (g_quark_global);
1215   quark = g_quark_from_string_internal (string, FALSE);
1216   result = g_quarks[quark];
1217   G_UNLOCK (g_quark_global);
1218
1219   return result;
1220 }