glib/libglib/src/gdataset.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     7  *
       
     8  * This library is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Lesser General Public
       
    10  * License as published by the Free Software Foundation; either
       
    11  * version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  * This library is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16  * Lesser General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Lesser General Public
       
    19  * License along with this library; if not, write to the Free Software
       
    20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 /*
       
    24  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
       
    25  * file for a list of people on the GLib Team.  See the ChangeLog
       
    26  * files for a list of changes.  These files are distributed with
       
    27  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
       
    28  */
       
    29 
       
    30 /* 
       
    31  * MT safe ; except for g_data*_foreach()
       
    32  */
       
    33 
       
    34 #include "config.h"
       
    35 
       
    36 #include <string.h>
       
    37 
       
    38 #include "glib.h"
       
    39 #include "galias.h"
       
    40 #include "gdatasetprivate.h"
       
    41 
       
    42 #ifdef __SYMBIAN32__
       
    43 #include <glib_wsd.h>
       
    44 #endif /* __SYMBIAN32__ */
       
    45 
       
    46 #if EMULATOR
       
    47 #define g_thread_functions_for_glib_use (*_g_thread_functions_for_glib_use())
       
    48 #define g_thread_use_default_impl (*_g_thread_use_default_impl())
       
    49 #endif /* EMULATOR */
       
    50 
       
    51 /* --- defines --- */
       
    52 #define	G_QUARK_BLOCK_SIZE			(512)
       
    53 
       
    54 /* datalist pointer accesses vae to be carried out atomically */
       
    55 #define G_DATALIST_GET_POINTER(datalist)						\
       
    56   ((GData*) ((gsize) g_atomic_pointer_get ((gpointer*) datalist) & ~(gsize) G_DATALIST_FLAGS_MASK))
       
    57 
       
    58 #define G_DATALIST_SET_POINTER(datalist, pointer)       G_STMT_START {                  \
       
    59   gpointer _oldv, _newv;                                                                \
       
    60   do {                                                                                  \
       
    61     _oldv = g_atomic_pointer_get (datalist);                                            \
       
    62     _newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK) | (gsize) pointer);     \
       
    63   } while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, _oldv, _newv));   \
       
    64 } G_STMT_END
       
    65 
       
    66 /* --- structures --- */
       
    67 #if !(EMULATOR)
       
    68 typedef struct _GDataset GDataset;
       
    69 #endif /* EMULATOR */
       
    70 struct _GData
       
    71 {
       
    72   GData *next;
       
    73   GQuark id;
       
    74   gpointer data;
       
    75   GDestroyNotify destroy_func;
       
    76 };
       
    77 
       
    78 #if !(EMULATOR)
       
    79 struct _GDataset
       
    80 {
       
    81   gconstpointer location;
       
    82   GData        *datalist;
       
    83 };
       
    84 #endif /* EMULATOR */
       
    85 
       
    86 
       
    87 /* --- prototypes --- */
       
    88 static inline GDataset*	g_dataset_lookup		(gconstpointer	  dataset_location);
       
    89 static inline void	g_datalist_clear_i		(GData		**datalist);
       
    90 static void		g_dataset_destroy_internal	(GDataset	 *dataset);
       
    91 static inline gpointer	g_data_set_internal		(GData     	**datalist,
       
    92 							 GQuark   	  key_id,
       
    93 							 gpointer         data,
       
    94 							 GDestroyNotify   destroy_func,
       
    95 							 GDataset	 *dataset);
       
    96 static void		g_data_initialize		(void);
       
    97 static inline GQuark	g_quark_new			(gchar  	*string);
       
    98 
       
    99 
       
   100 /* --- variables --- */
       
   101 #if EMULATOR
       
   102 
       
   103 PLS_MACRO(g_dataset_global,gdataset,GStaticMutex)
       
   104 PLS(g_dataset_location_ht,gdataset,GHashTable *)
       
   105 PLS(g_dataset_cached,gdataset,GDataset *)
       
   106 PLS_MACRO(g_quark_global,gdataset,GStaticMutex)
       
   107 PLS(g_quark_ht,gdataset,GHashTable *)
       
   108 PLS(g_quarks,gdataset,gchar **)
       
   109 PLS(g_quark_seq_id,gdataset,GQuark)
       
   110 
       
   111 #define g__g_dataset_global_lock (*FUNCTION_NAME_MACRO(g_dataset_global,gdataset)())
       
   112 #define g_dataset_location_ht (*FUNCTION_NAME(g_dataset_location_ht,gdataset)())
       
   113 #define g_dataset_cached (*FUNCTION_NAME(g_dataset_cached,gdataset)())
       
   114 #define g__g_quark_global_lock (*FUNCTION_NAME_MACRO(g_quark_global,gdataset)())
       
   115 #define g_quark_ht (*FUNCTION_NAME(g_quark_ht,gdataset)())
       
   116 #define g_quarks (*FUNCTION_NAME(g_quarks,gdataset)())
       
   117 #define g_quark_seq_id (*FUNCTION_NAME(g_quark_seq_id,gdataset)())
       
   118 
       
   119 #else
       
   120 
       
   121 G_LOCK_DEFINE_STATIC (g_dataset_global);
       
   122 static GHashTable   *g_dataset_location_ht = NULL;
       
   123 static GDataset     *g_dataset_cached = NULL; /* should this be
       
   124 						 threadspecific? */
       
   125 G_LOCK_DEFINE_STATIC (g_quark_global);
       
   126 static GHashTable   *g_quark_ht = NULL;
       
   127 static gchar       **g_quarks = NULL;
       
   128 static GQuark        g_quark_seq_id = 0;
       
   129 
       
   130 #endif /* EMULATOR */
       
   131 
       
   132 /* --- functions --- */
       
   133 
       
   134 /* HOLDS: g_dataset_global_lock */
       
   135 static inline void
       
   136 g_datalist_clear_i (GData **datalist)
       
   137 {
       
   138   register GData *list;
       
   139   
       
   140   /* unlink *all* items before walking their destructors
       
   141    */
       
   142   list = G_DATALIST_GET_POINTER (datalist);
       
   143   G_DATALIST_SET_POINTER (datalist, NULL);
       
   144   
       
   145   while (list)
       
   146     {
       
   147       register GData *prev;
       
   148       
       
   149       prev = list;
       
   150       list = prev->next;
       
   151       
       
   152       if (prev->destroy_func)
       
   153 	{
       
   154 	  G_UNLOCK (g_dataset_global);
       
   155 	  prev->destroy_func (prev->data);
       
   156 	  G_LOCK (g_dataset_global);
       
   157 	}
       
   158       
       
   159       g_slice_free (GData, prev);
       
   160     }
       
   161 }
       
   162 
       
   163 EXPORT_C void
       
   164 g_datalist_clear (GData **datalist)
       
   165 {
       
   166   g_return_if_fail (datalist != NULL);
       
   167   
       
   168   G_LOCK (g_dataset_global);
       
   169   if (!g_dataset_location_ht)
       
   170     g_data_initialize ();
       
   171 
       
   172   while (G_DATALIST_GET_POINTER (datalist))
       
   173     g_datalist_clear_i (datalist);
       
   174   G_UNLOCK (g_dataset_global);
       
   175 }
       
   176 
       
   177 /* HOLDS: g_dataset_global_lock */
       
   178 static inline GDataset*
       
   179 g_dataset_lookup (gconstpointer	dataset_location)
       
   180 {
       
   181   register GDataset *dataset;
       
   182   
       
   183   if (g_dataset_cached && g_dataset_cached->location == dataset_location)
       
   184     return g_dataset_cached;
       
   185   
       
   186   dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
       
   187   if (dataset)
       
   188     g_dataset_cached = dataset;
       
   189   
       
   190   return dataset;
       
   191 }
       
   192 
       
   193 /* HOLDS: g_dataset_global_lock */
       
   194 static void
       
   195 g_dataset_destroy_internal (GDataset *dataset)
       
   196 {
       
   197   register gconstpointer dataset_location;
       
   198   
       
   199   dataset_location = dataset->location;
       
   200   while (dataset)
       
   201     {
       
   202       if (!dataset->datalist)
       
   203 	{
       
   204 	  if (dataset == g_dataset_cached)
       
   205 	    g_dataset_cached = NULL;
       
   206 	  g_hash_table_remove (g_dataset_location_ht, dataset_location);
       
   207 	  g_slice_free (GDataset, dataset);
       
   208 	  break;
       
   209 	}
       
   210       
       
   211       g_datalist_clear_i (&dataset->datalist);
       
   212       dataset = g_dataset_lookup (dataset_location);
       
   213     }
       
   214 }
       
   215 
       
   216 EXPORT_C void
       
   217 g_dataset_destroy (gconstpointer  dataset_location)
       
   218 {
       
   219   g_return_if_fail (dataset_location != NULL);
       
   220   
       
   221   G_LOCK (g_dataset_global);
       
   222   if (g_dataset_location_ht)
       
   223     {
       
   224       register GDataset *dataset;
       
   225 
       
   226       dataset = g_dataset_lookup (dataset_location);
       
   227       if (dataset)
       
   228 	g_dataset_destroy_internal (dataset);
       
   229     }
       
   230   G_UNLOCK (g_dataset_global);
       
   231 }
       
   232 
       
   233 /* HOLDS: g_dataset_global_lock */
       
   234 static inline gpointer
       
   235 g_data_set_internal (GData	  **datalist,
       
   236 		     GQuark         key_id,
       
   237 		     gpointer       data,
       
   238 		     GDestroyNotify destroy_func,
       
   239 		     GDataset	   *dataset)
       
   240 {
       
   241   register GData *list;
       
   242   
       
   243   list = G_DATALIST_GET_POINTER (datalist);
       
   244   if (!data)
       
   245     {
       
   246       register GData *prev;
       
   247       
       
   248       prev = NULL;
       
   249       while (list)
       
   250 	{
       
   251 	  if (list->id == key_id)
       
   252 	    {
       
   253 	      gpointer ret_data = NULL;
       
   254 
       
   255 	      if (prev)
       
   256 		prev->next = list->next;
       
   257 	      else
       
   258 		{
       
   259 		  G_DATALIST_SET_POINTER (datalist, list->next);
       
   260 		  
       
   261 		  /* the dataset destruction *must* be done
       
   262 		   * prior to invocation of the data destroy function
       
   263 		   */
       
   264 		  if (!list->next && dataset)
       
   265 		    g_dataset_destroy_internal (dataset);
       
   266 		}
       
   267 	      
       
   268 	      /* the GData struct *must* already be unlinked
       
   269 	       * when invoking the destroy function.
       
   270 	       * we use (data==NULL && destroy_func!=NULL) as
       
   271 	       * a special hint combination to "steal"
       
   272 	       * data without destroy notification
       
   273 	       */
       
   274 	      if (list->destroy_func && !destroy_func)
       
   275 		{
       
   276 		  G_UNLOCK (g_dataset_global);
       
   277 		  list->destroy_func (list->data);
       
   278 		  G_LOCK (g_dataset_global);
       
   279 		}
       
   280 	      else
       
   281 		ret_data = list->data;
       
   282 	      
       
   283               g_slice_free (GData, list);
       
   284 	      
       
   285 	      return ret_data;
       
   286 	    }
       
   287 	  
       
   288 	  prev = list;
       
   289 	  list = list->next;
       
   290 	}
       
   291     }
       
   292   else
       
   293     {
       
   294       while (list)
       
   295 	{
       
   296 	  if (list->id == key_id)
       
   297 	    {
       
   298 	      if (!list->destroy_func)
       
   299 		{
       
   300 		  list->data = data;
       
   301 		  list->destroy_func = destroy_func;
       
   302 		}
       
   303 	      else
       
   304 		{
       
   305 		  register GDestroyNotify dfunc;
       
   306 		  register gpointer ddata;
       
   307 		  
       
   308 		  dfunc = list->destroy_func;
       
   309 		  ddata = list->data;
       
   310 		  list->data = data;
       
   311 		  list->destroy_func = destroy_func;
       
   312 		  
       
   313 		  /* we need to have updated all structures prior to
       
   314 		   * invocation of the destroy function
       
   315 		   */
       
   316 		  G_UNLOCK (g_dataset_global);
       
   317 		  dfunc (ddata);
       
   318 		  G_LOCK (g_dataset_global);
       
   319 		}
       
   320 	      
       
   321 	      return NULL;
       
   322 	    }
       
   323 	  
       
   324 	  list = list->next;
       
   325 	}
       
   326       
       
   327       
       
   328       list = g_slice_new (GData);
       
   329       
       
   330       list->next = G_DATALIST_GET_POINTER (datalist);
       
   331       list->id = key_id;
       
   332       list->data = data;
       
   333       list->destroy_func = destroy_func;
       
   334       G_DATALIST_SET_POINTER (datalist, list);
       
   335     }
       
   336 
       
   337   return NULL;
       
   338 }
       
   339 
       
   340 EXPORT_C void
       
   341 g_dataset_id_set_data_full (gconstpointer  dataset_location,
       
   342 			    GQuark         key_id,
       
   343 			    gpointer       data,
       
   344 			    GDestroyNotify destroy_func)
       
   345 {
       
   346   register GDataset *dataset;
       
   347   
       
   348   g_return_if_fail (dataset_location != NULL);
       
   349   if (!data)
       
   350     g_return_if_fail (destroy_func == NULL);
       
   351   if (!key_id)
       
   352     {
       
   353       if (data)
       
   354 	g_return_if_fail (key_id > 0);
       
   355       else
       
   356 	return;
       
   357     }
       
   358   
       
   359   G_LOCK (g_dataset_global);
       
   360   if (!g_dataset_location_ht)
       
   361     g_data_initialize ();
       
   362  
       
   363   dataset = g_dataset_lookup (dataset_location);
       
   364   if (!dataset)
       
   365     {
       
   366       dataset = g_slice_new (GDataset);
       
   367       dataset->location = dataset_location;
       
   368       g_datalist_init (&dataset->datalist);
       
   369       g_hash_table_insert (g_dataset_location_ht, 
       
   370 			   (gpointer) dataset->location,
       
   371 			   dataset);
       
   372     }
       
   373   
       
   374   g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
       
   375   G_UNLOCK (g_dataset_global);
       
   376 }
       
   377 
       
   378 EXPORT_C void
       
   379 g_datalist_id_set_data_full (GData	  **datalist,
       
   380 			     GQuark         key_id,
       
   381 			     gpointer       data,
       
   382 			     GDestroyNotify destroy_func)
       
   383 {
       
   384   g_return_if_fail (datalist != NULL);
       
   385   if (!data)
       
   386     g_return_if_fail (destroy_func == NULL);
       
   387   if (!key_id)
       
   388     {
       
   389       if (data)
       
   390 	g_return_if_fail (key_id > 0);
       
   391       else
       
   392 	return;
       
   393     }
       
   394 
       
   395   G_LOCK (g_dataset_global);
       
   396   if (!g_dataset_location_ht)
       
   397     g_data_initialize ();
       
   398   
       
   399   g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
       
   400   G_UNLOCK (g_dataset_global);
       
   401 }
       
   402 
       
   403 EXPORT_C gpointer
       
   404 g_dataset_id_remove_no_notify (gconstpointer  dataset_location,
       
   405 			       GQuark         key_id)
       
   406 {
       
   407   gpointer ret_data = NULL;
       
   408 
       
   409   g_return_val_if_fail (dataset_location != NULL, NULL);
       
   410   
       
   411   G_LOCK (g_dataset_global);
       
   412   if (key_id && g_dataset_location_ht)
       
   413     {
       
   414       GDataset *dataset;
       
   415   
       
   416       dataset = g_dataset_lookup (dataset_location);
       
   417       if (dataset)
       
   418 	ret_data = g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
       
   419     } 
       
   420   G_UNLOCK (g_dataset_global);
       
   421 
       
   422   return ret_data;
       
   423 }
       
   424 
       
   425 EXPORT_C gpointer
       
   426 g_datalist_id_remove_no_notify (GData	**datalist,
       
   427 				GQuark    key_id)
       
   428 {
       
   429   gpointer ret_data = NULL;
       
   430 
       
   431   g_return_val_if_fail (datalist != NULL, NULL);
       
   432 
       
   433   G_LOCK (g_dataset_global);
       
   434   if (key_id && g_dataset_location_ht)
       
   435     ret_data = g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
       
   436   G_UNLOCK (g_dataset_global);
       
   437 
       
   438   return ret_data;
       
   439 }
       
   440 
       
   441 EXPORT_C gpointer
       
   442 g_dataset_id_get_data (gconstpointer  dataset_location,
       
   443 		       GQuark         key_id)
       
   444 {
       
   445   g_return_val_if_fail (dataset_location != NULL, NULL);
       
   446   
       
   447   G_LOCK (g_dataset_global);
       
   448   if (key_id && g_dataset_location_ht)
       
   449     {
       
   450       register GDataset *dataset;
       
   451       
       
   452       dataset = g_dataset_lookup (dataset_location);
       
   453       if (dataset)
       
   454 	{
       
   455 	  register GData *list;
       
   456 	  
       
   457 	  for (list = dataset->datalist; list; list = list->next)
       
   458 	    if (list->id == key_id)
       
   459 	      {
       
   460 		G_UNLOCK (g_dataset_global);
       
   461 		return list->data;
       
   462 	      }
       
   463 	}
       
   464     }
       
   465   G_UNLOCK (g_dataset_global);
       
   466  
       
   467   return NULL;
       
   468 }
       
   469 
       
   470 EXPORT_C gpointer
       
   471 g_datalist_id_get_data (GData	 **datalist,
       
   472 			GQuark     key_id)
       
   473 {
       
   474   gpointer data = NULL;
       
   475   g_return_val_if_fail (datalist != NULL, NULL);
       
   476   if (key_id)
       
   477     {
       
   478       register GData *list;
       
   479       G_LOCK (g_dataset_global);
       
   480       for (list = G_DATALIST_GET_POINTER (datalist); list; list = list->next)
       
   481 	if (list->id == key_id)
       
   482 	  {
       
   483             data = list->data;
       
   484             break;
       
   485           }
       
   486       G_UNLOCK (g_dataset_global);
       
   487     }
       
   488   return data;
       
   489 }
       
   490 
       
   491 EXPORT_C void
       
   492 g_dataset_foreach (gconstpointer    dataset_location,
       
   493 		   GDataForeachFunc func,
       
   494 		   gpointer         user_data)
       
   495 {
       
   496   register GDataset *dataset;
       
   497   
       
   498   g_return_if_fail (dataset_location != NULL);
       
   499   g_return_if_fail (func != NULL);
       
   500 
       
   501   G_LOCK (g_dataset_global);
       
   502   if (g_dataset_location_ht)
       
   503     {
       
   504       dataset = g_dataset_lookup (dataset_location);
       
   505       G_UNLOCK (g_dataset_global);
       
   506       if (dataset)
       
   507 	{
       
   508 	  register GData *list, *next;
       
   509 	  
       
   510 	  for (list = dataset->datalist; list; list = next)
       
   511 	    {
       
   512 	      next = list->next;
       
   513 	      func (list->id, list->data, user_data);
       
   514 	    }
       
   515 	}
       
   516     }
       
   517   else
       
   518     {
       
   519       G_UNLOCK (g_dataset_global);
       
   520     }
       
   521 }
       
   522 
       
   523 EXPORT_C void
       
   524 g_datalist_foreach (GData	   **datalist,
       
   525 		    GDataForeachFunc func,
       
   526 		    gpointer         user_data)
       
   527 {
       
   528   register GData *list, *next;
       
   529 
       
   530   g_return_if_fail (datalist != NULL);
       
   531   g_return_if_fail (func != NULL);
       
   532   
       
   533   for (list = G_DATALIST_GET_POINTER (datalist); list; list = next)
       
   534     {
       
   535       next = list->next;
       
   536       func (list->id, list->data, user_data);
       
   537     }
       
   538 }
       
   539 
       
   540 EXPORT_C void
       
   541 g_datalist_init (GData **datalist)
       
   542 {
       
   543   g_return_if_fail (datalist != NULL);
       
   544 
       
   545   g_atomic_pointer_set ((gpointer*) datalist, NULL);
       
   546 }
       
   547 
       
   548 /**
       
   549  * g_datalist_set_flags:
       
   550  * @datalist: pointer to the location that holds a list
       
   551  * @flags: the flags to turn on. The values of the flags are
       
   552  *   restricted by %G_DATALIST_FLAGS_MASK (currently
       
   553  *   3; giving two possible boolean flags).
       
   554  *   A value for @flags that doesn't fit within the mask is
       
   555  *   an error.
       
   556  * 
       
   557  * Turns on flag values for a data list. This function is used
       
   558  * to keep a small number of boolean flags in an object with
       
   559  * a data list without using any additional space. It is
       
   560  * not generally useful except in circumstances where space
       
   561  * is very tight. (It is used in the base #GObject type, for
       
   562  * example.)
       
   563  *
       
   564  * Since: 2.8
       
   565  **/
       
   566 EXPORT_C void
       
   567 g_datalist_set_flags (GData **datalist,
       
   568 		      guint   flags)
       
   569 {
       
   570   gpointer oldvalue;
       
   571   g_return_if_fail (datalist != NULL);
       
   572   g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
       
   573   
       
   574   do
       
   575     {
       
   576       oldvalue = g_atomic_pointer_get (datalist);
       
   577     }
       
   578   while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
       
   579                                                  (gpointer) ((gsize) oldvalue | flags)));
       
   580 }
       
   581 
       
   582 /**
       
   583  * g_datalist_unset_flags:
       
   584  * @datalist: pointer to the location that holds a list
       
   585  * @flags: the flags to turn off. The values of the flags are
       
   586  *   restricted by %G_DATALIST_FLAGS_MASK (currently
       
   587  *   3: giving two possible boolean flags).
       
   588  *   A value for @flags that doesn't fit within the mask is
       
   589  *   an error.
       
   590  * 
       
   591  * Turns off flag values for a data list. See g_datalist_unset_flags()
       
   592  *
       
   593  * Since: 2.8
       
   594  **/
       
   595 EXPORT_C void
       
   596 g_datalist_unset_flags (GData **datalist,
       
   597 			guint   flags)
       
   598 {
       
   599   gpointer oldvalue;
       
   600   g_return_if_fail (datalist != NULL);
       
   601   g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
       
   602   
       
   603   do
       
   604     {
       
   605       oldvalue = g_atomic_pointer_get (datalist);
       
   606     }
       
   607   while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
       
   608                                                  (gpointer) ((gsize) oldvalue & ~(gsize) flags)));
       
   609 }
       
   610 
       
   611 /**
       
   612  * g_datalist_get_flags:
       
   613  * @datalist: pointer to the location that holds a list
       
   614  * 
       
   615  * Gets flags values packed in together with the datalist.
       
   616  * See g_datalist_set_flags().
       
   617  * 
       
   618  * Return value: the flags of the datalist
       
   619  *
       
   620  * Since: 2.8
       
   621  **/
       
   622 EXPORT_C guint
       
   623 g_datalist_get_flags (GData **datalist)
       
   624 {
       
   625   g_return_val_if_fail (datalist != NULL, 0);
       
   626   
       
   627   return G_DATALIST_GET_FLAGS (datalist); /* atomic macro */
       
   628 }
       
   629 
       
   630 /* HOLDS: g_dataset_global_lock */
       
   631 static void
       
   632 g_data_initialize (void)
       
   633 {
       
   634   g_return_if_fail (g_dataset_location_ht == NULL);
       
   635 
       
   636   g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
       
   637   g_dataset_cached = NULL;
       
   638 }
       
   639 
       
   640 EXPORT_C GQuark
       
   641 g_quark_try_string (const gchar *string)
       
   642 {
       
   643   GQuark quark = 0;
       
   644   g_return_val_if_fail (string != NULL, 0);
       
   645   
       
   646   G_LOCK (g_quark_global);
       
   647   if (g_quark_ht)
       
   648     quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
       
   649   G_UNLOCK (g_quark_global);
       
   650   
       
   651   return quark;
       
   652 }
       
   653 
       
   654 /* HOLDS: g_quark_global_lock */
       
   655 static inline GQuark
       
   656 g_quark_from_string_internal (const gchar *string, 
       
   657 			      gboolean     duplicate)
       
   658 {
       
   659   GQuark quark = 0;
       
   660   
       
   661   if (g_quark_ht)
       
   662     quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
       
   663   
       
   664   if (!quark)
       
   665     quark = g_quark_new (duplicate ? g_strdup (string) : (gchar *)string);
       
   666   
       
   667   return quark;
       
   668 }
       
   669 
       
   670 EXPORT_C GQuark
       
   671 g_quark_from_string (const gchar *string)
       
   672 {
       
   673   GQuark quark;
       
   674   
       
   675   g_return_val_if_fail (string != NULL, 0);
       
   676   
       
   677   G_LOCK (g_quark_global);
       
   678   quark = g_quark_from_string_internal (string, TRUE);
       
   679   G_UNLOCK (g_quark_global);
       
   680   
       
   681   return quark;
       
   682 }
       
   683 
       
   684 EXPORT_C GQuark
       
   685 g_quark_from_static_string (const gchar *string)
       
   686 {
       
   687   GQuark quark;
       
   688   
       
   689   g_return_val_if_fail (string != NULL, 0);
       
   690   
       
   691   G_LOCK (g_quark_global);
       
   692   quark = g_quark_from_string_internal (string, FALSE);
       
   693   G_UNLOCK (g_quark_global);
       
   694 
       
   695   return quark;
       
   696 }
       
   697 
       
   698 EXPORT_C G_CONST_RETURN gchar*
       
   699 g_quark_to_string (GQuark quark)
       
   700 {
       
   701   gchar* result = NULL;
       
   702 
       
   703   G_LOCK (g_quark_global);
       
   704   if (quark < g_quark_seq_id)
       
   705     result = g_quarks[quark];
       
   706   G_UNLOCK (g_quark_global);
       
   707 
       
   708   return result;
       
   709 }
       
   710 
       
   711 /* HOLDS: g_quark_global_lock */
       
   712 static inline GQuark
       
   713 g_quark_new (gchar *string)
       
   714 {
       
   715   GQuark quark;
       
   716   
       
   717   if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
       
   718   g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
       
   719   if (!g_quark_ht)
       
   720     {
       
   721       g_assert (g_quark_seq_id == 0);
       
   722       g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
       
   723       g_quarks[g_quark_seq_id++] = NULL;
       
   724     }
       
   725 
       
   726   quark = g_quark_seq_id++;
       
   727   g_quarks[quark] = string;
       
   728   g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
       
   729   
       
   730   return quark;
       
   731 }
       
   732 
       
   733 /**
       
   734  * g_intern_string:
       
   735  * @string: a string
       
   736  * 
       
   737  * Returns a canonical representation for @string. Interned strings can
       
   738  * be compared for equality by comparing the pointers, instead of using strcmp().
       
   739  * 
       
   740  * Returns: a canonical representation for the string
       
   741  *
       
   742  * Since: 2.10
       
   743  */
       
   744 EXPORT_C G_CONST_RETURN gchar*
       
   745 g_intern_string (const gchar *string)
       
   746 {
       
   747   const gchar *result;
       
   748   GQuark quark;
       
   749 
       
   750   if (!string)
       
   751     return NULL;
       
   752 
       
   753   G_LOCK (g_quark_global);
       
   754   quark = g_quark_from_string_internal (string, TRUE);
       
   755   result = g_quarks[quark];
       
   756   G_UNLOCK (g_quark_global);
       
   757 
       
   758   return result;
       
   759 }
       
   760 
       
   761 /**
       
   762  * g_intern_static_string:
       
   763  * @string: a static string
       
   764  * 
       
   765  * Returns a canonical representation for @string. Interned strings can
       
   766  * be compared for equality by comparing the pointers, instead of using strcmp().
       
   767  * g_intern_static_string() does not copy the string, therefore @string must
       
   768  * not be freed or modified. 
       
   769  * 
       
   770  * Returns: a canonical representation for the string
       
   771  *
       
   772  * Since: 2.10
       
   773  */
       
   774 EXPORT_C G_CONST_RETURN gchar*
       
   775 g_intern_static_string (const gchar *string)
       
   776 {
       
   777   GQuark quark;
       
   778   const gchar *result;
       
   779 
       
   780   if (!string)
       
   781     return NULL;
       
   782 
       
   783   G_LOCK (g_quark_global);
       
   784   quark = g_quark_from_string_internal (string, FALSE);
       
   785   result = g_quarks[quark];
       
   786   G_UNLOCK (g_quark_global);
       
   787 
       
   788   return result;
       
   789 }
       
   790 
       
   791 
       
   792 
       
   793 #define __G_DATASET_C__
       
   794 #include "galiasdef.c"