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()
41 #include "gdatasetprivate.h"
44 #include "gstrfuncs.h"
45 #include "gtestutils.h"
47 #include "glib_trace.h"
52 * @short_description: associate groups of data elements with
53 * particular memory locations
55 * Datasets associate groups of data elements with particular memory
56 * locations. These are useful if you need to associate data with a
57 * structure returned from an external library. Since you cannot modify
58 * the structure, you use its location in memory as the key into a
59 * dataset, where you can associate any number of data elements with it.
61 * There are two forms of most of the dataset functions. The first form
62 * uses strings to identify the data elements associated with a
63 * location. The second form uses #GQuark identifiers, which are
64 * created with a call to g_quark_from_string() or
65 * g_quark_from_static_string(). The second form is quicker, since it
66 * does not require looking up the string in the hash table of #GQuark
69 * There is no function to create a dataset. It is automatically
70 * created as soon as you add elements to it.
72 * To add data elements to a dataset use g_dataset_id_set_data(),
73 * g_dataset_id_set_data_full(), g_dataset_set_data() and
74 * g_dataset_set_data_full().
76 * To get data elements from a dataset use g_dataset_id_get_data() and
77 * g_dataset_get_data().
79 * To iterate over all data elements in a dataset use
80 * g_dataset_foreach() (not thread-safe).
82 * To remove data elements from a dataset use
83 * g_dataset_id_remove_data() and g_dataset_remove_data().
85 * To destroy a dataset, use g_dataset_destroy().
90 * @title: Keyed Data Lists
91 * @short_description: lists of data elements which are accessible by a
92 * string or GQuark identifier
94 * Keyed data lists provide lists of arbitrary data elements which can
95 * be accessed either with a string or with a #GQuark corresponding to
98 * The #GQuark methods are quicker, since the strings have to be
99 * converted to #GQuarks anyway.
101 * Data lists are used for associating arbitrary data with #GObjects,
102 * using g_object_set_data() and related functions.
104 * To create a datalist, use g_datalist_init().
106 * To add data elements to a datalist use g_datalist_id_set_data(),
107 * g_datalist_id_set_data_full(), g_datalist_set_data() and
108 * g_datalist_set_data_full().
110 * To get data elements from a datalist use g_datalist_id_get_data()
111 * and g_datalist_get_data().
113 * To iterate over all data elements in a datalist use
114 * g_datalist_foreach() (not thread-safe).
116 * To remove data elements from a datalist use
117 * g_datalist_id_remove_data() and g_datalist_remove_data().
119 * To remove all data elements from a datalist, use g_datalist_clear().
125 * The #GData struct is an opaque data structure to represent a <link
126 * linkend="glib-Keyed-Data-Lists">Keyed Data List</link>. It should
127 * only be accessed via the following functions.
132 * @data: the data element.
134 * Specifies the type of function which is called when a data element
135 * is destroyed. It is passed the pointer to the data element and
136 * should free any memory and resources allocated for it.
139 /* --- defines --- */
140 #define G_QUARK_BLOCK_SIZE (2048)
142 #define G_DATALIST_FLAGS_MASK_INTERNAL 0x7
144 /* datalist pointer accesses have to be carried out atomically */
145 #define G_DATALIST_GET_POINTER(datalist) \
146 ((GData*) ((gsize) g_atomic_pointer_get (datalist) & ~(gsize) G_DATALIST_FLAGS_MASK_INTERNAL))
148 #define G_DATALIST_SET_POINTER(datalist, pointer) G_STMT_START { \
149 gpointer _oldv, _newv; \
151 _oldv = g_atomic_pointer_get (datalist); \
152 _newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK_INTERNAL) | (gsize) pointer); \
153 } while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, _oldv, _newv)); \
156 /* --- structures --- */
160 GDestroyNotify destroy;
163 typedef struct _GDataset GDataset;
166 guint32 len; /* Number of elements */
167 guint32 alloc; /* Number of allocated elements */
168 GDataElt data[1]; /* Flexible array */
173 gconstpointer location;
178 /* --- prototypes --- */
179 static inline GDataset* g_dataset_lookup (gconstpointer dataset_location);
180 static inline void g_datalist_clear_i (GData **datalist);
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)
237 data = G_DATALIST_GET_POINTER (datalist);
238 G_DATALIST_SET_POINTER (datalist, NULL);
242 G_UNLOCK (g_dataset_global);
243 for (i = 0; i < data->len; i++)
245 if (data->data[i].data && data->data[i].destroy)
246 data->data[i].destroy (data->data[i].data);
248 G_LOCK (g_dataset_global);
257 * @datalist: a datalist.
259 * Frees all the data elements of the datalist.
260 * The data elements' destroy functions are called
261 * if they have been set.
264 g_datalist_clear (GData **datalist)
269 g_return_if_fail (datalist != NULL);
271 g_datalist_lock (datalist);
273 data = G_DATALIST_GET_POINTER (datalist);
274 G_DATALIST_SET_POINTER (datalist, NULL);
276 g_datalist_unlock (datalist);
280 for (i = 0; i < data->len; i++)
282 if (data->data[i].data && data->data[i].destroy)
283 data->data[i].destroy (data->data[i].data);
290 /* HOLDS: g_dataset_global_lock */
291 static inline GDataset*
292 g_dataset_lookup (gconstpointer dataset_location)
294 register GDataset *dataset;
296 if (g_dataset_cached && g_dataset_cached->location == dataset_location)
297 return g_dataset_cached;
299 dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
301 g_dataset_cached = dataset;
306 /* HOLDS: g_dataset_global_lock */
308 g_dataset_destroy_internal (GDataset *dataset)
310 register gconstpointer dataset_location;
312 dataset_location = dataset->location;
315 if (G_DATALIST_GET_POINTER(&dataset->datalist) == NULL)
317 if (dataset == g_dataset_cached)
318 g_dataset_cached = NULL;
319 g_hash_table_remove (g_dataset_location_ht, dataset_location);
320 g_slice_free (GDataset, dataset);
324 g_datalist_clear_i (&dataset->datalist);
325 dataset = g_dataset_lookup (dataset_location);
331 * @dataset_location: the location identifying the dataset.
333 * Destroys the dataset, freeing all memory allocated, and calling any
334 * destroy functions set for data elements.
337 g_dataset_destroy (gconstpointer dataset_location)
339 g_return_if_fail (dataset_location != NULL);
341 G_LOCK (g_dataset_global);
342 if (g_dataset_location_ht)
344 register GDataset *dataset;
346 dataset = g_dataset_lookup (dataset_location);
348 g_dataset_destroy_internal (dataset);
350 G_UNLOCK (g_dataset_global);
353 /* HOLDS: g_dataset_global_lock if dataset != null */
354 static inline gpointer
355 g_data_set_internal (GData **datalist,
358 GDestroyNotify new_destroy_func,
362 GDataElt old, *data, *data_last, *data_end;
364 g_datalist_lock (datalist);
366 d = G_DATALIST_GET_POINTER (datalist);
368 if (new_data == NULL) /* remove */
373 data_last = data + d->len - 1;
374 while (data <= data_last)
376 if (data->key == key_id)
379 if (data != data_last)
383 /* We don't bother to shrink, but if all data are now gone
384 * we at least free the memory
388 G_DATALIST_SET_POINTER (datalist, NULL);
391 /* the dataset destruction *must* be done
392 * prior to invocation of the data destroy function
395 g_dataset_destroy_internal (dataset);
398 g_datalist_unlock (datalist);
400 /* We found and removed an old value
401 * the GData struct *must* already be unlinked
402 * when invoking the destroy function.
403 * we use (new_data==NULL && new_destroy_func!=NULL) as
404 * a special hint combination to "steal"
405 * data without destroy notification
407 if (old.destroy && !new_destroy_func)
410 G_UNLOCK (g_dataset_global);
411 old.destroy (old.data);
413 G_LOCK (g_dataset_global);
429 data_end = data + d->len;
430 while (data < data_end)
432 if (data->key == key_id)
436 data->data = new_data;
437 data->destroy = new_destroy_func;
438 g_datalist_unlock (datalist);
443 data->data = new_data;
444 data->destroy = new_destroy_func;
446 g_datalist_unlock (datalist);
448 /* We found and replaced an old value
449 * the GData struct *must* already be unlinked
450 * when invoking the destroy function.
453 G_UNLOCK (g_dataset_global);
454 old.destroy (old.data);
456 G_LOCK (g_dataset_global);
464 /* The key was not found, insert it */
468 d = g_malloc (sizeof (GData));
472 else if (d->len == d->alloc)
474 d->alloc = d->alloc * 2;
475 d = g_realloc (d, sizeof (GData) + (d->alloc - 1) * sizeof (GDataElt));
478 G_DATALIST_SET_POINTER (datalist, d);
480 d->data[d->len].key = key_id;
481 d->data[d->len].data = new_data;
482 d->data[d->len].destroy = new_destroy_func;
486 g_datalist_unlock (datalist);
493 * g_dataset_id_set_data_full:
494 * @dataset_location: the location identifying the dataset.
495 * @key_id: the #GQuark id to identify the data element.
496 * @data: the data element.
497 * @destroy_func: the function to call when the data element is
498 * removed. This function will be called with the data
499 * element and can be used to free any memory allocated
502 * Sets the data element associated with the given #GQuark id, and also
503 * the function to call when the data element is destroyed. Any
504 * previous data with the same key is removed, and its destroy function
508 * g_dataset_set_data_full:
509 * @l: the location identifying the dataset.
510 * @k: the string to identify the data element.
511 * @d: the data element.
512 * @f: the function to call when the data element is removed. This
513 * function will be called with the data element and can be used to
514 * free any memory allocated for it.
516 * Sets the data corresponding to the given string identifier, and the
517 * function to call when the data element is destroyed.
520 * g_dataset_id_set_data:
521 * @l: the location identifying the dataset.
522 * @k: the #GQuark id to identify the data element.
523 * @d: the data element.
525 * Sets the data element associated with the given #GQuark id. Any
526 * previous data with the same key is removed, and its destroy function
530 * g_dataset_set_data:
531 * @l: the location identifying the dataset.
532 * @k: the string to identify the data element.
533 * @d: the data element.
535 * Sets the data corresponding to the given string identifier.
538 * g_dataset_id_remove_data:
539 * @l: the location identifying the dataset.
540 * @k: the #GQuark id identifying the data element.
542 * Removes a data element from a dataset. The data element's destroy
543 * function is called if it has been set.
546 * g_dataset_remove_data:
547 * @l: the location identifying the dataset.
548 * @k: the string identifying the data element.
550 * Removes a data element corresponding to a string. Its destroy
551 * function is called if it has been set.
554 g_dataset_id_set_data_full (gconstpointer dataset_location,
557 GDestroyNotify destroy_func)
559 register GDataset *dataset;
561 g_return_if_fail (dataset_location != NULL);
563 g_return_if_fail (destroy_func == NULL);
567 g_return_if_fail (key_id > 0);
572 G_LOCK (g_dataset_global);
573 if (!g_dataset_location_ht)
574 g_data_initialize ();
576 dataset = g_dataset_lookup (dataset_location);
579 dataset = g_slice_new (GDataset);
580 dataset->location = dataset_location;
581 g_datalist_init (&dataset->datalist);
582 g_hash_table_insert (g_dataset_location_ht,
583 (gpointer) dataset->location,
587 g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
588 G_UNLOCK (g_dataset_global);
592 * g_datalist_id_set_data_full:
593 * @datalist: a datalist.
594 * @key_id: the #GQuark to identify the data element.
595 * @data: the data element or %NULL to remove any previous element
596 * corresponding to @key_id.
597 * @destroy_func: the function to call when the data element is
598 * removed. This function will be called with the data
599 * element and can be used to free any memory allocated
600 * for it. If @data is %NULL, then @destroy_func must
603 * Sets the data corresponding to the given #GQuark id, and the
604 * function to be called when the element is removed from the datalist.
605 * Any previous data with the same key is removed, and its destroy
606 * function is called.
609 * g_datalist_set_data_full:
611 * @k: the string to identify the data element.
612 * @d: the data element, or %NULL to remove any previous element
613 * corresponding to @k.
614 * @f: the function to call when the data element is removed. This
615 * function will be called with the data element and can be used to
616 * free any memory allocated for it. If @d is %NULL, then @f must
619 * Sets the data element corresponding to the given string identifier,
620 * and the function to be called when the data element is removed.
623 * g_datalist_id_set_data:
625 * @q: the #GQuark to identify the data element.
626 * @d: the data element, or %NULL to remove any previous element
627 * corresponding to @q.
629 * Sets the data corresponding to the given #GQuark id. Any previous
630 * data with the same key is removed, and its destroy function is
634 * g_datalist_set_data:
636 * @k: the string to identify the data element.
637 * @d: the data element, or %NULL to remove any previous element
638 * corresponding to @k.
640 * Sets the data element corresponding to the given string identifier.
643 * g_datalist_id_remove_data:
645 * @q: the #GQuark identifying the data element.
647 * Removes an element, using its #GQuark identifier.
650 * g_datalist_remove_data:
652 * @k: the string identifying the data element.
654 * Removes an element using its string identifier. The data element's
655 * destroy function is called if it has been set.
658 g_datalist_id_set_data_full (GData **datalist,
661 GDestroyNotify destroy_func)
663 g_return_if_fail (datalist != NULL);
665 g_return_if_fail (destroy_func == NULL);
669 g_return_if_fail (key_id > 0);
674 g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
678 * g_dataset_id_remove_no_notify:
679 * @dataset_location: the location identifying the dataset.
680 * @key_id: the #GQuark ID identifying the data element.
681 * @Returns: the data previously stored at @key_id, or %NULL if none.
683 * Removes an element, without calling its destroy notification
687 * g_dataset_remove_no_notify:
688 * @l: the location identifying the dataset.
689 * @k: the string identifying the data element.
691 * Removes an element, without calling its destroy notifier.
694 g_dataset_id_remove_no_notify (gconstpointer dataset_location,
697 gpointer ret_data = NULL;
699 g_return_val_if_fail (dataset_location != NULL, NULL);
701 G_LOCK (g_dataset_global);
702 if (key_id && g_dataset_location_ht)
706 dataset = g_dataset_lookup (dataset_location);
708 ret_data = g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
710 G_UNLOCK (g_dataset_global);
716 * g_datalist_id_remove_no_notify:
717 * @datalist: a datalist.
718 * @key_id: the #GQuark identifying a data element.
719 * @Returns: the data previously stored at @key_id, or %NULL if none.
721 * Removes an element, without calling its destroy notification
725 * g_datalist_remove_no_notify:
727 * @k: the string identifying the data element.
729 * Removes an element, without calling its destroy notifier.
732 g_datalist_id_remove_no_notify (GData **datalist,
735 gpointer ret_data = NULL;
737 g_return_val_if_fail (datalist != NULL, NULL);
740 ret_data = g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
746 * g_dataset_id_get_data:
747 * @dataset_location: the location identifying the dataset.
748 * @key_id: the #GQuark id to identify the data element.
749 * @Returns: the data element corresponding to the #GQuark, or %NULL if
752 * Gets the data element corresponding to a #GQuark.
755 * g_dataset_get_data:
756 * @l: the location identifying the dataset.
757 * @k: the string identifying the data element.
758 * @Returns: the data element corresponding to the string, or %NULL if
761 * Gets the data element corresponding to a string.
764 g_dataset_id_get_data (gconstpointer dataset_location,
767 gpointer retval = NULL;
769 g_return_val_if_fail (dataset_location != NULL, NULL);
771 G_LOCK (g_dataset_global);
772 if (key_id && g_dataset_location_ht)
776 dataset = g_dataset_lookup (dataset_location);
778 retval = g_datalist_id_get_data (&dataset->datalist, key_id);
780 G_UNLOCK (g_dataset_global);
786 * g_datalist_id_get_data:
787 * @datalist: a datalist.
788 * @key_id: the #GQuark identifying a data element.
789 * @Returns: the data element, or %NULL if it is not found.
791 * Retrieves the data element corresponding to @key_id.
794 g_datalist_id_get_data (GData **datalist,
799 g_return_val_if_fail (datalist != NULL, NULL);
803 GDataElt *data, *data_end;
805 g_datalist_lock (datalist);
807 d = G_DATALIST_GET_POINTER (datalist);
811 data_end = data + d->len;
812 while (data < data_end)
814 if (data->key == key_id)
823 g_datalist_unlock (datalist);
830 * g_datalist_get_data:
831 * @datalist: a datalist.
832 * @key: the string identifying a data element.
833 * @Returns: the data element, or %NULL if it is not found.
835 * Gets a data element, using its string identifer. This is slower than
836 * g_datalist_id_get_data() because it compares strings.
839 g_datalist_get_data (GData **datalist,
844 GDataElt *data, *data_end;
846 g_return_val_if_fail (datalist != NULL, NULL);
848 g_datalist_lock (datalist);
850 d = G_DATALIST_GET_POINTER (datalist);
854 data_end = data + d->len;
855 while (data < data_end)
857 if (strcmp (g_quark_to_string (data->key), key) == 0)
866 g_datalist_unlock (datalist);
873 * @key_id: the #GQuark id to identifying the data element.
874 * @data: the data element.
875 * @user_data: user data passed to g_dataset_foreach().
877 * Specifies the type of function passed to g_dataset_foreach(). It is
878 * called with each #GQuark id and associated data element, together
879 * with the @user_data parameter supplied to g_dataset_foreach().
884 * @dataset_location: the location identifying the dataset.
885 * @func: the function to call for each data element.
886 * @user_data: user data to pass to the function.
888 * Calls the given function for each data element which is associated
889 * with the given location. Note that this function is NOT thread-safe.
890 * So unless @datalist can be protected from any modifications during
891 * invocation of this function, it should not be called.
894 g_dataset_foreach (gconstpointer dataset_location,
895 GDataForeachFunc func,
898 register GDataset *dataset;
900 g_return_if_fail (dataset_location != NULL);
901 g_return_if_fail (func != NULL);
903 G_LOCK (g_dataset_global);
904 if (g_dataset_location_ht)
906 dataset = g_dataset_lookup (dataset_location);
907 G_UNLOCK (g_dataset_global);
909 g_datalist_foreach (&dataset->datalist, func, user_data);
913 G_UNLOCK (g_dataset_global);
918 * g_datalist_foreach:
919 * @datalist: a datalist.
920 * @func: the function to call for each data element.
921 * @user_data: user data to pass to the function.
923 * Calls the given function for each data element of the datalist. The
924 * function is called with each data element's #GQuark id and data,
925 * together with the given @user_data parameter. Note that this
926 * function is NOT thread-safe. So unless @datalist can be protected
927 * from any modifications during invocation of this function, it should
931 g_datalist_foreach (GData **datalist,
932 GDataForeachFunc func,
939 g_return_if_fail (datalist != NULL);
940 g_return_if_fail (func != NULL);
942 d = G_DATALIST_GET_POINTER (datalist);
946 /* We make a copy of the keys so that we can handle it changing
949 keys = g_new (GQuark, len);
950 for (i = 0; i < len; i++)
951 keys[i] = d->data[i].key;
953 for (i = 0; i < len; i++)
955 /* A previous callback might have removed a later item, so always check that
956 it still exists before calling */
957 d = G_DATALIST_GET_POINTER (datalist);
961 for (j = 0; j < d->len; j++)
963 if (d->data[j].key == keys[i]) {
964 func (d->data[i].key, d->data[i].data, user_data);
974 * @datalist: a pointer to a pointer to a datalist.
976 * Resets the datalist to %NULL. It does not free any memory or call
977 * any destroy functions.
980 g_datalist_init (GData **datalist)
982 g_return_if_fail (datalist != NULL);
984 g_atomic_pointer_set (datalist, NULL);
988 * g_datalist_set_flags:
989 * @datalist: pointer to the location that holds a list
990 * @flags: the flags to turn on. The values of the flags are
991 * restricted by %G_DATALIST_FLAGS_MASK (currently
992 * 3; giving two possible boolean flags).
993 * A value for @flags that doesn't fit within the mask is
996 * Turns on flag values for a data list. This function is used
997 * to keep a small number of boolean flags in an object with
998 * a data list without using any additional space. It is
999 * not generally useful except in circumstances where space
1000 * is very tight. (It is used in the base #GObject type, for
1006 g_datalist_set_flags (GData **datalist,
1009 g_return_if_fail (datalist != NULL);
1010 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
1012 g_atomic_pointer_or (datalist, (gsize)flags);
1016 * g_datalist_unset_flags:
1017 * @datalist: pointer to the location that holds a list
1018 * @flags: the flags to turn off. The values of the flags are
1019 * restricted by %G_DATALIST_FLAGS_MASK (currently
1020 * 3: giving two possible boolean flags).
1021 * A value for @flags that doesn't fit within the mask is
1024 * Turns off flag values for a data list. See g_datalist_unset_flags()
1029 g_datalist_unset_flags (GData **datalist,
1032 g_return_if_fail (datalist != NULL);
1033 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
1035 g_atomic_pointer_and (datalist, ~(gsize)flags);
1039 * g_datalist_get_flags:
1040 * @datalist: pointer to the location that holds a list
1042 * Gets flags values packed in together with the datalist.
1043 * See g_datalist_set_flags().
1045 * Return value: the flags of the datalist
1050 g_datalist_get_flags (GData **datalist)
1052 g_return_val_if_fail (datalist != NULL, 0);
1054 return G_DATALIST_GET_FLAGS (datalist); /* atomic macro */
1057 /* HOLDS: g_dataset_global_lock */
1059 g_data_initialize (void)
1061 g_return_if_fail (g_dataset_location_ht == NULL);
1063 g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
1064 g_dataset_cached = NULL;
1070 * @short_description: a 2-way association between a string and a
1071 * unique integer identifier
1073 * Quarks are associations between strings and integer identifiers.
1074 * Given either the string or the #GQuark identifier it is possible to
1075 * retrieve the other.
1077 * Quarks are used for both <link
1078 * linkend="glib-Datasets">Datasets</link> and <link
1079 * linkend="glib-Keyed-Data-Lists">Keyed Data Lists</link>.
1081 * To create a new quark from a string, use g_quark_from_string() or
1082 * g_quark_from_static_string().
1084 * To find the string corresponding to a given #GQuark, use
1085 * g_quark_to_string().
1087 * To find the #GQuark corresponding to a given string, use
1088 * g_quark_try_string().
1090 * Another use for the string pool maintained for the quark functions
1091 * is string interning, using g_intern_string() or
1092 * g_intern_static_string(). An interned string is a canonical
1093 * representation for a string. One important advantage of interned
1094 * strings is that they can be compared for equality by a simple
1095 * pointer comparison, rather than using strcmp().
1101 * A GQuark is a non-zero integer which uniquely identifies a
1102 * particular string. A GQuark value of zero is associated to %NULL.
1106 * g_quark_try_string:
1107 * @string: (allow-none): a string.
1108 * @Returns: the #GQuark associated with the string, or 0 if @string is
1109 * %NULL or there is no #GQuark associated with it.
1111 * Gets the #GQuark associated with the given string, or 0 if string is
1112 * %NULL or it has no associated #GQuark.
1114 * If you want the GQuark to be created if it doesn't already exist,
1115 * use g_quark_from_string() or g_quark_from_static_string().
1118 g_quark_try_string (const gchar *string)
1125 G_LOCK (g_quark_global);
1127 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1128 G_UNLOCK (g_quark_global);
1133 #define QUARK_STRING_BLOCK_SIZE (4096 - sizeof (gsize))
1134 static char *quark_block = NULL;
1135 static int quark_block_offset = 0;
1137 /* HOLDS: g_quark_global_lock */
1139 quark_strdup(const gchar *string)
1144 len = strlen (string) + 1;
1146 /* For strings longer than half the block size, fall back
1147 to strdup so that we fill our blocks at least 50%. */
1148 if (len > QUARK_STRING_BLOCK_SIZE / 2)
1149 return g_strdup (string);
1151 if (quark_block == NULL ||
1152 QUARK_STRING_BLOCK_SIZE - quark_block_offset < len)
1154 quark_block = g_malloc (QUARK_STRING_BLOCK_SIZE);
1155 quark_block_offset = 0;
1158 copy = quark_block + quark_block_offset;
1159 memcpy (copy, string, len);
1160 quark_block_offset += len;
1165 /* HOLDS: g_quark_global_lock */
1166 static inline GQuark
1167 g_quark_from_string_internal (const gchar *string,
1173 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1177 quark = g_quark_new (duplicate ? quark_strdup (string) : (gchar *)string);
1178 TRACE(GLIB_QUARK_NEW(string, quark));
1185 * g_quark_from_string:
1186 * @string: (allow-none): a string.
1187 * @Returns: the #GQuark identifying the string, or 0 if @string is
1190 * Gets the #GQuark identifying the given string. If the string does
1191 * not currently have an associated #GQuark, a new #GQuark is created,
1192 * using a copy of the string.
1195 g_quark_from_string (const gchar *string)
1202 G_LOCK (g_quark_global);
1203 quark = g_quark_from_string_internal (string, TRUE);
1204 G_UNLOCK (g_quark_global);
1210 * g_quark_from_static_string:
1211 * @string: (allow-none): a string.
1212 * @Returns: the #GQuark identifying the string, or 0 if @string is
1215 * Gets the #GQuark identifying the given (static) string. If the
1216 * string does not currently have an associated #GQuark, a new #GQuark
1217 * is created, linked to the given string.
1219 * Note that this function is identical to g_quark_from_string() except
1220 * that if a new #GQuark is created the string itself is used rather
1221 * than a copy. This saves memory, but can only be used if the string
1222 * will <emphasis>always</emphasis> exist. It can be used with
1223 * statically allocated strings in the main program, but not with
1224 * statically allocated memory in dynamically loaded modules, if you
1225 * expect to ever unload the module again (e.g. do not use this
1226 * function in GTK+ theme engines).
1229 g_quark_from_static_string (const gchar *string)
1236 G_LOCK (g_quark_global);
1237 quark = g_quark_from_string_internal (string, FALSE);
1238 G_UNLOCK (g_quark_global);
1244 * g_quark_to_string:
1245 * @quark: a #GQuark.
1246 * @Returns: the string associated with the #GQuark.
1248 * Gets the string associated with the given #GQuark.
1251 g_quark_to_string (GQuark quark)
1253 gchar* result = NULL;
1257 quark_seq_id = g_atomic_int_get (&g_quark_seq_id);
1258 quarks = g_atomic_pointer_get (&g_quarks);
1260 if (quark < quark_seq_id)
1261 result = quarks[quark];
1266 /* HOLDS: g_quark_global_lock */
1267 static inline GQuark
1268 g_quark_new (gchar *string)
1271 gchar **g_quarks_new;
1273 if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
1275 g_quarks_new = g_new (gchar*, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
1276 if (g_quark_seq_id != 0)
1277 memcpy (g_quarks_new, g_quarks, sizeof (char *) * g_quark_seq_id);
1278 memset (g_quarks_new + g_quark_seq_id, 0, sizeof (char *) * G_QUARK_BLOCK_SIZE);
1279 /* This leaks the old quarks array. Its unfortunate, but it allows
1280 us to do lockless lookup of the arrays, and there shouldn't be that
1281 many quarks in an app */
1282 g_atomic_pointer_set (&g_quarks, g_quarks_new);
1286 g_assert (g_quark_seq_id == 0);
1287 g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
1288 g_quarks[g_quark_seq_id] = NULL;
1289 g_atomic_int_inc (&g_quark_seq_id);
1292 quark = g_quark_seq_id;
1293 g_atomic_pointer_set (&g_quarks[quark], string);
1294 g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
1295 g_atomic_int_inc (&g_quark_seq_id);
1302 * @string: (allow-none): a string
1304 * Returns a canonical representation for @string. Interned strings can
1305 * be compared for equality by comparing the pointers, instead of using strcmp().
1307 * Returns: a canonical representation for the string
1312 g_intern_string (const gchar *string)
1314 const gchar *result;
1320 G_LOCK (g_quark_global);
1321 quark = g_quark_from_string_internal (string, TRUE);
1322 result = g_quarks[quark];
1323 G_UNLOCK (g_quark_global);
1329 * g_intern_static_string:
1330 * @string: (allow-none): a static string
1332 * Returns a canonical representation for @string. Interned strings can
1333 * be compared for equality by comparing the pointers, instead of using strcmp().
1334 * g_intern_static_string() does not copy the string, therefore @string must
1335 * not be freed or modified.
1337 * Returns: a canonical representation for the string
1342 g_intern_static_string (const gchar *string)
1345 const gchar *result;
1350 G_LOCK (g_quark_global);
1351 quark = g_quark_from_string_internal (string, FALSE);
1352 result = g_quarks[quark];
1353 G_UNLOCK (g_quark_global);