1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * gdataset.c: Generic dataset mechanism, similar to GtkObject data.
5 * Copyright (C) 1998 Tim Janik
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.
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.
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.
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/.
30 * MT safe ; except for g_data*_foreach()
40 #include "gdatasetprivate.h"
43 #include "gstrfuncs.h"
44 #include "gtestutils.h"
46 #include "glib_trace.h"
51 * @short_description: associate groups of data elements with
52 * particular memory locations
54 * Datasets associate groups of data elements with particular memory
55 * locations. These are useful if you need to associate data with a
56 * structure returned from an external library. Since you cannot modify
57 * the structure, you use its location in memory as the key into a
58 * dataset, where you can associate any number of data elements with it.
60 * There are two forms of most of the dataset functions. The first form
61 * uses strings to identify the data elements associated with a
62 * location. The second form uses #GQuark identifiers, which are
63 * created with a call to g_quark_from_string() or
64 * g_quark_from_static_string(). The second form is quicker, since it
65 * does not require looking up the string in the hash table of #GQuark
68 * There is no function to create a dataset. It is automatically
69 * created as soon as you add elements to it.
71 * To add data elements to a dataset use g_dataset_id_set_data(),
72 * g_dataset_id_set_data_full(), g_dataset_set_data() and
73 * g_dataset_set_data_full().
75 * To get data elements from a dataset use g_dataset_id_get_data() and
76 * g_dataset_get_data().
78 * To iterate over all data elements in a dataset use
79 * g_dataset_foreach() (not thread-safe).
81 * To remove data elements from a dataset use
82 * g_dataset_id_remove_data() and g_dataset_remove_data().
84 * To destroy a dataset, use g_dataset_destroy().
89 * @title: Keyed Data Lists
90 * @short_description: lists of data elements which are accessible by a
91 * string or GQuark identifier
93 * Keyed data lists provide lists of arbitrary data elements which can
94 * be accessed either with a string or with a #GQuark corresponding to
97 * The #GQuark methods are quicker, since the strings have to be
98 * converted to #GQuarks anyway.
100 * Data lists are used for associating arbitrary data with #GObjects,
101 * using g_object_set_data() and related functions.
103 * To create a datalist, use g_datalist_init().
105 * To add data elements to a datalist use g_datalist_id_set_data(),
106 * g_datalist_id_set_data_full(), g_datalist_set_data() and
107 * g_datalist_set_data_full().
109 * To get data elements from a datalist use g_datalist_id_get_data()
110 * and g_datalist_get_data().
112 * To iterate over all data elements in a datalist use
113 * g_datalist_foreach() (not thread-safe).
115 * To remove data elements from a datalist use
116 * g_datalist_id_remove_data() and g_datalist_remove_data().
118 * To remove all data elements from a datalist, use g_datalist_clear().
124 * The #GData struct is an opaque data structure to represent a <link
125 * linkend="glib-Keyed-Data-Lists">Keyed Data List</link>. It should
126 * only be accessed via the following functions.
131 * @data: the data element.
133 * Specifies the type of function which is called when a data element
134 * is destroyed. It is passed the pointer to the data element and
135 * should free any memory and resources allocated for it.
138 /* --- defines --- */
139 #define G_QUARK_BLOCK_SIZE (2048)
141 #define G_DATALIST_FLAGS_MASK_INTERNAL 0x7
143 /* datalist pointer accesses have to be carried out atomically */
144 #define G_DATALIST_GET_POINTER(datalist) \
145 ((GData*) ((gsize) g_atomic_pointer_get (datalist) & ~(gsize) G_DATALIST_FLAGS_MASK_INTERNAL))
147 #define G_DATALIST_SET_POINTER(datalist, pointer) G_STMT_START { \
148 gpointer _oldv, _newv; \
150 _oldv = g_atomic_pointer_get (datalist); \
151 _newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK_INTERNAL) | (gsize) pointer); \
152 } while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, _oldv, _newv)); \
155 /* --- structures --- */
159 GDestroyNotify destroy;
162 typedef struct _GDataset GDataset;
165 guint32 len; /* Number of elements */
166 guint32 alloc; /* Number of allocated elements */
167 GDataElt data[1]; /* Flexible array */
172 gconstpointer location;
177 /* --- prototypes --- */
178 static inline GDataset* g_dataset_lookup (gconstpointer dataset_location);
179 static inline void g_datalist_clear_i (GData **datalist,
180 gboolean unlock_dataset);
181 static void g_dataset_destroy_internal (GDataset *dataset);
182 static inline gpointer g_data_set_internal (GData **datalist,
185 GDestroyNotify destroy_func,
187 static void g_data_initialize (void);
188 static inline GQuark g_quark_new (gchar *string);
192 * Each standalone GDataList is protected by a bitlock in the datalist pointer,
193 * which protects that modification of the non-flags part of the datalist pointer
194 * and the contents of the datalist.
196 * For GDataSet we have a global lock g_dataset_global that protects
197 * the global dataset hash and cache, and additionally it protects the
198 * datalist such that we can avoid to use the bit lock in a few places
202 /* --- variables --- */
203 G_LOCK_DEFINE_STATIC (g_dataset_global);
204 static GHashTable *g_dataset_location_ht = NULL;
205 static GDataset *g_dataset_cached = NULL; /* should this be
207 G_LOCK_DEFINE_STATIC (g_quark_global);
208 static GHashTable *g_quark_ht = NULL;
209 static gchar **g_quarks = NULL;
210 static int g_quark_seq_id = 0;
212 /* --- functions --- */
214 #define DATALIST_LOCK_BIT 2
217 g_datalist_lock (GData **datalist)
219 g_pointer_bit_lock ((void **)datalist, DATALIST_LOCK_BIT);
223 g_datalist_unlock (GData **datalist)
225 g_pointer_bit_unlock ((void **)datalist, DATALIST_LOCK_BIT);
228 /* Called with the datalist lock held, or the dataset global
229 * lock for dataset lists
232 g_datalist_clear_i (GData **datalist, gboolean unlock_dataset)
237 data = G_DATALIST_GET_POINTER (datalist);
238 G_DATALIST_SET_POINTER (datalist, NULL);
243 G_UNLOCK (g_dataset_global);
244 for (i = 0; i < data->len; i++)
246 if (data->data[i].data && data->data[i].destroy)
247 data->data[i].destroy (data->data[i].data);
250 G_LOCK (g_dataset_global);
259 * @datalist: a datalist.
261 * Frees all the data elements of the datalist. The data elements'
262 * destroy functions are called if they have been set.
265 g_datalist_clear (GData **datalist)
267 g_return_if_fail (datalist != NULL);
269 g_datalist_lock (datalist);
271 g_datalist_clear_i (datalist, FALSE);
273 g_datalist_unlock (datalist);
276 /* HOLDS: g_dataset_global_lock */
277 static inline GDataset*
278 g_dataset_lookup (gconstpointer dataset_location)
280 register GDataset *dataset;
282 if (g_dataset_cached && g_dataset_cached->location == dataset_location)
283 return g_dataset_cached;
285 dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
287 g_dataset_cached = dataset;
292 /* HOLDS: g_dataset_global_lock */
294 g_dataset_destroy_internal (GDataset *dataset)
296 register gconstpointer dataset_location;
298 dataset_location = dataset->location;
301 if (G_DATALIST_GET_POINTER(&dataset->datalist) == NULL)
303 if (dataset == g_dataset_cached)
304 g_dataset_cached = NULL;
305 g_hash_table_remove (g_dataset_location_ht, dataset_location);
306 g_slice_free (GDataset, dataset);
310 g_datalist_clear_i (&dataset->datalist, TRUE);
311 dataset = g_dataset_lookup (dataset_location);
317 * @dataset_location: the location identifying the dataset.
319 * Destroys the dataset, freeing all memory allocated, and calling any
320 * destroy functions set for data elements.
323 g_dataset_destroy (gconstpointer dataset_location)
325 g_return_if_fail (dataset_location != NULL);
327 G_LOCK (g_dataset_global);
328 if (g_dataset_location_ht)
330 register GDataset *dataset;
332 dataset = g_dataset_lookup (dataset_location);
334 g_dataset_destroy_internal (dataset);
336 G_UNLOCK (g_dataset_global);
339 /* HOLDS: g_dataset_global_lock if dataset != null */
340 static inline gpointer
341 g_data_set_internal (GData **datalist,
344 GDestroyNotify new_destroy_func,
348 GDataElt old, *data, *data_last, *data_end;
350 g_datalist_lock (datalist);
352 d = G_DATALIST_GET_POINTER (datalist);
354 if (new_data == NULL) /* remove */
359 data_last = data + d->len - 1;
360 while (data <= data_last)
362 if (data->key == key_id)
365 if (data != data_last)
369 /* We don't bother to shrink, but if all data are now gone
370 * we at least free the memory
374 G_DATALIST_SET_POINTER (datalist, NULL);
377 /* the dataset destruction *must* be done
378 * prior to invocation of the data destroy function
381 g_dataset_destroy_internal (dataset);
384 g_datalist_unlock (datalist);
386 /* We found and removed an old value
387 * the GData struct *must* already be unlinked
388 * when invoking the destroy function.
389 * we use (new_data==NULL && new_destroy_func!=NULL) as
390 * a special hint combination to "steal"
391 * data without destroy notification
393 if (old.destroy && !new_destroy_func)
396 G_UNLOCK (g_dataset_global);
397 old.destroy (old.data);
399 G_LOCK (g_dataset_global);
415 data_end = data + d->len;
416 while (data < data_end)
418 if (data->key == key_id)
422 data->data = new_data;
423 data->destroy = new_destroy_func;
424 g_datalist_unlock (datalist);
429 data->data = new_data;
430 data->destroy = new_destroy_func;
432 g_datalist_unlock (datalist);
434 /* We found and replaced an old value
435 * the GData struct *must* already be unlinked
436 * when invoking the destroy function.
439 G_UNLOCK (g_dataset_global);
440 old.destroy (old.data);
442 G_LOCK (g_dataset_global);
450 /* The key was not found, insert it */
454 d = g_malloc (sizeof (GData));
458 else if (d->len == d->alloc)
460 d->alloc = d->alloc * 2;
461 d = g_realloc (d, sizeof (GData) + (d->alloc - 1) * sizeof (GDataElt));
464 G_DATALIST_SET_POINTER (datalist, d);
466 d->data[d->len].key = key_id;
467 d->data[d->len].data = new_data;
468 d->data[d->len].destroy = new_destroy_func;
472 g_datalist_unlock (datalist);
479 * g_dataset_id_set_data_full:
480 * @dataset_location: the location identifying the dataset.
481 * @key_id: the #GQuark id to identify the data element.
482 * @data: the data element.
483 * @destroy_func: the function to call when the data element is
484 * removed. This function will be called with the data
485 * element and can be used to free any memory allocated
488 * Sets the data element associated with the given #GQuark id, and also
489 * the function to call when the data element is destroyed. Any
490 * previous data with the same key is removed, and its destroy function
494 * g_dataset_set_data_full:
495 * @l: the location identifying the dataset.
496 * @k: the string to identify the data element.
497 * @d: the data element.
498 * @f: the function to call when the data element is removed. This
499 * function will be called with the data element and can be used to
500 * free any memory allocated for it.
502 * Sets the data corresponding to the given string identifier, and the
503 * function to call when the data element is destroyed.
506 * g_dataset_id_set_data:
507 * @l: the location identifying the dataset.
508 * @k: the #GQuark id to identify the data element.
509 * @d: the data element.
511 * Sets the data element associated with the given #GQuark id. Any
512 * previous data with the same key is removed, and its destroy function
516 * g_dataset_set_data:
517 * @l: the location identifying the dataset.
518 * @k: the string to identify the data element.
519 * @d: the data element.
521 * Sets the data corresponding to the given string identifier.
524 * g_dataset_id_remove_data:
525 * @l: the location identifying the dataset.
526 * @k: the #GQuark id identifying the data element.
528 * Removes a data element from a dataset. The data element's destroy
529 * function is called if it has been set.
532 * g_dataset_remove_data:
533 * @l: the location identifying the dataset.
534 * @k: the string identifying the data element.
536 * Removes a data element corresponding to a string. Its destroy
537 * function is called if it has been set.
540 g_dataset_id_set_data_full (gconstpointer dataset_location,
543 GDestroyNotify destroy_func)
545 register GDataset *dataset;
547 g_return_if_fail (dataset_location != NULL);
549 g_return_if_fail (destroy_func == NULL);
553 g_return_if_fail (key_id > 0);
558 G_LOCK (g_dataset_global);
559 if (!g_dataset_location_ht)
560 g_data_initialize ();
562 dataset = g_dataset_lookup (dataset_location);
565 dataset = g_slice_new (GDataset);
566 dataset->location = dataset_location;
567 g_datalist_init (&dataset->datalist);
568 g_hash_table_insert (g_dataset_location_ht,
569 (gpointer) dataset->location,
573 g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
574 G_UNLOCK (g_dataset_global);
578 * g_datalist_id_set_data_full:
579 * @datalist: a datalist.
580 * @key_id: the #GQuark to identify the data element.
581 * @data: the data element or %NULL to remove any previous element
582 * corresponding to @key_id.
583 * @destroy_func: the function to call when the data element is
584 * removed. This function will be called with the data
585 * element and can be used to free any memory allocated
586 * for it. If @data is %NULL, then @destroy_func must
589 * Sets the data corresponding to the given #GQuark id, and the
590 * function to be called when the element is removed from the datalist.
591 * Any previous data with the same key is removed, and its destroy
592 * function is called.
595 * g_datalist_set_data_full:
597 * @k: the string to identify the data element.
598 * @d: the data element, or %NULL to remove any previous element
599 * corresponding to @k.
600 * @f: the function to call when the data element is removed. This
601 * function will be called with the data element and can be used to
602 * free any memory allocated for it. If @d is %NULL, then @f must
605 * Sets the data element corresponding to the given string identifier,
606 * and the function to be called when the data element is removed.
609 * g_datalist_id_set_data:
611 * @q: the #GQuark to identify the data element.
612 * @d: the data element, or %NULL to remove any previous element
613 * corresponding to @q.
615 * Sets the data corresponding to the given #GQuark id. Any previous
616 * data with the same key is removed, and its destroy function is
620 * g_datalist_set_data:
622 * @k: the string to identify the data element.
623 * @d: the data element, or %NULL to remove any previous element
624 * corresponding to @k.
626 * Sets the data element corresponding to the given string identifier.
629 * g_datalist_id_remove_data:
631 * @q: the #GQuark identifying the data element.
633 * Removes an element, using its #GQuark identifier.
636 * g_datalist_remove_data:
638 * @k: the string identifying the data element.
640 * Removes an element using its string identifier. The data element's
641 * destroy function is called if it has been set.
644 g_datalist_id_set_data_full (GData **datalist,
647 GDestroyNotify destroy_func)
649 g_return_if_fail (datalist != NULL);
651 g_return_if_fail (destroy_func == NULL);
655 g_return_if_fail (key_id > 0);
660 g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
664 * g_dataset_id_remove_no_notify:
665 * @dataset_location: the location identifying the dataset.
666 * @key_id: the #GQuark ID identifying the data element.
667 * @Returns: the data previously stored at @key_id, or %NULL if none.
669 * Removes an element, without calling its destroy notification
673 * g_dataset_remove_no_notify:
674 * @l: the location identifying the dataset.
675 * @k: the string identifying the data element.
677 * Removes an element, without calling its destroy notifier.
680 g_dataset_id_remove_no_notify (gconstpointer dataset_location,
683 gpointer ret_data = NULL;
685 g_return_val_if_fail (dataset_location != NULL, NULL);
687 G_LOCK (g_dataset_global);
688 if (key_id && g_dataset_location_ht)
692 dataset = g_dataset_lookup (dataset_location);
694 ret_data = g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
696 G_UNLOCK (g_dataset_global);
702 * g_datalist_id_remove_no_notify:
703 * @datalist: a datalist.
704 * @key_id: the #GQuark identifying a data element.
705 * @Returns: the data previously stored at @key_id, or %NULL if none.
707 * Removes an element, without calling its destroy notification
711 * g_datalist_remove_no_notify:
713 * @k: the string identifying the data element.
715 * Removes an element, without calling its destroy notifier.
718 g_datalist_id_remove_no_notify (GData **datalist,
721 gpointer ret_data = NULL;
723 g_return_val_if_fail (datalist != NULL, NULL);
726 ret_data = g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
732 * g_dataset_id_get_data:
733 * @dataset_location: the location identifying the dataset.
734 * @key_id: the #GQuark id to identify the data element.
735 * @Returns: the data element corresponding to the #GQuark, or %NULL if
738 * Gets the data element corresponding to a #GQuark.
741 * g_dataset_get_data:
742 * @l: the location identifying the dataset.
743 * @k: the string identifying the data element.
744 * @Returns: the data element corresponding to the string, or %NULL if
747 * Gets the data element corresponding to a string.
750 g_dataset_id_get_data (gconstpointer dataset_location,
753 gpointer retval = NULL;
755 g_return_val_if_fail (dataset_location != NULL, NULL);
757 G_LOCK (g_dataset_global);
758 if (key_id && g_dataset_location_ht)
762 dataset = g_dataset_lookup (dataset_location);
764 retval = g_datalist_id_get_data (&dataset->datalist, key_id);
766 G_UNLOCK (g_dataset_global);
772 * g_datalist_id_get_data:
773 * @datalist: a datalist.
774 * @key_id: the #GQuark identifying a data element.
775 * @Returns: the data element, or %NULL if it is not found.
777 * Retrieves the data element corresponding to @key_id.
780 g_datalist_id_get_data (GData **datalist,
785 g_return_val_if_fail (datalist != NULL, NULL);
789 GDataElt *data, *data_end;
791 g_datalist_lock (datalist);
793 d = G_DATALIST_GET_POINTER (datalist);
797 data_end = data + d->len;
798 while (data < data_end)
800 if (data->key == key_id)
809 g_datalist_unlock (datalist);
816 * g_datalist_get_data:
818 * @k: the string identifying a data element.
819 * @Returns: the data element, or %NULL if it is not found.
821 * Gets a data element, using its string identifer. This is slower than
822 * g_datalist_id_get_data() because it compares strings.
825 g_datalist_get_data (GData **datalist,
830 GDataElt *data, *data_end;
832 g_return_val_if_fail (datalist != NULL, NULL);
834 g_datalist_lock (datalist);
836 d = G_DATALIST_GET_POINTER (datalist);
840 data_end = data + d->len;
841 while (data < data_end)
843 if (strcmp (g_quark_to_string (data->key), key) == 0)
852 g_datalist_unlock (datalist);
859 * @key_id: the #GQuark id to identifying the data element.
860 * @data: the data element.
861 * @user_data: user data passed to g_dataset_foreach().
863 * Specifies the type of function passed to g_dataset_foreach(). It is
864 * called with each #GQuark id and associated data element, together
865 * with the @user_data parameter supplied to g_dataset_foreach().
870 * @dataset_location: the location identifying the dataset.
871 * @func: the function to call for each data element.
872 * @user_data: user data to pass to the function.
874 * Calls the given function for each data element which is associated
875 * with the given location. Note that this function is NOT thread-safe.
876 * So unless @datalist can be protected from any modifications during
877 * invocation of this function, it should not be called.
880 g_dataset_foreach (gconstpointer dataset_location,
881 GDataForeachFunc func,
884 register GDataset *dataset;
886 g_return_if_fail (dataset_location != NULL);
887 g_return_if_fail (func != NULL);
889 G_LOCK (g_dataset_global);
890 if (g_dataset_location_ht)
892 dataset = g_dataset_lookup (dataset_location);
893 G_UNLOCK (g_dataset_global);
895 g_datalist_foreach (&dataset->datalist, func, user_data);
899 G_UNLOCK (g_dataset_global);
904 * g_datalist_foreach:
905 * @datalist: a datalist.
906 * @func: the function to call for each data element.
907 * @user_data: user data to pass to the function.
909 * Calls the given function for each data element of the datalist. The
910 * function is called with each data element's #GQuark id and data,
911 * together with the given @user_data parameter. Note that this
912 * function is NOT thread-safe. So unless @datalist can be protected
913 * from any modifications during invocation of this function, it should
917 g_datalist_foreach (GData **datalist,
918 GDataForeachFunc func,
925 g_return_if_fail (datalist != NULL);
926 g_return_if_fail (func != NULL);
928 d = G_DATALIST_GET_POINTER (datalist);
932 /* We make a copy of the keys so that we can handle it changing
935 keys = g_new (GQuark, len);
936 for (i = 0; i < len; i++)
937 keys[i] = d->data[i].key;
939 for (i = 0; i < len; i++)
941 /* A previous callback might have removed a later item, so always check that
942 it still exists before calling */
943 d = G_DATALIST_GET_POINTER (datalist);
947 for (j = 0; j < d->len; j++)
949 if (d->data[j].key == keys[i]) {
950 func (d->data[i].key, d->data[i].data, user_data);
960 * @datalist: a pointer to a pointer to a datalist.
962 * Resets the datalist to %NULL. It does not free any memory or call
963 * any destroy functions.
966 g_datalist_init (GData **datalist)
968 g_return_if_fail (datalist != NULL);
970 g_atomic_pointer_set (datalist, NULL);
974 * g_datalist_set_flags:
975 * @datalist: pointer to the location that holds a list
976 * @flags: the flags to turn on. The values of the flags are
977 * restricted by %G_DATALIST_FLAGS_MASK (currently
978 * 3; giving two possible boolean flags).
979 * A value for @flags that doesn't fit within the mask is
982 * Turns on flag values for a data list. This function is used
983 * to keep a small number of boolean flags in an object with
984 * a data list without using any additional space. It is
985 * not generally useful except in circumstances where space
986 * is very tight. (It is used in the base #GObject type, for
992 g_datalist_set_flags (GData **datalist,
996 g_return_if_fail (datalist != NULL);
997 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
1001 oldvalue = g_atomic_pointer_get (datalist);
1003 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
1004 (gpointer) ((gsize) oldvalue | flags)));
1008 * g_datalist_unset_flags:
1009 * @datalist: pointer to the location that holds a list
1010 * @flags: the flags to turn off. The values of the flags are
1011 * restricted by %G_DATALIST_FLAGS_MASK (currently
1012 * 3: giving two possible boolean flags).
1013 * A value for @flags that doesn't fit within the mask is
1016 * Turns off flag values for a data list. See g_datalist_unset_flags()
1021 g_datalist_unset_flags (GData **datalist,
1025 g_return_if_fail (datalist != NULL);
1026 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
1030 oldvalue = g_atomic_pointer_get (datalist);
1032 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
1033 (gpointer) ((gsize) oldvalue & ~(gsize) flags)));
1037 * g_datalist_get_flags:
1038 * @datalist: pointer to the location that holds a list
1040 * Gets flags values packed in together with the datalist.
1041 * See g_datalist_set_flags().
1043 * Return value: the flags of the datalist
1048 g_datalist_get_flags (GData **datalist)
1050 g_return_val_if_fail (datalist != NULL, 0);
1052 return G_DATALIST_GET_FLAGS (datalist); /* atomic macro */
1055 /* HOLDS: g_dataset_global_lock */
1057 g_data_initialize (void)
1059 g_return_if_fail (g_dataset_location_ht == NULL);
1061 g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
1062 g_dataset_cached = NULL;
1068 * @short_description: a 2-way association between a string and a
1069 * unique integer identifier
1071 * Quarks are associations between strings and integer identifiers.
1072 * Given either the string or the #GQuark identifier it is possible to
1073 * retrieve the other.
1075 * Quarks are used for both <link
1076 * linkend="glib-datasets">Datasets</link> and <link
1077 * linkend="glib-keyed-data-lists">Keyed Data Lists</link>.
1079 * To create a new quark from a string, use g_quark_from_string() or
1080 * g_quark_from_static_string().
1082 * To find the string corresponding to a given #GQuark, use
1083 * g_quark_to_string().
1085 * To find the #GQuark corresponding to a given string, use
1086 * g_quark_try_string().
1088 * Another use for the string pool maintained for the quark functions
1089 * is string interning, using g_intern_string() or
1090 * g_intern_static_string(). An interned string is a canonical
1091 * representation for a string. One important advantage of interned
1092 * strings is that they can be compared for equality by a simple
1093 * pointer comparision, rather than using strcmp().
1099 * A GQuark is a non-zero integer which uniquely identifies a
1100 * particular string. A GQuark value of zero is associated to %NULL.
1104 * g_quark_try_string:
1105 * @string: a string.
1106 * @Returns: the #GQuark associated with the string, or 0 if @string is
1107 * %NULL or there is no #GQuark associated with it.
1109 * Gets the #GQuark associated with the given string, or 0 if string is
1110 * %NULL or it has no associated #GQuark.
1112 * If you want the GQuark to be created if it doesn't already exist,
1113 * use g_quark_from_string() or g_quark_from_static_string().
1116 g_quark_try_string (const gchar *string)
1123 G_LOCK (g_quark_global);
1125 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1126 G_UNLOCK (g_quark_global);
1131 #define QUARK_STRING_BLOCK_SIZE (4096 - sizeof (gsize))
1132 static char *quark_block = NULL;
1133 static int quark_block_offset = 0;
1135 /* HOLDS: g_quark_global_lock */
1137 quark_strdup(const gchar *string)
1142 len = strlen (string) + 1;
1144 /* For strings longer than half the block size, fall back
1145 to strdup so that we fill our blocks at least 50%. */
1146 if (len > QUARK_STRING_BLOCK_SIZE / 2)
1147 return g_strdup (string);
1149 if (quark_block == NULL ||
1150 QUARK_STRING_BLOCK_SIZE - quark_block_offset < len)
1152 quark_block = g_malloc (QUARK_STRING_BLOCK_SIZE);
1153 quark_block_offset = 0;
1156 copy = quark_block + quark_block_offset;
1157 memcpy (copy, string, len);
1158 quark_block_offset += len;
1163 /* HOLDS: g_quark_global_lock */
1164 static inline GQuark
1165 g_quark_from_string_internal (const gchar *string,
1171 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1175 quark = g_quark_new (duplicate ? quark_strdup (string) : (gchar *)string);
1176 TRACE(GLIB_QUARK_NEW(string, quark));
1183 * g_quark_from_string:
1184 * @string: a string.
1185 * @Returns: the #GQuark identifying the string, or 0 if @string is
1188 * Gets the #GQuark identifying the given string. If the string does
1189 * not currently have an associated #GQuark, a new #GQuark is created,
1190 * using a copy of the string.
1193 g_quark_from_string (const gchar *string)
1200 G_LOCK (g_quark_global);
1201 quark = g_quark_from_string_internal (string, TRUE);
1202 G_UNLOCK (g_quark_global);
1208 * g_quark_from_static_string:
1209 * @string: a string.
1210 * @Returns: the #GQuark identifying the string, or 0 if @string is
1213 * Gets the #GQuark identifying the given (static) string. If the
1214 * string does not currently have an associated #GQuark, a new #GQuark
1215 * is created, linked to the given string.
1217 * Note that this function is identical to g_quark_from_string() except
1218 * that if a new #GQuark is created the string itself is used rather
1219 * than a copy. This saves memory, but can only be used if the string
1220 * will <emphasis>always</emphasis> exist. It can be used with
1221 * statically allocated strings in the main program, but not with
1222 * statically allocated memory in dynamically loaded modules, if you
1223 * expect to ever unload the module again (e.g. do not use this
1224 * function in GTK+ theme engines).
1227 g_quark_from_static_string (const gchar *string)
1234 G_LOCK (g_quark_global);
1235 quark = g_quark_from_string_internal (string, FALSE);
1236 G_UNLOCK (g_quark_global);
1242 * g_quark_to_string:
1243 * @quark: a #GQuark.
1244 * @Returns: the string associated with the #GQuark.
1246 * Gets the string associated with the given #GQuark.
1248 G_CONST_RETURN gchar*
1249 g_quark_to_string (GQuark quark)
1251 gchar* result = NULL;
1255 quark_seq_id = g_atomic_int_get (&g_quark_seq_id);
1256 quarks = g_atomic_pointer_get (&g_quarks);
1258 if (quark < quark_seq_id)
1259 result = quarks[quark];
1264 /* HOLDS: g_quark_global_lock */
1265 static inline GQuark
1266 g_quark_new (gchar *string)
1269 gchar **g_quarks_new;
1271 if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
1273 g_quarks_new = g_new (gchar*, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
1274 if (g_quark_seq_id != 0)
1275 memcpy (g_quarks_new, g_quarks, sizeof (char *) * g_quark_seq_id);
1276 memset (g_quarks_new + g_quark_seq_id, 0, sizeof (char *) * G_QUARK_BLOCK_SIZE);
1277 /* This leaks the old quarks array. Its unfortunate, but it allows
1278 us to do lockless lookup of the arrays, and there shouldn't be that
1279 many quarks in an app */
1280 g_atomic_pointer_set (&g_quarks, g_quarks_new);
1284 g_assert (g_quark_seq_id == 0);
1285 g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
1286 g_quarks[g_quark_seq_id] = NULL;
1287 g_atomic_int_inc (&g_quark_seq_id);
1290 quark = g_quark_seq_id;
1291 g_atomic_pointer_set (&g_quarks[quark], string);
1292 g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
1293 g_atomic_int_inc (&g_quark_seq_id);
1302 * Returns a canonical representation for @string. Interned strings can
1303 * be compared for equality by comparing the pointers, instead of using strcmp().
1305 * Returns: a canonical representation for the string
1309 G_CONST_RETURN gchar*
1310 g_intern_string (const gchar *string)
1312 const gchar *result;
1318 G_LOCK (g_quark_global);
1319 quark = g_quark_from_string_internal (string, TRUE);
1320 result = g_quarks[quark];
1321 G_UNLOCK (g_quark_global);
1327 * g_intern_static_string:
1328 * @string: a static string
1330 * Returns a canonical representation for @string. Interned strings can
1331 * be compared for equality by comparing the pointers, instead of using strcmp().
1332 * g_intern_static_string() does not copy the string, therefore @string must
1333 * not be freed or modified.
1335 * Returns: a canonical representation for the string
1339 G_CONST_RETURN gchar*
1340 g_intern_static_string (const gchar *string)
1343 const gchar *result;
1348 G_LOCK (g_quark_global);
1349 quark = g_quark_from_string_internal (string, FALSE);
1350 result = g_quarks[quark];
1351 G_UNLOCK (g_quark_global);