Home | History | Annotate | Download | only in gobject
      1 /* GObject - GLib Type, Object, Parameter and Signal Library
      2  * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Lesser General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General
     15  * Public License along with this library; if not, write to the
     16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
     17  * Boston, MA 02111-1307, USA.
     18  */
     19 
     20 /*
     21  * MT safe
     22  */
     23 
     24 #include "config.h"
     25 
     26 #include <string.h>
     27 
     28 #include "gtype.h"
     29 #include "gtypeplugin.h"
     30 #include "gvaluecollector.h"
     31 #include "gbsearcharray.h"
     32 #include "gobjectalias.h"
     33 
     34 
     35 /**
     36  * SECTION:gtype
     37  * @short_description: The GLib Runtime type identification and
     38  *     management system
     39  * @title:Type Information
     40  *
     41  * The GType API is the foundation of the GObject system.  It provides the
     42  * facilities for registering and managing all fundamental data types,
     43  * user-defined object and interface types.  Before using any GType
     44  * or GObject functions, g_type_init() must be called to initialize the
     45  * type system.
     46  *
     47  * For type creation and registration purposes, all types fall into one of
     48  * two categories: static or dynamic.  Static types are never loaded or
     49  * unloaded at run-time as dynamic types may be.  Static types are created
     50  * with g_type_register_static() that gets type specific information passed
     51  * in via a #GTypeInfo structure.
     52  * Dynamic types are created with g_type_register_dynamic() which takes a
     53  * #GTypePlugin structure instead. The remaining type information (the
     54  * #GTypeInfo structure) is retrieved during runtime through #GTypePlugin
     55  * and the g_type_plugin_*() API.
     56  * These registration functions are usually called only once from a
     57  * function whose only purpose is to return the type identifier for a
     58  * specific class.  Once the type (or class or interface) is registered,
     59  * it may be instantiated, inherited, or implemented depending on exactly
     60  * what sort of type it is.
     61  * There is also a third registration function for registering fundamental
     62  * types called g_type_register_fundamental() which requires both a #GTypeInfo
     63  * structure and a #GTypeFundamentalInfo structure but it is seldom used
     64  * since most fundamental types are predefined rather than user-defined.
     65  *
     66  * A final word about type names.
     67  * Such an identifier needs to be at least three characters long. There is no
     68  * upper length limit. The first character needs to be a letter (a-z or A-Z)
     69  * or an underscore '_'. Subsequent characters can be letters, numbers or
     70  * any of '-_+'.
     71  */
     72 
     73 
     74 /* NOTE: some functions (some internal variants and exported ones)
     75  * invalidate data portions of the TypeNodes. if external functions/callbacks
     76  * are called, pointers to memory maintained by TypeNodes have to be looked up
     77  * again. this affects most of the struct TypeNode fields, e.g. ->children or
     78  * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
     79  * not ->supers[]), as all those memory portions can get realloc()ed during
     80  * callback invocation.
     81  *
     82  * TODO:
     83  * - g_type_from_name() should do an ordered array lookup after fetching the
     84  *   the quark, instead of a second hashtable lookup.
     85  *
     86  * LOCKING:
     87  * lock handling issues when calling static functions are indicated by
     88  * uppercase letter postfixes, all static functions have to have
     89  * one of the below postfixes:
     90  * - _I:	[Indifferent about locking]
     91  *   function doesn't care about locks at all
     92  * - _U:	[Unlocked invocation]
     93  *   no read or write lock has to be held across function invocation
     94  *   (locks may be acquired and released during invocation though)
     95  * - _L:	[Locked invocation]
     96  *   a write lock or more than 0 read locks have to be held across
     97  *   function invocation
     98  * - _W:	[Write-locked invocation]
     99  *   a write lock has to be held across function invocation
    100  * - _Wm:	[Write-locked invocation, mutatable]
    101  *   like _W, but the write lock might be released and reacquired
    102  *   during invocation, watch your pointers
    103  * - _WmREC:    [Write-locked invocation, mutatable, recursive]
    104  *   like _Wm, but also acquires recursive mutex class_init_rec_mutex
    105  */
    106 
    107 #ifdef LOCK_DEBUG
    108 #define G_READ_LOCK(rw_lock)    do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0)
    109 #define G_READ_UNLOCK(rw_lock)  do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0)
    110 #define G_WRITE_LOCK(rw_lock)   do { g_printerr (G_STRLOC ": writeL++\n"); g_static_rw_lock_writer_lock (rw_lock); } while (0)
    111 #define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_static_rw_lock_writer_unlock (rw_lock); } while (0)
    112 #else
    113 #define G_READ_LOCK(rw_lock)    g_static_rw_lock_reader_lock (rw_lock)
    114 #define G_READ_UNLOCK(rw_lock)  g_static_rw_lock_reader_unlock (rw_lock)
    115 #define G_WRITE_LOCK(rw_lock)   g_static_rw_lock_writer_lock (rw_lock)
    116 #define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
    117 #endif
    118 #define	INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
    119     static const gchar _action[] = " invalidly modified type ";  \
    120     gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
    121     if (_arg) \
    122       g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
    123     else \
    124       g_error ("%s()%s`%s'", _fname, _action, _tname); \
    125 }G_STMT_END
    126 #define	g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{	\
    127   if (!(condition))										\
    128     {												\
    129       g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,						\
    130 	     "%s: initialization assertion failed, use %s() prior to this function",		\
    131 	     G_STRLOC, G_STRINGIFY (init_function));						\
    132       return (return_value);									\
    133     }												\
    134 }G_STMT_END
    135 
    136 #ifdef  G_ENABLE_DEBUG
    137 #define DEBUG_CODE(debug_type, code_block)  G_STMT_START {    \
    138     if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
    139       { code_block; }                                     \
    140 } G_STMT_END
    141 #else /* !G_ENABLE_DEBUG */
    142 #define DEBUG_CODE(debug_type, code_block)  /* code_block */
    143 #endif  /* G_ENABLE_DEBUG */
    144 
    145 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
    146 				    G_TYPE_FLAG_INSTANTIATABLE | \
    147 				    G_TYPE_FLAG_DERIVABLE | \
    148 				    G_TYPE_FLAG_DEEP_DERIVABLE)
    149 #define	TYPE_FLAG_MASK		   (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
    150 #define	SIZEOF_FUNDAMENTAL_INFO	   ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
    151 						       sizeof (gpointer)), \
    152                                                   sizeof (glong)))
    153 
    154 /* The 2*sizeof(size_t) alignment here is borrowed from
    155  * GNU libc, so it should be good most everywhere.
    156  * It is more conservative than is needed on some 64-bit
    157  * platforms, but ia64 does require a 16-byte alignment.
    158  * The SIMD extensions for x86 and ppc32 would want a
    159  * larger alignment than this, but we don't need to
    160  * do better than malloc.
    161  */
    162 #define STRUCT_ALIGNMENT (2 * sizeof (gsize))
    163 #define ALIGN_STRUCT(offset) \
    164       ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
    165 
    166 
    167 /* --- typedefs --- */
    168 typedef struct _TypeNode        TypeNode;
    169 typedef struct _CommonData      CommonData;
    170 typedef struct _IFaceData       IFaceData;
    171 typedef struct _ClassData       ClassData;
    172 typedef struct _InstanceData    InstanceData;
    173 typedef union  _TypeData        TypeData;
    174 typedef struct _IFaceEntry      IFaceEntry;
    175 typedef struct _IFaceHolder	IFaceHolder;
    176 
    177 
    178 /* --- prototypes --- */
    179 static inline GTypeFundamentalInfo*	type_node_fundamental_info_I	(TypeNode		*node);
    180 static	      void			type_add_flags_W		(TypeNode		*node,
    181 									 GTypeFlags		 flags);
    182 static	      void			type_data_make_W		(TypeNode		*node,
    183 									 const GTypeInfo	*info,
    184 									 const GTypeValueTable	*value_table);
    185 static inline void			type_data_ref_Wm		(TypeNode		*node);
    186 static inline void			type_data_unref_WmREC		(TypeNode		*node,
    187 									 gboolean		 uncached);
    188 static void				type_data_last_unref_Wm		(GType			 type,
    189 									 gboolean		 uncached);
    190 static inline gpointer			type_get_qdata_L		(TypeNode		*node,
    191 									 GQuark			 quark);
    192 static inline void			type_set_qdata_W		(TypeNode		*node,
    193 									 GQuark			 quark,
    194 									 gpointer		 data);
    195 static IFaceHolder*			type_iface_peek_holder_L	(TypeNode		*iface,
    196 									 GType			 instance_type);
    197 static gboolean                         type_iface_vtable_base_init_Wm  (TypeNode               *iface,
    198                                                                          TypeNode               *node);
    199 static void                             type_iface_vtable_iface_init_Wm (TypeNode               *iface,
    200                                                                          TypeNode               *node);
    201 static gboolean				type_node_is_a_L		(TypeNode		*node,
    202 									 TypeNode		*iface_node);
    203 
    204 
    205 /* --- enumeration --- */
    206 
    207 /* The InitState enumeration is used to track the progress of initializing
    208  * both classes and interface vtables. Keeping the state of initialization
    209  * is necessary to handle new interfaces being added while we are initializing
    210  * the class or other interfaces.
    211  */
    212 typedef enum
    213 {
    214   UNINITIALIZED,
    215   BASE_CLASS_INIT,
    216   BASE_IFACE_INIT,
    217   CLASS_INIT,
    218   IFACE_INIT,
    219   INITIALIZED
    220 } InitState;
    221 
    222 /* --- structures --- */
    223 struct _TypeNode
    224 {
    225   GTypePlugin *plugin;
    226   guint        n_children : 12;
    227   guint        n_supers : 8;
    228   guint        _prot_n_ifaces_prerequisites : 9;
    229   guint        is_classed : 1;
    230   guint        is_instantiatable : 1;
    231   guint        mutatable_check_cache : 1;	/* combines some common path checks */
    232   GType       *children;
    233   TypeData * volatile data;
    234   GQuark       qname;
    235   GData       *global_gdata;
    236   union {
    237     IFaceEntry  *iface_entries;		/* for !iface types */
    238     GType       *prerequisistes;
    239   } _prot;
    240   GType        supers[1]; /* flexible array */
    241 };
    242 
    243 #define SIZEOF_BASE_TYPE_NODE()			(G_STRUCT_OFFSET (TypeNode, supers))
    244 #define MAX_N_SUPERS				(255)
    245 #define MAX_N_CHILDREN				(4095)
    246 #define MAX_N_IFACES				(511)
    247 #define	MAX_N_PREREQUISITES			(MAX_N_IFACES)
    248 #define NODE_TYPE(node)				(node->supers[0])
    249 #define NODE_PARENT_TYPE(node)			(node->supers[1])
    250 #define NODE_FUNDAMENTAL_TYPE(node)		(node->supers[node->n_supers])
    251 #define NODE_NAME(node)				(g_quark_to_string (node->qname))
    252 #define	NODE_IS_IFACE(node)			(NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
    253 #define	CLASSED_NODE_N_IFACES(node)		((node)->_prot_n_ifaces_prerequisites)
    254 #define	CLASSED_NODE_IFACES_ENTRIES(node)	((node)->_prot.iface_entries)
    255 #define	IFACE_NODE_N_PREREQUISITES(node)	((node)->_prot_n_ifaces_prerequisites)
    256 #define	IFACE_NODE_PREREQUISITES(node)		((node)->_prot.prerequisistes)
    257 #define	iface_node_get_holders_L(node)		((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
    258 #define	iface_node_set_holders_W(node, holders)	(type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
    259 #define	iface_node_get_dependants_array_L(n)	((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
    260 #define	iface_node_set_dependants_array_W(n,d)	(type_set_qdata_W ((n), static_quark_dependants_array, (d)))
    261 #define	TYPE_ID_MASK				((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1))
    262 
    263 #define NODE_IS_ANCESTOR(ancestor, node)                                                    \
    264         ((ancestor)->n_supers <= (node)->n_supers &&                                        \
    265 	 (node)->supers[(node)->n_supers - (ancestor)->n_supers] == NODE_TYPE (ancestor))
    266 
    267 
    268 struct _IFaceHolder
    269 {
    270   GType           instance_type;
    271   GInterfaceInfo *info;
    272   GTypePlugin    *plugin;
    273   IFaceHolder    *next;
    274 };
    275 
    276 struct _IFaceEntry
    277 {
    278   GType           iface_type;
    279   GTypeInterface *vtable;
    280   InitState       init_state;
    281 };
    282 
    283 struct _CommonData
    284 {
    285   guint             ref_count;
    286   GTypeValueTable  *value_table;
    287 };
    288 
    289 struct _IFaceData
    290 {
    291   CommonData         common;
    292   guint16            vtable_size;
    293   GBaseInitFunc      vtable_init_base;
    294   GBaseFinalizeFunc  vtable_finalize_base;
    295   GClassInitFunc     dflt_init;
    296   GClassFinalizeFunc dflt_finalize;
    297   gconstpointer      dflt_data;
    298   gpointer           dflt_vtable;
    299 };
    300 
    301 struct _ClassData
    302 {
    303   CommonData         common;
    304   guint16            class_size;
    305   guint              init_state : 4;
    306   GBaseInitFunc      class_init_base;
    307   GBaseFinalizeFunc  class_finalize_base;
    308   GClassInitFunc     class_init;
    309   GClassFinalizeFunc class_finalize;
    310   gconstpointer      class_data;
    311   gpointer           class;
    312 };
    313 
    314 struct _InstanceData
    315 {
    316   CommonData         common;
    317   guint16            class_size;
    318   guint              init_state : 4;
    319   GBaseInitFunc      class_init_base;
    320   GBaseFinalizeFunc  class_finalize_base;
    321   GClassInitFunc     class_init;
    322   GClassFinalizeFunc class_finalize;
    323   gconstpointer      class_data;
    324   gpointer           class;
    325   guint16            instance_size;
    326   guint16            private_size;
    327   guint16            n_preallocs;
    328   GInstanceInitFunc  instance_init;
    329 };
    330 
    331 union _TypeData
    332 {
    333   CommonData         common;
    334   IFaceData          iface;
    335   ClassData          class;
    336   InstanceData       instance;
    337 };
    338 
    339 typedef struct {
    340   gpointer            cache_data;
    341   GTypeClassCacheFunc cache_func;
    342 } ClassCacheFunc;
    343 
    344 typedef struct {
    345   gpointer                check_data;
    346   GTypeInterfaceCheckFunc check_func;
    347 } IFaceCheckFunc;
    348 
    349 
    350 /* --- variables --- */
    351 static GStaticRWLock   type_rw_lock = G_STATIC_RW_LOCK_INIT;
    352 static GStaticRecMutex class_init_rec_mutex = G_STATIC_REC_MUTEX_INIT;
    353 static guint           static_n_class_cache_funcs = 0;
    354 static ClassCacheFunc *static_class_cache_funcs = NULL;
    355 static guint           static_n_iface_check_funcs = 0;
    356 static IFaceCheckFunc *static_iface_check_funcs = NULL;
    357 static GQuark          static_quark_type_flags = 0;
    358 static GQuark          static_quark_iface_holder = 0;
    359 static GQuark          static_quark_dependants_array = 0;
    360 GTypeDebugFlags	       _g_type_debug_flags = 0;
    361 
    362 
    363 /* --- type nodes --- */
    364 static GHashTable       *static_type_nodes_ht = NULL;
    365 static TypeNode		*static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) + 1] = { NULL, };
    366 static GType		 static_fundamental_next = G_TYPE_RESERVED_USER_FIRST;
    367 
    368 static inline TypeNode*
    369 lookup_type_node_I (register GType utype)
    370 {
    371   if (utype > G_TYPE_FUNDAMENTAL_MAX)
    372     return (TypeNode*) (utype & ~TYPE_ID_MASK);
    373   else
    374     return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT];
    375 }
    376 
    377 static TypeNode*
    378 type_node_any_new_W (TypeNode             *pnode,
    379 		     GType                 ftype,
    380 		     const gchar          *name,
    381 		     GTypePlugin          *plugin,
    382 		     GTypeFundamentalFlags type_flags)
    383 {
    384   guint n_supers;
    385   GType type;
    386   TypeNode *node;
    387   guint i, node_size = 0;
    388 
    389   n_supers = pnode ? pnode->n_supers + 1 : 0;
    390 
    391   if (!pnode)
    392     node_size += SIZEOF_FUNDAMENTAL_INFO;	      /* fundamental type info */
    393   node_size += SIZEOF_BASE_TYPE_NODE ();	      /* TypeNode structure */
    394   node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */
    395   node = g_malloc0 (node_size);
    396   if (!pnode)					      /* offset fundamental types */
    397     {
    398       node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
    399       static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;
    400       type = ftype;
    401     }
    402   else
    403     type = (GType) node;
    404 
    405   g_assert ((type & TYPE_ID_MASK) == 0);
    406 
    407   node->n_supers = n_supers;
    408   if (!pnode)
    409     {
    410       node->supers[0] = type;
    411       node->supers[1] = 0;
    412 
    413       node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
    414       node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
    415 
    416       if (NODE_IS_IFACE (node))
    417 	{
    418           IFACE_NODE_N_PREREQUISITES (node) = 0;
    419 	  IFACE_NODE_PREREQUISITES (node) = NULL;
    420 	}
    421       else
    422 	{
    423 	  CLASSED_NODE_N_IFACES (node) = 0;
    424 	  CLASSED_NODE_IFACES_ENTRIES (node) = NULL;
    425 	}
    426     }
    427   else
    428     {
    429       node->supers[0] = type;
    430       memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
    431 
    432       node->is_classed = pnode->is_classed;
    433       node->is_instantiatable = pnode->is_instantiatable;
    434 
    435       if (NODE_IS_IFACE (node))
    436 	{
    437 	  IFACE_NODE_N_PREREQUISITES (node) = 0;
    438 	  IFACE_NODE_PREREQUISITES (node) = NULL;
    439 	}
    440       else
    441 	{
    442 	  guint j;
    443 
    444 	  CLASSED_NODE_N_IFACES (node) = CLASSED_NODE_N_IFACES (pnode);
    445 	  CLASSED_NODE_IFACES_ENTRIES (node) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode),
    446 							 sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode)[0]) *
    447 							 CLASSED_NODE_N_IFACES (node));
    448 	  for (j = 0; j < CLASSED_NODE_N_IFACES (node); j++)
    449 	    {
    450 	      CLASSED_NODE_IFACES_ENTRIES (node)[j].vtable = NULL;
    451 	      CLASSED_NODE_IFACES_ENTRIES (node)[j].init_state = UNINITIALIZED;
    452 	    }
    453 	}
    454 
    455       i = pnode->n_children++;
    456       pnode->children = g_renew (GType, pnode->children, pnode->n_children);
    457       pnode->children[i] = type;
    458     }
    459 
    460   node->plugin = plugin;
    461   node->n_children = 0;
    462   node->children = NULL;
    463   node->data = NULL;
    464   node->qname = g_quark_from_string (name);
    465   node->global_gdata = NULL;
    466 
    467   g_hash_table_insert (static_type_nodes_ht,
    468 		       GUINT_TO_POINTER (node->qname),
    469 		       (gpointer) type);
    470   return node;
    471 }
    472 
    473 static inline GTypeFundamentalInfo*
    474 type_node_fundamental_info_I (TypeNode *node)
    475 {
    476   GType ftype = NODE_FUNDAMENTAL_TYPE (node);
    477 
    478   if (ftype != NODE_TYPE (node))
    479     node = lookup_type_node_I (ftype);
    480 
    481   return node ? G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO) : NULL;
    482 }
    483 
    484 static TypeNode*
    485 type_node_fundamental_new_W (GType                 ftype,
    486 			     const gchar          *name,
    487 			     GTypeFundamentalFlags type_flags)
    488 {
    489   GTypeFundamentalInfo *finfo;
    490   TypeNode *node;
    491 
    492   g_assert ((ftype & TYPE_ID_MASK) == 0);
    493   g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX);
    494 
    495   if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next)
    496     static_fundamental_next++;
    497 
    498   type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
    499 
    500   node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
    501 
    502   finfo = type_node_fundamental_info_I (node);
    503   finfo->type_flags = type_flags;
    504 
    505   return node;
    506 }
    507 
    508 static TypeNode*
    509 type_node_new_W (TypeNode    *pnode,
    510 		 const gchar *name,
    511 		 GTypePlugin *plugin)
    512 
    513 {
    514   g_assert (pnode);
    515   g_assert (pnode->n_supers < MAX_N_SUPERS);
    516   g_assert (pnode->n_children < MAX_N_CHILDREN);
    517 
    518   return type_node_any_new_W (pnode, NODE_FUNDAMENTAL_TYPE (pnode), name, plugin, 0);
    519 }
    520 
    521 static inline IFaceEntry*
    522 type_lookup_iface_entry_L (TypeNode *node,
    523 			   TypeNode *iface_node)
    524 {
    525   if (NODE_IS_IFACE (iface_node) && CLASSED_NODE_N_IFACES (node))
    526     {
    527       IFaceEntry *ifaces = CLASSED_NODE_IFACES_ENTRIES (node) - 1;
    528       guint n_ifaces = CLASSED_NODE_N_IFACES (node);
    529       GType iface_type = NODE_TYPE (iface_node);
    530 
    531       do
    532 	{
    533 	  guint i;
    534 	  IFaceEntry *check;
    535 
    536 	  i = (n_ifaces + 1) >> 1;
    537 	  check = ifaces + i;
    538 	  if (iface_type == check->iface_type)
    539 	    return check;
    540 	  else if (iface_type > check->iface_type)
    541 	    {
    542 	      n_ifaces -= i;
    543 	      ifaces = check;
    544 	    }
    545 	  else /* if (iface_type < check->iface_type) */
    546 	    n_ifaces = i - 1;
    547 	}
    548       while (n_ifaces);
    549     }
    550 
    551   return NULL;
    552 }
    553 
    554 static inline gboolean
    555 type_lookup_prerequisite_L (TypeNode *iface,
    556 			    GType     prerequisite_type)
    557 {
    558   if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface))
    559     {
    560       GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1;
    561       guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface);
    562 
    563       do
    564 	{
    565 	  guint i;
    566 	  GType *check;
    567 
    568 	  i = (n_prerequisites + 1) >> 1;
    569 	  check = prerequisites + i;
    570 	  if (prerequisite_type == *check)
    571 	    return TRUE;
    572 	  else if (prerequisite_type > *check)
    573 	    {
    574 	      n_prerequisites -= i;
    575 	      prerequisites = check;
    576 	    }
    577 	  else /* if (prerequisite_type < *check) */
    578 	    n_prerequisites = i - 1;
    579 	}
    580       while (n_prerequisites);
    581     }
    582   return FALSE;
    583 }
    584 
    585 static gchar*
    586 type_descriptive_name_I (GType type)
    587 {
    588   if (type)
    589     {
    590       TypeNode *node = lookup_type_node_I (type);
    591 
    592       return node ? NODE_NAME (node) : "<unknown>";
    593     }
    594   else
    595     return "<invalid>";
    596 }
    597 
    598 
    599 /* --- type consistency checks --- */
    600 static gboolean
    601 check_plugin_U (GTypePlugin *plugin,
    602 		gboolean     need_complete_type_info,
    603 		gboolean     need_complete_interface_info,
    604 		const gchar *type_name)
    605 {
    606   /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U
    607    */
    608   if (!plugin)
    609     {
    610       g_warning ("plugin handle for type `%s' is NULL",
    611 		 type_name);
    612       return FALSE;
    613     }
    614   if (!G_IS_TYPE_PLUGIN (plugin))
    615     {
    616       g_warning ("plugin pointer (%p) for type `%s' is invalid",
    617 		 plugin, type_name);
    618       return FALSE;
    619     }
    620   if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
    621     {
    622       g_warning ("plugin for type `%s' has no complete_type_info() implementation",
    623 		 type_name);
    624       return FALSE;
    625     }
    626   if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
    627     {
    628       g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
    629 		 type_name);
    630       return FALSE;
    631     }
    632   return TRUE;
    633 }
    634 
    635 static gboolean
    636 check_type_name_I (const gchar *type_name)
    637 {
    638   static const gchar extra_chars[] = "-_+";
    639   const gchar *p = type_name;
    640   gboolean name_valid;
    641 
    642   if (!type_name[0] || !type_name[1] || !type_name[2])
    643     {
    644       g_warning ("type name `%s' is too short", type_name);
    645       return FALSE;
    646     }
    647   /* check the first letter */
    648   name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
    649   for (p = type_name + 1; *p; p++)
    650     name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
    651 		   (p[0] >= 'a' && p[0] <= 'z') ||
    652 		   (p[0] >= '0' && p[0] <= '9') ||
    653 		   strchr (extra_chars, p[0]));
    654   if (!name_valid)
    655     {
    656       g_warning ("type name `%s' contains invalid characters", type_name);
    657       return FALSE;
    658     }
    659   if (g_type_from_name (type_name))
    660     {
    661       g_warning ("cannot register existing type `%s'", type_name);
    662       return FALSE;
    663     }
    664 
    665   return TRUE;
    666 }
    667 
    668 static gboolean
    669 check_derivation_I (GType        parent_type,
    670 		    const gchar *type_name)
    671 {
    672   TypeNode *pnode;
    673   GTypeFundamentalInfo* finfo;
    674 
    675   pnode = lookup_type_node_I (parent_type);
    676   if (!pnode)
    677     {
    678       g_warning ("cannot derive type `%s' from invalid parent type `%s'",
    679 		 type_name,
    680 		 type_descriptive_name_I (parent_type));
    681       return FALSE;
    682     }
    683   finfo = type_node_fundamental_info_I (pnode);
    684   /* ensure flat derivability */
    685   if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
    686     {
    687       g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
    688 		 type_name,
    689 		 NODE_NAME (pnode));
    690       return FALSE;
    691     }
    692   /* ensure deep derivability */
    693   if (parent_type != NODE_FUNDAMENTAL_TYPE (pnode) &&
    694       !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
    695     {
    696       g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
    697 		 type_name,
    698 		 NODE_NAME (pnode));
    699       return FALSE;
    700     }
    701 
    702   return TRUE;
    703 }
    704 
    705 static gboolean
    706 check_collect_format_I (const gchar *collect_format)
    707 {
    708   const gchar *p = collect_format;
    709   gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
    710 			   G_VALUE_COLLECT_INT64, G_VALUE_COLLECT_DOUBLE,
    711 			   G_VALUE_COLLECT_POINTER, 0 };
    712 
    713   while (*p)
    714     if (!strchr (valid_format, *p++))
    715       return FALSE;
    716   return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
    717 }
    718 
    719 static gboolean
    720 check_value_table_I (const gchar           *type_name,
    721 		     const GTypeValueTable *value_table)
    722 {
    723   if (!value_table)
    724     return FALSE;
    725   else if (value_table->value_init == NULL)
    726     {
    727       if (value_table->value_free || value_table->value_copy ||
    728 	  value_table->value_peek_pointer ||
    729 	  value_table->collect_format || value_table->collect_value ||
    730 	  value_table->lcopy_format || value_table->lcopy_value)
    731 	g_warning ("cannot handle uninitializable values of type `%s'",
    732 		   type_name);
    733       return FALSE;
    734     }
    735   else /* value_table->value_init != NULL */
    736     {
    737       if (!value_table->value_free)
    738 	{
    739 	  /* +++ optional +++
    740 	   * g_warning ("missing `value_free()' for type `%s'", type_name);
    741 	   * return FALSE;
    742 	   */
    743 	}
    744       if (!value_table->value_copy)
    745 	{
    746 	  g_warning ("missing `value_copy()' for type `%s'", type_name);
    747 	  return FALSE;
    748 	}
    749       if ((value_table->collect_format || value_table->collect_value) &&
    750 	  (!value_table->collect_format || !value_table->collect_value))
    751 	{
    752 	  g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
    753 		     type_name);
    754 	  return FALSE;
    755 	}
    756       if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
    757 	{
    758 	  g_warning ("the `%s' specification for type `%s' is too long or invalid",
    759 		     "collect_format",
    760 		     type_name);
    761 	  return FALSE;
    762 	}
    763       if ((value_table->lcopy_format || value_table->lcopy_value) &&
    764 	  (!value_table->lcopy_format || !value_table->lcopy_value))
    765 	{
    766 	  g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
    767 		     type_name);
    768 	  return FALSE;
    769 	}
    770       if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
    771 	{
    772 	  g_warning ("the `%s' specification for type `%s' is too long or invalid",
    773 		     "lcopy_format",
    774 		     type_name);
    775 	  return FALSE;
    776 	}
    777     }
    778   return TRUE;
    779 }
    780 
    781 static gboolean
    782 check_type_info_I (TypeNode        *pnode,
    783 		   GType            ftype,
    784 		   const gchar     *type_name,
    785 		   const GTypeInfo *info)
    786 {
    787   GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (lookup_type_node_I (ftype));
    788   gboolean is_interface = ftype == G_TYPE_INTERFACE;
    789 
    790   g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX && !(ftype & TYPE_ID_MASK));
    791 
    792   /* check instance members */
    793   if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
    794       (info->instance_size || info->n_preallocs || info->instance_init))
    795     {
    796       if (pnode)
    797 	g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
    798 		   type_name,
    799 		   NODE_NAME (pnode));
    800       else
    801 	g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
    802 		   type_name);
    803       return FALSE;
    804     }
    805   /* check class & interface members */
    806   if (!((finfo->type_flags & G_TYPE_FLAG_CLASSED) || is_interface) &&
    807       (info->class_init || info->class_finalize || info->class_data ||
    808        info->class_size || info->base_init || info->base_finalize))
    809     {
    810       if (pnode)
    811 	g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
    812 		   type_name,
    813                    NODE_NAME (pnode));
    814       else
    815 	g_warning ("cannot create class for `%s' as non-classed fundamental",
    816 		   type_name);
    817       return FALSE;
    818     }
    819   /* check interface size */
    820   if (is_interface && info->class_size < sizeof (GTypeInterface))
    821     {
    822       g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
    823 		 type_name);
    824       return FALSE;
    825     }
    826   /* check class size */
    827   if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
    828     {
    829       if (info->class_size < sizeof (GTypeClass))
    830 	{
    831 	  g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
    832 		     type_name);
    833 	  return FALSE;
    834 	}
    835       if (pnode && info->class_size < pnode->data->class.class_size)
    836 	{
    837 	  g_warning ("specified class size for type `%s' is smaller "
    838 		     "than the parent type's `%s' class size",
    839 		     type_name,
    840 		     NODE_NAME (pnode));
    841 	  return FALSE;
    842 	}
    843     }
    844   /* check instance size */
    845   if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
    846     {
    847       if (info->instance_size < sizeof (GTypeInstance))
    848 	{
    849 	  g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
    850 		     type_name);
    851 	  return FALSE;
    852 	}
    853       if (pnode && info->instance_size < pnode->data->instance.instance_size)
    854 	{
    855 	  g_warning ("specified instance size for type `%s' is smaller "
    856 		     "than the parent type's `%s' instance size",
    857 		     type_name,
    858 		     NODE_NAME (pnode));
    859 	  return FALSE;
    860 	}
    861     }
    862 
    863   return TRUE;
    864 }
    865 
    866 static TypeNode*
    867 find_conforming_child_type_L (TypeNode *pnode,
    868 			      TypeNode *iface)
    869 {
    870   TypeNode *node = NULL;
    871   guint i;
    872 
    873   if (type_lookup_iface_entry_L (pnode, iface))
    874     return pnode;
    875 
    876   for (i = 0; i < pnode->n_children && !node; i++)
    877     node = find_conforming_child_type_L (lookup_type_node_I (pnode->children[i]), iface);
    878 
    879   return node;
    880 }
    881 
    882 static gboolean
    883 check_add_interface_L (GType instance_type,
    884 		       GType iface_type)
    885 {
    886   TypeNode *node = lookup_type_node_I (instance_type);
    887   TypeNode *iface = lookup_type_node_I (iface_type);
    888   IFaceEntry *entry;
    889   TypeNode *tnode;
    890   GType *prerequisites;
    891   guint i;
    892 
    893 
    894   if (!node || !node->is_instantiatable)
    895     {
    896       g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
    897 		 type_descriptive_name_I (instance_type));
    898       return FALSE;
    899     }
    900   if (!iface || !NODE_IS_IFACE (iface))
    901     {
    902       g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
    903 		 type_descriptive_name_I (iface_type),
    904 		 NODE_NAME (node));
    905       return FALSE;
    906     }
    907   tnode = lookup_type_node_I (NODE_PARENT_TYPE (iface));
    908   if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
    909     {
    910       /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
    911       g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
    912 		 NODE_NAME (iface),
    913 		 NODE_NAME (node),
    914 		 NODE_NAME (tnode));
    915       return FALSE;
    916     }
    917   /* allow overriding of interface type introduced for parent type */
    918   entry = type_lookup_iface_entry_L (node, iface);
    919   if (entry && entry->vtable == NULL && !type_iface_peek_holder_L (iface, NODE_TYPE (node)))
    920     {
    921       /* ok, we do conform to this interface already, but the interface vtable was not
    922        * yet intialized, and we just conform to the interface because it got added to
    923        * one of our parents. so we allow overriding of holder info here.
    924        */
    925       return TRUE;
    926     }
    927   /* check whether one of our children already conforms (or whether the interface
    928    * got added to this node already)
    929    */
    930   tnode = find_conforming_child_type_L (node, iface);  /* tnode is_a node */
    931   if (tnode)
    932     {
    933       g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
    934 		 NODE_NAME (iface),
    935 		 NODE_NAME (node),
    936 		 NODE_NAME (tnode));
    937       return FALSE;
    938     }
    939   prerequisites = IFACE_NODE_PREREQUISITES (iface);
    940   for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
    941     {
    942       tnode = lookup_type_node_I (prerequisites[i]);
    943       if (!type_node_is_a_L (node, tnode))
    944 	{
    945 	  g_warning ("cannot add interface type `%s' to type `%s' which does not conform to prerequisite `%s'",
    946 		     NODE_NAME (iface),
    947 		     NODE_NAME (node),
    948 		     NODE_NAME (tnode));
    949 	  return FALSE;
    950 	}
    951     }
    952   return TRUE;
    953 }
    954 
    955 static gboolean
    956 check_interface_info_I (TypeNode             *iface,
    957 			GType                 instance_type,
    958 			const GInterfaceInfo *info)
    959 {
    960   if ((info->interface_finalize || info->interface_data) && !info->interface_init)
    961     {
    962       g_warning ("interface type `%s' for type `%s' comes without initializer",
    963 		 NODE_NAME (iface),
    964 		 type_descriptive_name_I (instance_type));
    965       return FALSE;
    966     }
    967 
    968   return TRUE;
    969 }
    970 
    971 /* --- type info (type node data) --- */
    972 static void
    973 type_data_make_W (TypeNode              *node,
    974 		  const GTypeInfo       *info,
    975 		  const GTypeValueTable *value_table)
    976 {
    977   TypeData *data;
    978   GTypeValueTable *vtable = NULL;
    979   guint vtable_size = 0;
    980 
    981   g_assert (node->data == NULL && info != NULL);
    982 
    983   if (!value_table)
    984     {
    985       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
    986 
    987       if (pnode)
    988 	vtable = pnode->data->common.value_table;
    989       else
    990 	{
    991 	  static const GTypeValueTable zero_vtable = { NULL, };
    992 
    993 	  value_table = &zero_vtable;
    994 	}
    995     }
    996   if (value_table)
    997     {
    998       /* need to setup vtable_size since we have to allocate it with data in one chunk */
    999       vtable_size = sizeof (GTypeValueTable);
   1000       if (value_table->collect_format)
   1001 	vtable_size += strlen (value_table->collect_format);
   1002       if (value_table->lcopy_format)
   1003 	vtable_size += strlen (value_table->lcopy_format);
   1004       vtable_size += 2;
   1005     }
   1006 
   1007   if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
   1008     {
   1009       data = g_malloc0 (sizeof (InstanceData) + vtable_size);
   1010       if (vtable_size)
   1011 	vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
   1012       data->instance.class_size = info->class_size;
   1013       data->instance.class_init_base = info->base_init;
   1014       data->instance.class_finalize_base = info->base_finalize;
   1015       data->instance.class_init = info->class_init;
   1016       data->instance.class_finalize = info->class_finalize;
   1017       data->instance.class_data = info->class_data;
   1018       data->instance.class = NULL;
   1019       data->instance.init_state = UNINITIALIZED;
   1020       data->instance.instance_size = info->instance_size;
   1021       /* We'll set the final value for data->instance.private size
   1022        * after the parent class has been initialized
   1023        */
   1024       data->instance.private_size = 0;
   1025 #ifdef	DISABLE_MEM_POOLS
   1026       data->instance.n_preallocs = 0;
   1027 #else	/* !DISABLE_MEM_POOLS */
   1028       data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
   1029 #endif	/* !DISABLE_MEM_POOLS */
   1030       data->instance.instance_init = info->instance_init;
   1031     }
   1032   else if (node->is_classed) /* only classed */
   1033     {
   1034       data = g_malloc0 (sizeof (ClassData) + vtable_size);
   1035       if (vtable_size)
   1036 	vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
   1037       data->class.class_size = info->class_size;
   1038       data->class.class_init_base = info->base_init;
   1039       data->class.class_finalize_base = info->base_finalize;
   1040       data->class.class_init = info->class_init;
   1041       data->class.class_finalize = info->class_finalize;
   1042       data->class.class_data = info->class_data;
   1043       data->class.class = NULL;
   1044       data->class.init_state = UNINITIALIZED;
   1045     }
   1046   else if (NODE_IS_IFACE (node))
   1047     {
   1048       data = g_malloc0 (sizeof (IFaceData) + vtable_size);
   1049       if (vtable_size)
   1050 	vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
   1051       data->iface.vtable_size = info->class_size;
   1052       data->iface.vtable_init_base = info->base_init;
   1053       data->iface.vtable_finalize_base = info->base_finalize;
   1054       data->iface.dflt_init = info->class_init;
   1055       data->iface.dflt_finalize = info->class_finalize;
   1056       data->iface.dflt_data = info->class_data;
   1057       data->iface.dflt_vtable = NULL;
   1058     }
   1059   else
   1060     {
   1061       data = g_malloc0 (sizeof (CommonData) + vtable_size);
   1062       if (vtable_size)
   1063 	vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
   1064     }
   1065 
   1066   node->data = data;
   1067   node->data->common.ref_count = 1;
   1068 
   1069   if (vtable_size)
   1070     {
   1071       gchar *p;
   1072 
   1073       /* we allocate the vtable and its strings together with the type data, so
   1074        * children can take over their parent's vtable pointer, and we don't
   1075        * need to worry freeing it or not when the child data is destroyed
   1076        */
   1077       *vtable = *value_table;
   1078       p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable));
   1079       p[0] = 0;
   1080       vtable->collect_format = p;
   1081       if (value_table->collect_format)
   1082 	{
   1083 	  strcat (p, value_table->collect_format);
   1084 	  p += strlen (value_table->collect_format);
   1085 	}
   1086       p++;
   1087       p[0] = 0;
   1088       vtable->lcopy_format = p;
   1089       if (value_table->lcopy_format)
   1090 	strcat  (p, value_table->lcopy_format);
   1091     }
   1092   node->data->common.value_table = vtable;
   1093   node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL &&
   1094 				 !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) &
   1095 				   GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))));
   1096 
   1097   g_assert (node->data->common.value_table != NULL); /* paranoid */
   1098 }
   1099 
   1100 static inline void
   1101 type_data_ref_Wm (TypeNode *node)
   1102 {
   1103   if (!node->data)
   1104     {
   1105       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
   1106       GTypeInfo tmp_info;
   1107       GTypeValueTable tmp_value_table;
   1108 
   1109       g_assert (node->plugin != NULL);
   1110 
   1111       if (pnode)
   1112 	{
   1113 	  type_data_ref_Wm (pnode);
   1114 	  if (node->data)
   1115 	    INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
   1116 	}
   1117 
   1118       memset (&tmp_info, 0, sizeof (tmp_info));
   1119       memset (&tmp_value_table, 0, sizeof (tmp_value_table));
   1120 
   1121       G_WRITE_UNLOCK (&type_rw_lock);
   1122       g_type_plugin_use (node->plugin);
   1123       g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
   1124       G_WRITE_LOCK (&type_rw_lock);
   1125       if (node->data)
   1126 	INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
   1127 
   1128       check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (node), NODE_NAME (node), &tmp_info);
   1129       type_data_make_W (node, &tmp_info,
   1130 			check_value_table_I (NODE_NAME (node),
   1131 					     &tmp_value_table) ? &tmp_value_table : NULL);
   1132     }
   1133   else
   1134     {
   1135       g_assert (node->data->common.ref_count > 0);
   1136 
   1137       node->data->common.ref_count += 1;
   1138     }
   1139 }
   1140 
   1141 static inline void
   1142 type_data_unref_WmREC (TypeNode *node,
   1143                        gboolean  uncached)
   1144 {
   1145   g_assert (node->data && node->data->common.ref_count);
   1146   if (node->data->common.ref_count > 1)
   1147     node->data->common.ref_count -= 1;
   1148   else
   1149     {
   1150       GType node_type = NODE_TYPE (node);
   1151       if (!node->plugin)
   1152 	{
   1153 	  g_warning ("static type `%s' unreferenced too often",
   1154 		     NODE_NAME (node));
   1155 	  return;
   1156 	}
   1157       G_WRITE_UNLOCK (&type_rw_lock);
   1158       g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
   1159       G_WRITE_LOCK (&type_rw_lock);
   1160       type_data_last_unref_Wm (node_type, uncached);
   1161       g_static_rec_mutex_unlock (&class_init_rec_mutex);
   1162     }
   1163 }
   1164 
   1165 static void
   1166 type_node_add_iface_entry_W (TypeNode   *node,
   1167 			     GType       iface_type,
   1168                              IFaceEntry *parent_entry)
   1169 {
   1170   IFaceEntry *entries;
   1171   guint i;
   1172 
   1173   g_assert (node->is_instantiatable && CLASSED_NODE_N_IFACES (node) < MAX_N_IFACES);
   1174 
   1175   entries = CLASSED_NODE_IFACES_ENTRIES (node);
   1176   for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
   1177     if (entries[i].iface_type == iface_type)
   1178       {
   1179 	/* this can happen in two cases:
   1180          * - our parent type already conformed to iface_type and node
   1181          *   got its own holder info. here, our children already have
   1182          *   entries and NULL vtables, since this will only work for
   1183          *   uninitialized classes.
   1184 	 * - an interface type is added to an ancestor after it was
   1185          *   added to a child type.
   1186 	 */
   1187         if (!parent_entry)
   1188           g_assert (entries[i].vtable == NULL && entries[i].init_state == UNINITIALIZED);
   1189         else
   1190           {
   1191             /* sick, interface is added to ancestor *after* child type;
   1192              * nothing todo, the entry and our children were already setup correctly
   1193              */
   1194           }
   1195         return;
   1196       }
   1197     else if (entries[i].iface_type > iface_type)
   1198       break;
   1199   CLASSED_NODE_N_IFACES (node) += 1;
   1200   CLASSED_NODE_IFACES_ENTRIES (node) = g_renew (IFaceEntry,
   1201 						CLASSED_NODE_IFACES_ENTRIES (node),
   1202 						CLASSED_NODE_N_IFACES (node));
   1203   entries = CLASSED_NODE_IFACES_ENTRIES (node);
   1204   g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (CLASSED_NODE_N_IFACES (node) - i - 1));
   1205   entries[i].iface_type = iface_type;
   1206   entries[i].vtable = NULL;
   1207   entries[i].init_state = UNINITIALIZED;
   1208 
   1209   if (parent_entry)
   1210     {
   1211       if (node->data && node->data->class.init_state >= BASE_IFACE_INIT)
   1212         {
   1213           entries[i].init_state = INITIALIZED;
   1214           entries[i].vtable = parent_entry->vtable;
   1215         }
   1216       for (i = 0; i < node->n_children; i++)
   1217         type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), iface_type, &entries[i]);
   1218     }
   1219 }
   1220 
   1221 static void
   1222 type_add_interface_Wm (TypeNode             *node,
   1223                        TypeNode             *iface,
   1224                        const GInterfaceInfo *info,
   1225                        GTypePlugin          *plugin)
   1226 {
   1227   IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
   1228   IFaceEntry *entry;
   1229   guint i;
   1230 
   1231   g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin)));
   1232 
   1233   iholder->next = iface_node_get_holders_L (iface);
   1234   iface_node_set_holders_W (iface, iholder);
   1235   iholder->instance_type = NODE_TYPE (node);
   1236   iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
   1237   iholder->plugin = plugin;
   1238 
   1239   /* create an iface entry for this type */
   1240   type_node_add_iface_entry_W (node, NODE_TYPE (iface), NULL);
   1241 
   1242   /* if the class is already (partly) initialized, we may need to base
   1243    * initalize and/or initialize the new interface.
   1244    */
   1245   if (node->data)
   1246     {
   1247       InitState class_state = node->data->class.init_state;
   1248 
   1249       if (class_state >= BASE_IFACE_INIT)
   1250         type_iface_vtable_base_init_Wm (iface, node);
   1251 
   1252       if (class_state >= IFACE_INIT)
   1253         type_iface_vtable_iface_init_Wm (iface, node);
   1254     }
   1255 
   1256   /* create iface entries for children of this type */
   1257   entry = type_lookup_iface_entry_L (node, iface);
   1258   for (i = 0; i < node->n_children; i++)
   1259     type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), NODE_TYPE (iface), entry);
   1260 }
   1261 
   1262 static void
   1263 type_iface_add_prerequisite_W (TypeNode *iface,
   1264 			       TypeNode *prerequisite_node)
   1265 {
   1266   GType prerequisite_type = NODE_TYPE (prerequisite_node);
   1267   GType *prerequisites, *dependants;
   1268   guint n_dependants, i;
   1269 
   1270   g_assert (NODE_IS_IFACE (iface) &&
   1271 	    IFACE_NODE_N_PREREQUISITES (iface) < MAX_N_PREREQUISITES &&
   1272 	    (prerequisite_node->is_instantiatable || NODE_IS_IFACE (prerequisite_node)));
   1273 
   1274   prerequisites = IFACE_NODE_PREREQUISITES (iface);
   1275   for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
   1276     if (prerequisites[i] == prerequisite_type)
   1277       return;			/* we already have that prerequisiste */
   1278     else if (prerequisites[i] > prerequisite_type)
   1279       break;
   1280   IFACE_NODE_N_PREREQUISITES (iface) += 1;
   1281   IFACE_NODE_PREREQUISITES (iface) = g_renew (GType,
   1282 					      IFACE_NODE_PREREQUISITES (iface),
   1283 					      IFACE_NODE_N_PREREQUISITES (iface));
   1284   prerequisites = IFACE_NODE_PREREQUISITES (iface);
   1285   g_memmove (prerequisites + i + 1, prerequisites + i,
   1286 	     sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1));
   1287   prerequisites[i] = prerequisite_type;
   1288 
   1289   /* we want to get notified when prerequisites get added to prerequisite_node */
   1290   if (NODE_IS_IFACE (prerequisite_node))
   1291     {
   1292       dependants = iface_node_get_dependants_array_L (prerequisite_node);
   1293       n_dependants = dependants ? dependants[0] : 0;
   1294       n_dependants += 1;
   1295       dependants = g_renew (GType, dependants, n_dependants + 1);
   1296       dependants[n_dependants] = NODE_TYPE (iface);
   1297       dependants[0] = n_dependants;
   1298       iface_node_set_dependants_array_W (prerequisite_node, dependants);
   1299     }
   1300 
   1301   /* we need to notify all dependants */
   1302   dependants = iface_node_get_dependants_array_L (iface);
   1303   n_dependants = dependants ? dependants[0] : 0;
   1304   for (i = 1; i <= n_dependants; i++)
   1305     type_iface_add_prerequisite_W (lookup_type_node_I (dependants[i]), prerequisite_node);
   1306 }
   1307 
   1308 /**
   1309  * g_type_interface_add_prerequisite:
   1310  * @interface_type: #GType value of an interface type.
   1311  * @prerequisite_type: #GType value of an interface or instantiatable type.
   1312  *
   1313  * Adds @prerequisite_type to the list of prerequisites of @interface_type.
   1314  * This means that any type implementing @interface_type must also implement
   1315  * @prerequisite_type. Prerequisites can be thought of as an alternative to
   1316  * interface derivation (which GType doesn't support). An interface can have
   1317  * at most one instantiatable prerequisite type.
   1318  */
   1319 void
   1320 g_type_interface_add_prerequisite (GType interface_type,
   1321 				   GType prerequisite_type)
   1322 {
   1323   TypeNode *iface, *prerequisite_node;
   1324   IFaceHolder *holders;
   1325 
   1326   g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type));	/* G_TYPE_IS_INTERFACE() is an external call: _U */
   1327   g_return_if_fail (!g_type_is_a (interface_type, prerequisite_type));
   1328   g_return_if_fail (!g_type_is_a (prerequisite_type, interface_type));
   1329 
   1330   iface = lookup_type_node_I (interface_type);
   1331   prerequisite_node = lookup_type_node_I (prerequisite_type);
   1332   if (!iface || !prerequisite_node || !NODE_IS_IFACE (iface))
   1333     {
   1334       g_warning ("interface type `%s' or prerequisite type `%s' invalid",
   1335 		 type_descriptive_name_I (interface_type),
   1336 		 type_descriptive_name_I (prerequisite_type));
   1337       return;
   1338     }
   1339   G_WRITE_LOCK (&type_rw_lock);
   1340   holders = iface_node_get_holders_L (iface);
   1341   if (holders)
   1342     {
   1343       G_WRITE_UNLOCK (&type_rw_lock);
   1344       g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'",
   1345 		 type_descriptive_name_I (prerequisite_type),
   1346 		 type_descriptive_name_I (interface_type),
   1347 		 type_descriptive_name_I (holders->instance_type));
   1348       return;
   1349     }
   1350   if (prerequisite_node->is_instantiatable)
   1351     {
   1352       guint i;
   1353 
   1354       /* can have at most one publically installable instantiatable prerequisite */
   1355       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
   1356 	{
   1357 	  TypeNode *prnode = lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface)[i]);
   1358 
   1359 	  if (prnode->is_instantiatable)
   1360 	    {
   1361 	      G_WRITE_UNLOCK (&type_rw_lock);
   1362 	      g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
   1363 			 type_descriptive_name_I (prerequisite_type),
   1364 			 type_descriptive_name_I (interface_type),
   1365 			 type_descriptive_name_I (NODE_TYPE (prnode)));
   1366 	      return;
   1367 	    }
   1368 	}
   1369 
   1370       for (i = 0; i < prerequisite_node->n_supers + 1; i++)
   1371 	type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisite_node->supers[i]));
   1372       G_WRITE_UNLOCK (&type_rw_lock);
   1373     }
   1374   else if (NODE_IS_IFACE (prerequisite_node))
   1375     {
   1376       GType *prerequisites;
   1377       guint i;
   1378 
   1379       prerequisites = IFACE_NODE_PREREQUISITES (prerequisite_node);
   1380       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (prerequisite_node); i++)
   1381 	type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisites[i]));
   1382       type_iface_add_prerequisite_W (iface, prerequisite_node);
   1383       G_WRITE_UNLOCK (&type_rw_lock);
   1384     }
   1385   else
   1386     {
   1387       G_WRITE_UNLOCK (&type_rw_lock);
   1388       g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface",
   1389 		 type_descriptive_name_I (prerequisite_type),
   1390 		 type_descriptive_name_I (interface_type));
   1391     }
   1392 }
   1393 
   1394 /**
   1395  * g_type_interface_prerequisites:
   1396  * @interface_type: an interface type
   1397  * @n_prerequisites: location to return the number of prerequisites, or %NULL
   1398  *
   1399  * Returns the prerequisites of an interfaces type.
   1400  *
   1401  * Since: 2.2
   1402  *
   1403  * Returns: a newly-allocated zero-terminated array of #GType containing
   1404  *  the prerequisites of @interface_type
   1405  */
   1406 GType*
   1407 g_type_interface_prerequisites (GType  interface_type,
   1408 				guint *n_prerequisites)
   1409 {
   1410   TypeNode *iface;
   1411 
   1412   g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
   1413 
   1414   iface = lookup_type_node_I (interface_type);
   1415   if (iface)
   1416     {
   1417       GType *types;
   1418       TypeNode *inode = NULL;
   1419       guint i, n = 0;
   1420 
   1421       G_READ_LOCK (&type_rw_lock);
   1422       types = g_new0 (GType, IFACE_NODE_N_PREREQUISITES (iface) + 1);
   1423       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
   1424 	{
   1425 	  GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
   1426 	  TypeNode *node = lookup_type_node_I (prerequisite);
   1427 	  if (node->is_instantiatable &&
   1428 	      (!inode || type_node_is_a_L (node, inode)))
   1429 	    inode = node;
   1430 	  else
   1431 	    types[n++] = NODE_TYPE (node);
   1432 	}
   1433       if (inode)
   1434 	types[n++] = NODE_TYPE (inode);
   1435 
   1436       if (n_prerequisites)
   1437 	*n_prerequisites = n;
   1438       G_READ_UNLOCK (&type_rw_lock);
   1439 
   1440       return types;
   1441     }
   1442   else
   1443     {
   1444       if (n_prerequisites)
   1445 	*n_prerequisites = 0;
   1446 
   1447       return NULL;
   1448     }
   1449 }
   1450 
   1451 
   1452 static IFaceHolder*
   1453 type_iface_peek_holder_L (TypeNode *iface,
   1454 			  GType     instance_type)
   1455 {
   1456   IFaceHolder *iholder;
   1457 
   1458   g_assert (NODE_IS_IFACE (iface));
   1459 
   1460   iholder = iface_node_get_holders_L (iface);
   1461   while (iholder && iholder->instance_type != instance_type)
   1462     iholder = iholder->next;
   1463   return iholder;
   1464 }
   1465 
   1466 static IFaceHolder*
   1467 type_iface_retrieve_holder_info_Wm (TypeNode *iface,
   1468 				    GType     instance_type,
   1469 				    gboolean  need_info)
   1470 {
   1471   IFaceHolder *iholder = type_iface_peek_holder_L (iface, instance_type);
   1472 
   1473   if (iholder && !iholder->info && need_info)
   1474     {
   1475       GInterfaceInfo tmp_info;
   1476 
   1477       g_assert (iholder->plugin != NULL);
   1478 
   1479       type_data_ref_Wm (iface);
   1480       if (iholder->info)
   1481 	INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface));
   1482 
   1483       memset (&tmp_info, 0, sizeof (tmp_info));
   1484 
   1485       G_WRITE_UNLOCK (&type_rw_lock);
   1486       g_type_plugin_use (iholder->plugin);
   1487       g_type_plugin_complete_interface_info (iholder->plugin, instance_type, NODE_TYPE (iface), &tmp_info);
   1488       G_WRITE_LOCK (&type_rw_lock);
   1489       if (iholder->info)
   1490         INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
   1491 
   1492       check_interface_info_I (iface, instance_type, &tmp_info);
   1493       iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
   1494     }
   1495 
   1496   return iholder;	/* we don't modify write lock upon returning NULL */
   1497 }
   1498 
   1499 static void
   1500 type_iface_blow_holder_info_Wm (TypeNode *iface,
   1501 				GType     instance_type)
   1502 {
   1503   IFaceHolder *iholder = iface_node_get_holders_L (iface);
   1504 
   1505   g_assert (NODE_IS_IFACE (iface));
   1506 
   1507   while (iholder->instance_type != instance_type)
   1508     iholder = iholder->next;
   1509 
   1510   if (iholder->info && iholder->plugin)
   1511     {
   1512       g_free (iholder->info);
   1513       iholder->info = NULL;
   1514 
   1515       G_WRITE_UNLOCK (&type_rw_lock);
   1516       g_type_plugin_unuse (iholder->plugin);
   1517       G_WRITE_LOCK (&type_rw_lock);
   1518 
   1519       type_data_unref_WmREC (iface, FALSE);
   1520     }
   1521 }
   1522 
   1523 /* Assumes type's class already exists
   1524  */
   1525 static inline size_t
   1526 type_total_instance_size_I (TypeNode *node)
   1527 {
   1528   gsize total_instance_size;
   1529 
   1530   total_instance_size = node->data->instance.instance_size;
   1531   if (node->data->instance.private_size != 0)
   1532     total_instance_size = ALIGN_STRUCT (total_instance_size) + node->data->instance.private_size;
   1533 
   1534   return total_instance_size;
   1535 }
   1536 
   1537 /* --- type structure creation/destruction --- */
   1538 typedef struct {
   1539   gpointer instance;
   1540   gpointer class;
   1541 } InstanceRealClass;
   1542 
   1543 static gint
   1544 instance_real_class_cmp (gconstpointer p1,
   1545                          gconstpointer p2)
   1546 {
   1547   const InstanceRealClass *irc1 = p1;
   1548   const InstanceRealClass *irc2 = p2;
   1549   guint8 *i1 = irc1->instance;
   1550   guint8 *i2 = irc2->instance;
   1551   return G_BSEARCH_ARRAY_CMP (i1, i2);
   1552 }
   1553 
   1554 G_LOCK_DEFINE_STATIC (instance_real_class);
   1555 static GBSearchArray *instance_real_class_bsa = NULL;
   1556 static GBSearchConfig instance_real_class_bconfig = {
   1557   sizeof (InstanceRealClass),
   1558   instance_real_class_cmp,
   1559   0,
   1560 };
   1561 
   1562 static inline void
   1563 instance_real_class_set (gpointer    instance,
   1564                          GTypeClass *class)
   1565 {
   1566   InstanceRealClass key;
   1567   key.instance = instance;
   1568   key.class = class;
   1569   G_LOCK (instance_real_class);
   1570   if (!instance_real_class_bsa)
   1571     instance_real_class_bsa = g_bsearch_array_create (&instance_real_class_bconfig);
   1572   instance_real_class_bsa = g_bsearch_array_replace (instance_real_class_bsa, &instance_real_class_bconfig, &key);
   1573   G_UNLOCK (instance_real_class);
   1574 }
   1575 
   1576 static inline void
   1577 instance_real_class_remove (gpointer instance)
   1578 {
   1579   InstanceRealClass key, *node;
   1580   guint index;
   1581   key.instance = instance;
   1582   G_LOCK (instance_real_class);
   1583   node = g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key);
   1584   index = g_bsearch_array_get_index (instance_real_class_bsa, &instance_real_class_bconfig, node);
   1585   instance_real_class_bsa = g_bsearch_array_remove (instance_real_class_bsa, &instance_real_class_bconfig, index);
   1586   if (!g_bsearch_array_get_n_nodes (instance_real_class_bsa))
   1587     {
   1588       g_bsearch_array_free (instance_real_class_bsa, &instance_real_class_bconfig);
   1589       instance_real_class_bsa = NULL;
   1590     }
   1591   G_UNLOCK (instance_real_class);
   1592 }
   1593 
   1594 static inline GTypeClass*
   1595 instance_real_class_get (gpointer instance)
   1596 {
   1597   InstanceRealClass key, *node;
   1598   GTypeClass *class;
   1599   key.instance = instance;
   1600   G_LOCK (instance_real_class);
   1601   node = instance_real_class_bsa ? g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key) : NULL;
   1602   class = node ? node->class : NULL;
   1603   G_UNLOCK (instance_real_class);
   1604   return class;
   1605 }
   1606 
   1607 /**
   1608  * g_type_create_instance:
   1609  * @type: An instantiatable type to create an instance for.
   1610  *
   1611  * Creates and initializes an instance of @type if @type is valid and
   1612  * can be instantiated. The type system only performs basic allocation
   1613  * and structure setups for instances: actual instance creation should
   1614  * happen through functions supplied by the type's fundamental type
   1615  * implementation.  So use of g_type_create_instance() is reserved for
   1616  * implementators of fundamental types only. E.g. instances of the
   1617  * #GObject hierarchy should be created via g_object_new() and
   1618  * <emphasis>never</emphasis> directly through
   1619  * g_type_create_instance() which doesn't handle things like singleton
   1620  * objects or object construction.  Note: Do <emphasis>not</emphasis>
   1621  * use this function, unless you're implementing a fundamental
   1622  * type. Also language bindings should <emphasis>not</emphasis> use
   1623  * this function but g_object_new() instead.
   1624  *
   1625  * Returns: An allocated and initialized instance, subject to further
   1626  *  treatment by the fundamental type implementation.
   1627  */
   1628 GTypeInstance*
   1629 g_type_create_instance (GType type)
   1630 {
   1631   TypeNode *node;
   1632   GTypeInstance *instance;
   1633   GTypeClass *class;
   1634   guint i, total_size;
   1635 
   1636   node = lookup_type_node_I (type);
   1637   if (!node || !node->is_instantiatable)
   1638     {
   1639       g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
   1640 		 type_descriptive_name_I (type));
   1641       return NULL;
   1642     }
   1643   /* G_TYPE_IS_ABSTRACT() is an external call: _U */
   1644   if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (type))
   1645     {
   1646       g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
   1647 		 type_descriptive_name_I (type));
   1648       return NULL;
   1649     }
   1650 
   1651   class = g_type_class_ref (type);
   1652   total_size = type_total_instance_size_I (node);
   1653 
   1654   instance = g_slice_alloc0 (total_size);
   1655 
   1656   if (node->data->instance.private_size)
   1657     instance_real_class_set (instance, class);
   1658   for (i = node->n_supers; i > 0; i--)
   1659     {
   1660       TypeNode *pnode;
   1661 
   1662       pnode = lookup_type_node_I (node->supers[i]);
   1663       if (pnode->data->instance.instance_init)
   1664 	{
   1665 	  instance->g_class = pnode->data->instance.class;
   1666 	  pnode->data->instance.instance_init (instance, class);
   1667 	}
   1668     }
   1669   if (node->data->instance.private_size)
   1670     instance_real_class_remove (instance);
   1671 
   1672   instance->g_class = class;
   1673   if (node->data->instance.instance_init)
   1674     node->data->instance.instance_init (instance, class);
   1675 
   1676   return instance;
   1677 }
   1678 
   1679 /**
   1680  * g_type_free_instance:
   1681  * @instance: an instance of a type.
   1682  *
   1683  * Frees an instance of a type, returning it to the instance pool for
   1684  * the type, if there is one.
   1685  *
   1686  * Like g_type_create_instance(), this function is reserved for
   1687  * implementors of fundamental types.
   1688  */
   1689 void
   1690 g_type_free_instance (GTypeInstance *instance)
   1691 {
   1692   TypeNode *node;
   1693   GTypeClass *class;
   1694 
   1695   g_return_if_fail (instance != NULL && instance->g_class != NULL);
   1696 
   1697   class = instance->g_class;
   1698   node = lookup_type_node_I (class->g_type);
   1699   if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
   1700     {
   1701       g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
   1702 		 type_descriptive_name_I (class->g_type));
   1703       return;
   1704     }
   1705   /* G_TYPE_IS_ABSTRACT() is an external call: _U */
   1706   if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
   1707     {
   1708       g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
   1709 		 NODE_NAME (node));
   1710       return;
   1711     }
   1712 
   1713   instance->g_class = NULL;
   1714 #ifdef G_ENABLE_DEBUG
   1715   memset (instance, 0xaa, type_total_instance_size_I (node));
   1716 #endif
   1717   g_slice_free1 (type_total_instance_size_I (node), instance);
   1718 
   1719   g_type_class_unref (class);
   1720 }
   1721 
   1722 static void
   1723 type_iface_ensure_dflt_vtable_Wm (TypeNode *iface)
   1724 {
   1725   g_assert (iface->data);
   1726 
   1727   if (!iface->data->iface.dflt_vtable)
   1728     {
   1729       GTypeInterface *vtable = g_malloc0 (iface->data->iface.vtable_size);
   1730       iface->data->iface.dflt_vtable = vtable;
   1731       vtable->g_type = NODE_TYPE (iface);
   1732       vtable->g_instance_type = 0;
   1733       if (iface->data->iface.vtable_init_base ||
   1734           iface->data->iface.dflt_init)
   1735         {
   1736           G_WRITE_UNLOCK (&type_rw_lock);
   1737           if (iface->data->iface.vtable_init_base)
   1738             iface->data->iface.vtable_init_base (vtable);
   1739           if (iface->data->iface.dflt_init)
   1740             iface->data->iface.dflt_init (vtable, (gpointer) iface->data->iface.dflt_data);
   1741           G_WRITE_LOCK (&type_rw_lock);
   1742         }
   1743     }
   1744 }
   1745 
   1746 
   1747 /* This is called to allocate and do the first part of initializing
   1748  * the interface vtable; type_iface_vtable_iface_init_Wm() does the remainder.
   1749  *
   1750  * A FALSE return indicates that we didn't find an init function for
   1751  * this type/iface pair, so the vtable from the parent type should
   1752  * be used. Note that the write lock is not modified upon a FALSE
   1753  * return.
   1754  */
   1755 static gboolean
   1756 type_iface_vtable_base_init_Wm (TypeNode *iface,
   1757 				TypeNode *node)
   1758 {
   1759   IFaceEntry *entry;
   1760   IFaceHolder *iholder;
   1761   GTypeInterface *vtable = NULL;
   1762   TypeNode *pnode;
   1763 
   1764   /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
   1765   iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), TRUE);
   1766   if (!iholder)
   1767     return FALSE;	/* we don't modify write lock upon FALSE */
   1768 
   1769   type_iface_ensure_dflt_vtable_Wm (iface);
   1770 
   1771   entry = type_lookup_iface_entry_L (node, iface);
   1772 
   1773   g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
   1774 
   1775   entry->init_state = IFACE_INIT;
   1776 
   1777   pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
   1778   if (pnode)	/* want to copy over parent iface contents */
   1779     {
   1780       IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
   1781 
   1782       if (pentry)
   1783 	vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
   1784     }
   1785   if (!vtable)
   1786     vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
   1787   entry->vtable = vtable;
   1788   vtable->g_type = NODE_TYPE (iface);
   1789   vtable->g_instance_type = NODE_TYPE (node);
   1790 
   1791   if (iface->data->iface.vtable_init_base)
   1792     {
   1793       G_WRITE_UNLOCK (&type_rw_lock);
   1794       iface->data->iface.vtable_init_base (vtable);
   1795       G_WRITE_LOCK (&type_rw_lock);
   1796     }
   1797   return TRUE;	/* initialized the vtable */
   1798 }
   1799 
   1800 /* Finishes what type_iface_vtable_base_init_Wm started by
   1801  * calling the interface init function.
   1802  * this function may only be called for types with their
   1803  * own interface holder info, i.e. types for which
   1804  * g_type_add_interface*() was called and not children thereof.
   1805  */
   1806 static void
   1807 type_iface_vtable_iface_init_Wm (TypeNode *iface,
   1808 				 TypeNode *node)
   1809 {
   1810   IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
   1811   IFaceHolder *iholder = type_iface_peek_holder_L (iface, NODE_TYPE (node));
   1812   GTypeInterface *vtable = NULL;
   1813   guint i;
   1814 
   1815   /* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */
   1816   g_assert (iface->data && entry && iholder && iholder->info);
   1817   g_assert (entry->init_state == IFACE_INIT); /* assert prior base_init() */
   1818 
   1819   entry->init_state = INITIALIZED;
   1820 
   1821   vtable = entry->vtable;
   1822 
   1823   if (iholder->info->interface_init)
   1824     {
   1825       G_WRITE_UNLOCK (&type_rw_lock);
   1826       if (iholder->info->interface_init)
   1827 	iholder->info->interface_init (vtable, iholder->info->interface_data);
   1828       G_WRITE_LOCK (&type_rw_lock);
   1829     }
   1830 
   1831   for (i = 0; i < static_n_iface_check_funcs; i++)
   1832     {
   1833       GTypeInterfaceCheckFunc check_func = static_iface_check_funcs[i].check_func;
   1834       gpointer check_data = static_iface_check_funcs[i].check_data;
   1835 
   1836       G_WRITE_UNLOCK (&type_rw_lock);
   1837       check_func (check_data, (gpointer)vtable);
   1838       G_WRITE_LOCK (&type_rw_lock);
   1839     }
   1840 }
   1841 
   1842 static gboolean
   1843 type_iface_vtable_finalize_Wm (TypeNode       *iface,
   1844 			       TypeNode       *node,
   1845 			       GTypeInterface *vtable)
   1846 {
   1847   IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
   1848   IFaceHolder *iholder;
   1849 
   1850   /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
   1851   iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), FALSE);
   1852   if (!iholder)
   1853     return FALSE;	/* we don't modify write lock upon FALSE */
   1854 
   1855   g_assert (entry && entry->vtable == vtable && iholder->info);
   1856 
   1857   entry->vtable = NULL;
   1858   entry->init_state = UNINITIALIZED;
   1859   if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
   1860     {
   1861       G_WRITE_UNLOCK (&type_rw_lock);
   1862       if (iholder->info->interface_finalize)
   1863 	iholder->info->interface_finalize (vtable, iholder->info->interface_data);
   1864       if (iface->data->iface.vtable_finalize_base)
   1865 	iface->data->iface.vtable_finalize_base (vtable);
   1866       G_WRITE_LOCK (&type_rw_lock);
   1867     }
   1868   vtable->g_type = 0;
   1869   vtable->g_instance_type = 0;
   1870   g_free (vtable);
   1871 
   1872   type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
   1873 
   1874   return TRUE;	/* write lock modified */
   1875 }
   1876 
   1877 static void
   1878 type_class_init_Wm (TypeNode   *node,
   1879 		    GTypeClass *pclass)
   1880 {
   1881   GSList *slist, *init_slist = NULL;
   1882   GTypeClass *class;
   1883   IFaceEntry *entry;
   1884   TypeNode *bnode, *pnode;
   1885   guint i;
   1886 
   1887   g_assert (node->is_classed && node->data &&
   1888 	    node->data->class.class_size &&
   1889 	    !node->data->class.class &&
   1890 	    node->data->class.init_state == UNINITIALIZED);
   1891 
   1892   class = g_malloc0 (node->data->class.class_size);
   1893   node->data->class.class = class;
   1894   node->data->class.init_state = BASE_CLASS_INIT;
   1895 
   1896   if (pclass)
   1897     {
   1898       TypeNode *pnode = lookup_type_node_I (pclass->g_type);
   1899 
   1900       memcpy (class, pclass, pnode->data->class.class_size);
   1901 
   1902       if (node->is_instantiatable)
   1903 	{
   1904 	  /* We need to initialize the private_size here rather than in
   1905 	   * type_data_make_W() since the class init for the parent
   1906 	   * class may have changed pnode->data->instance.private_size.
   1907 	   */
   1908 	  node->data->instance.private_size = pnode->data->instance.private_size;
   1909 	}
   1910     }
   1911   class->g_type = NODE_TYPE (node);
   1912 
   1913   G_WRITE_UNLOCK (&type_rw_lock);
   1914 
   1915   /* stack all base class initialization functions, so we
   1916    * call them in ascending order.
   1917    */
   1918   for (bnode = node; bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
   1919     if (bnode->data->class.class_init_base)
   1920       init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
   1921   for (slist = init_slist; slist; slist = slist->next)
   1922     {
   1923       GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
   1924 
   1925       class_init_base (class);
   1926     }
   1927   g_slist_free (init_slist);
   1928 
   1929   G_WRITE_LOCK (&type_rw_lock);
   1930 
   1931   node->data->class.init_state = BASE_IFACE_INIT;
   1932 
   1933   /* Before we initialize the class, base initialize all interfaces, either
   1934    * from parent, or through our holder info
   1935    */
   1936   pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
   1937 
   1938   i = 0;
   1939   while (i < CLASSED_NODE_N_IFACES (node))
   1940     {
   1941       entry = &CLASSED_NODE_IFACES_ENTRIES (node)[i];
   1942       while (i < CLASSED_NODE_N_IFACES (node) &&
   1943 	     entry->init_state == IFACE_INIT)
   1944 	{
   1945 	  entry++;
   1946 	  i++;
   1947 	}
   1948 
   1949       if (i == CLASSED_NODE_N_IFACES (node))
   1950 	break;
   1951 
   1952       if (!type_iface_vtable_base_init_Wm (lookup_type_node_I (entry->iface_type), node))
   1953 	{
   1954 	  guint j;
   1955 
   1956 	  /* need to get this interface from parent, type_iface_vtable_base_init_Wm()
   1957 	   * doesn't modify write lock upon FALSE, so entry is still valid;
   1958 	   */
   1959 	  g_assert (pnode != NULL);
   1960 
   1961 	  for (j = 0; j < CLASSED_NODE_N_IFACES (pnode); j++)
   1962 	    {
   1963 	      IFaceEntry *pentry = CLASSED_NODE_IFACES_ENTRIES (pnode) + j;
   1964 
   1965 	      if (pentry->iface_type == entry->iface_type)
   1966 		{
   1967 		  entry->vtable = pentry->vtable;
   1968 		  entry->init_state = INITIALIZED;
   1969 		  break;
   1970 		}
   1971 	    }
   1972 	  g_assert (entry->vtable != NULL);
   1973 	}
   1974 
   1975       /* If the write lock was released, additional interface entries might
   1976        * have been inserted into CLASSED_NODE_IFACES_ENTRIES (node); they'll
   1977        * be base-initialized when inserted, so we don't have to worry that
   1978        * we might miss them. Uninitialized entries can only be moved higher
   1979        * when new ones are inserted.
   1980        */
   1981       i++;
   1982     }
   1983 
   1984   node->data->class.init_state = CLASS_INIT;
   1985 
   1986   G_WRITE_UNLOCK (&type_rw_lock);
   1987 
   1988   if (node->data->class.class_init)
   1989     node->data->class.class_init (class, (gpointer) node->data->class.class_data);
   1990 
   1991   G_WRITE_LOCK (&type_rw_lock);
   1992 
   1993   node->data->class.init_state = IFACE_INIT;
   1994 
   1995   /* finish initializing the interfaces through our holder info.
   1996    * inherited interfaces are already init_state == INITIALIZED, because
   1997    * they either got setup in the above base_init loop, or during
   1998    * class_init from within type_add_interface_Wm() for this or
   1999    * an anchestor type.
   2000    */
   2001   i = 0;
   2002   while (TRUE)
   2003     {
   2004       entry = &CLASSED_NODE_IFACES_ENTRIES (node)[i];
   2005       while (i < CLASSED_NODE_N_IFACES (node) &&
   2006 	     entry->init_state == INITIALIZED)
   2007 	{
   2008 	  entry++;
   2009 	  i++;
   2010 	}
   2011 
   2012       if (i == CLASSED_NODE_N_IFACES (node))
   2013 	break;
   2014 
   2015       type_iface_vtable_iface_init_Wm (lookup_type_node_I (entry->iface_type), node);
   2016 
   2017       /* As in the loop above, additional initialized entries might be inserted
   2018        * if the write lock is released, but that's harmless because the entries
   2019        * we need to initialize only move higher in the list.
   2020        */
   2021       i++;
   2022     }
   2023 
   2024   node->data->class.init_state = INITIALIZED;
   2025 }
   2026 
   2027 static void
   2028 type_data_finalize_class_ifaces_Wm (TypeNode *node)
   2029 {
   2030   guint i;
   2031 
   2032   g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
   2033 
   2034  reiterate:
   2035   for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
   2036     {
   2037       IFaceEntry *entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
   2038       if (entry->vtable)
   2039 	{
   2040           if (type_iface_vtable_finalize_Wm (lookup_type_node_I (entry->iface_type), node, entry->vtable))
   2041             {
   2042               /* refetch entries, IFACES_ENTRIES might be modified */
   2043               goto reiterate;
   2044             }
   2045           else
   2046             {
   2047               /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
   2048                * iface vtable came from parent
   2049                */
   2050               entry->vtable = NULL;
   2051               entry->init_state = UNINITIALIZED;
   2052             }
   2053 	}
   2054     }
   2055 }
   2056 
   2057 static void
   2058 type_data_finalize_class_U (TypeNode  *node,
   2059 			    ClassData *cdata)
   2060 {
   2061   GTypeClass *class = cdata->class;
   2062   TypeNode *bnode;
   2063 
   2064   g_assert (cdata->class && cdata->common.ref_count == 0);
   2065 
   2066   if (cdata->class_finalize)
   2067     cdata->class_finalize (class, (gpointer) cdata->class_data);
   2068 
   2069   /* call all base class destruction functions in descending order
   2070    */
   2071   if (cdata->class_finalize_base)
   2072     cdata->class_finalize_base (class);
   2073   for (bnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
   2074     if (bnode->data->class.class_finalize_base)
   2075       bnode->data->class.class_finalize_base (class);
   2076 
   2077   g_free (cdata->class);
   2078 }
   2079 
   2080 static void
   2081 type_data_last_unref_Wm (GType    type,
   2082 			 gboolean uncached)
   2083 {
   2084   TypeNode *node = lookup_type_node_I (type);
   2085 
   2086   g_return_if_fail (node != NULL && node->plugin != NULL);
   2087 
   2088   if (!node->data || node->data->common.ref_count == 0)
   2089     {
   2090       g_warning ("cannot drop last reference to unreferenced type `%s'",
   2091 		 type_descriptive_name_I (type));
   2092       return;
   2093     }
   2094 
   2095   /* call class cache hooks */
   2096   if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs && !uncached)
   2097     {
   2098       guint i;
   2099 
   2100       G_WRITE_UNLOCK (&type_rw_lock);
   2101       G_READ_LOCK (&type_rw_lock);
   2102       for (i = 0; i < static_n_class_cache_funcs; i++)
   2103 	{
   2104 	  GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func;
   2105 	  gpointer cache_data = static_class_cache_funcs[i].cache_data;
   2106 	  gboolean need_break;
   2107 
   2108 	  G_READ_UNLOCK (&type_rw_lock);
   2109 	  need_break = cache_func (cache_data, node->data->class.class);
   2110 	  G_READ_LOCK (&type_rw_lock);
   2111 	  if (!node->data || node->data->common.ref_count == 0)
   2112 	    INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
   2113 	  if (need_break)
   2114 	    break;
   2115 	}
   2116       G_READ_UNLOCK (&type_rw_lock);
   2117       G_WRITE_LOCK (&type_rw_lock);
   2118     }
   2119 
   2120   if (node->data->common.ref_count > 1)	/* may have been re-referenced meanwhile */
   2121     node->data->common.ref_count -= 1;
   2122   else
   2123     {
   2124       GType ptype = NODE_PARENT_TYPE (node);
   2125       TypeData *tdata;
   2126 
   2127       node->data->common.ref_count = 0;
   2128 
   2129       if (node->is_instantiatable)
   2130 	{
   2131 	  /* destroy node->data->instance.mem_chunk */
   2132 	}
   2133 
   2134       tdata = node->data;
   2135       if (node->is_classed && tdata->class.class)
   2136 	{
   2137 	  if (CLASSED_NODE_N_IFACES (node))
   2138 	    type_data_finalize_class_ifaces_Wm (node);
   2139 	  node->mutatable_check_cache = FALSE;
   2140 	  node->data = NULL;
   2141 	  G_WRITE_UNLOCK (&type_rw_lock);
   2142 	  type_data_finalize_class_U (node, &tdata->class);
   2143 	  G_WRITE_LOCK (&type_rw_lock);
   2144 	}
   2145       else if (NODE_IS_IFACE (node) && tdata->iface.dflt_vtable)
   2146         {
   2147           node->mutatable_check_cache = FALSE;
   2148           node->data = NULL;
   2149           if (tdata->iface.dflt_finalize || tdata->iface.vtable_finalize_base)
   2150             {
   2151               G_WRITE_UNLOCK (&type_rw_lock);
   2152               if (tdata->iface.dflt_finalize)
   2153                 tdata->iface.dflt_finalize (tdata->iface.dflt_vtable, (gpointer) tdata->iface.dflt_data);
   2154               if (tdata->iface.vtable_finalize_base)
   2155                 tdata->iface.vtable_finalize_base (tdata->iface.dflt_vtable);
   2156               G_WRITE_LOCK (&type_rw_lock);
   2157             }
   2158           g_free (tdata->iface.dflt_vtable);
   2159         }
   2160       else
   2161         {
   2162           node->mutatable_check_cache = FALSE;
   2163           node->data = NULL;
   2164         }
   2165 
   2166       /* freeing tdata->common.value_table and its contents is taken care of
   2167        * by allocating it in one chunk with tdata
   2168        */
   2169       g_free (tdata);
   2170 
   2171       G_WRITE_UNLOCK (&type_rw_lock);
   2172       g_type_plugin_unuse (node->plugin);
   2173       G_WRITE_LOCK (&type_rw_lock);
   2174       if (ptype)
   2175 	type_data_unref_WmREC (lookup_type_node_I (ptype), FALSE);
   2176     }
   2177 }
   2178 
   2179 /**
   2180  * g_type_add_class_cache_func:
   2181  * @cache_data: data to be passed to @cache_func
   2182  * @cache_func: a #GTypeClassCacheFunc
   2183  *
   2184  * Adds a #GTypeClassCacheFunc to be called before the reference count of a
   2185  * class goes from one to zero. This can be used to prevent premature class
   2186  * destruction. All installed #GTypeClassCacheFunc functions will be chained
   2187  * until one of them returns %TRUE. The functions have to check the class id
   2188  * passed in to figure whether they actually want to cache the class of this
   2189  * type, since all classes are routed through the same #GTypeClassCacheFunc
   2190  * chain.
   2191  */
   2192 void
   2193 g_type_add_class_cache_func (gpointer            cache_data,
   2194 			     GTypeClassCacheFunc cache_func)
   2195 {
   2196   guint i;
   2197 
   2198   g_return_if_fail (cache_func != NULL);
   2199 
   2200   G_WRITE_LOCK (&type_rw_lock);
   2201   i = static_n_class_cache_funcs++;
   2202   static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
   2203   static_class_cache_funcs[i].cache_data = cache_data;
   2204   static_class_cache_funcs[i].cache_func = cache_func;
   2205   G_WRITE_UNLOCK (&type_rw_lock);
   2206 }
   2207 
   2208 /**
   2209  * g_type_remove_class_cache_func:
   2210  * @cache_data: data that was given when adding @cache_func
   2211  * @cache_func: a #GTypeClassCacheFunc
   2212  *
   2213  * Removes a previously installed #GTypeClassCacheFunc. The cache
   2214  * maintained by @cache_func has to be empty when calling
   2215  * g_type_remove_class_cache_func() to avoid leaks.
   2216  */
   2217 void
   2218 g_type_remove_class_cache_func (gpointer            cache_data,
   2219 				GTypeClassCacheFunc cache_func)
   2220 {
   2221   gboolean found_it = FALSE;
   2222   guint i;
   2223 
   2224   g_return_if_fail (cache_func != NULL);
   2225 
   2226   G_WRITE_LOCK (&type_rw_lock);
   2227   for (i = 0; i < static_n_class_cache_funcs; i++)
   2228     if (static_class_cache_funcs[i].cache_data == cache_data &&
   2229 	static_class_cache_funcs[i].cache_func == cache_func)
   2230       {
   2231 	static_n_class_cache_funcs--;
   2232 	g_memmove (static_class_cache_funcs + i,
   2233 		   static_class_cache_funcs + i + 1,
   2234 		   sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
   2235 	static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
   2236 	found_it = TRUE;
   2237 	break;
   2238       }
   2239   G_WRITE_UNLOCK (&type_rw_lock);
   2240 
   2241   if (!found_it)
   2242     g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
   2243 	       cache_func, cache_data);
   2244 }
   2245 
   2246 
   2247 /**
   2248  * g_type_add_interface_check:
   2249  * @check_data: data to pass to @check_func
   2250  * @check_func: function to be called after each interface
   2251  *              is initialized.
   2252  *
   2253  * Adds a function to be called after an interface vtable is
   2254  * initialized for any class (i.e. after the @interface_init member of
   2255  * #GInterfaceInfo has been called).
   2256  *
   2257  * This function is useful when you want to check an invariant that
   2258  * depends on the interfaces of a class. For instance, the
   2259  * implementation of #GObject uses this facility to check that an
   2260  * object implements all of the properties that are defined on its
   2261  * interfaces.
   2262  *
   2263  * Since: 2.4
   2264  */
   2265 void
   2266 g_type_add_interface_check (gpointer	            check_data,
   2267 			    GTypeInterfaceCheckFunc check_func)
   2268 {
   2269   guint i;
   2270 
   2271   g_return_if_fail (check_func != NULL);
   2272 
   2273   G_WRITE_LOCK (&type_rw_lock);
   2274   i = static_n_iface_check_funcs++;
   2275   static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
   2276   static_iface_check_funcs[i].check_data = check_data;
   2277   static_iface_check_funcs[i].check_func = check_func;
   2278   G_WRITE_UNLOCK (&type_rw_lock);
   2279 }
   2280 
   2281 /**
   2282  * g_type_remove_interface_check:
   2283  * @check_data: callback data passed to g_type_add_interface_check()
   2284  * @check_func: callback function passed to g_type_add_interface_check()
   2285  *
   2286  * Removes an interface check function added with
   2287  * g_type_add_interface_check().
   2288  *
   2289  * Since: 2.4
   2290  */
   2291 void
   2292 g_type_remove_interface_check (gpointer                check_data,
   2293 			       GTypeInterfaceCheckFunc check_func)
   2294 {
   2295   gboolean found_it = FALSE;
   2296   guint i;
   2297 
   2298   g_return_if_fail (check_func != NULL);
   2299 
   2300   G_WRITE_LOCK (&type_rw_lock);
   2301   for (i = 0; i < static_n_iface_check_funcs; i++)
   2302     if (static_iface_check_funcs[i].check_data == check_data &&
   2303 	static_iface_check_funcs[i].check_func == check_func)
   2304       {
   2305 	static_n_iface_check_funcs--;
   2306 	g_memmove (static_iface_check_funcs + i,
   2307 		   static_iface_check_funcs + i + 1,
   2308 		   sizeof (static_iface_check_funcs[0]) * (static_n_iface_check_funcs - i));
   2309 	static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
   2310 	found_it = TRUE;
   2311 	break;
   2312       }
   2313   G_WRITE_UNLOCK (&type_rw_lock);
   2314 
   2315   if (!found_it)
   2316     g_warning (G_STRLOC ": cannot remove unregistered class check func %p with data %p",
   2317 	       check_func, check_data);
   2318 }
   2319 
   2320 /* --- type registration --- */
   2321 /**
   2322  * g_type_register_fundamental:
   2323  * @type_id: A predefined type identifier.
   2324  * @type_name: 0-terminated string used as the name of the new type.
   2325  * @info: The #GTypeInfo structure for this type.
   2326  * @finfo: The #GTypeFundamentalInfo structure for this type.
   2327  * @flags: Bitwise combination of #GTypeFlags values.
   2328  *
   2329  * Registers @type_id as the predefined identifier and @type_name as the
   2330  * name of a fundamental type.  The type system uses the information
   2331  * contained in the #GTypeInfo structure pointed to by @info and the
   2332  * #GTypeFundamentalInfo structure pointed to by @finfo to manage the
   2333  * type and its instances.  The value of @flags determines additional
   2334  * characteristics of the fundamental type.
   2335  *
   2336  * Returns: The predefined type identifier.
   2337  */
   2338 GType
   2339 g_type_register_fundamental (GType                       type_id,
   2340 			     const gchar                *type_name,
   2341 			     const GTypeInfo            *info,
   2342 			     const GTypeFundamentalInfo *finfo,
   2343 			     GTypeFlags			 flags)
   2344 {
   2345   TypeNode *node;
   2346 
   2347   g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
   2348   g_return_val_if_fail (type_id > 0, 0);
   2349   g_return_val_if_fail (type_name != NULL, 0);
   2350   g_return_val_if_fail (info != NULL, 0);
   2351   g_return_val_if_fail (finfo != NULL, 0);
   2352 
   2353   if (!check_type_name_I (type_name))
   2354     return 0;
   2355   if ((type_id & TYPE_ID_MASK) ||
   2356       type_id > G_TYPE_FUNDAMENTAL_MAX)
   2357     {
   2358       g_warning ("attempt to register fundamental type `%s' with invalid type id (%" G_GSIZE_FORMAT ")",
   2359 		 type_name,
   2360 		 type_id);
   2361       return 0;
   2362     }
   2363   if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
   2364       !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
   2365     {
   2366       g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
   2367 		 type_name);
   2368       return 0;
   2369     }
   2370   if (lookup_type_node_I (type_id))
   2371     {
   2372       g_warning ("cannot register existing fundamental type `%s' (as `%s')",
   2373 		 type_descriptive_name_I (type_id),
   2374 		 type_name);
   2375       return 0;
   2376     }
   2377 
   2378   G_WRITE_LOCK (&type_rw_lock);
   2379   node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
   2380   type_add_flags_W (node, flags);
   2381 
   2382   if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info))
   2383     type_data_make_W (node, info,
   2384 		      check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
   2385   G_WRITE_UNLOCK (&type_rw_lock);
   2386 
   2387   return NODE_TYPE (node);
   2388 }
   2389 
   2390 /**
   2391  * g_type_register_static_simple:
   2392  * @parent_type: Type from which this type will be derived.
   2393  * @type_name: 0-terminated string used as the name of the new type.
   2394  * @class_size: Size of the class structure (see #GTypeInfo)
   2395  * @class_init: Location of the class initialization function (see #GTypeInfo)
   2396  * @instance_size: Size of the instance structure (see #GTypeInfo)
   2397  * @instance_init: Location of the instance initialization function (see #GTypeInfo)
   2398  * @flags: Bitwise combination of #GTypeFlags values.
   2399  *
   2400  * Registers @type_name as the name of a new static type derived from
   2401  * @parent_type.  The value of @flags determines the nature (e.g.
   2402  * abstract or not) of the type. It works by filling a #GTypeInfo
   2403  * struct and calling g_type_register_static().
   2404  *
   2405  * Since: 2.12
   2406  *
   2407  * Returns: The new type identifier.
   2408  */
   2409 GType
   2410 g_type_register_static_simple (GType             parent_type,
   2411 			       const gchar      *type_name,
   2412 			       guint             class_size,
   2413 			       GClassInitFunc    class_init,
   2414 			       guint             instance_size,
   2415 			       GInstanceInitFunc instance_init,
   2416 			       GTypeFlags	 flags)
   2417 {
   2418   GTypeInfo info;
   2419 
   2420   info.class_size = class_size;
   2421   info.base_init = NULL;
   2422   info.base_finalize = NULL;
   2423   info.class_init = class_init;
   2424   info.class_finalize = NULL;
   2425   info.class_data = NULL;
   2426   info.instance_size = instance_size;
   2427   info.n_preallocs = 0;
   2428   info.instance_init = instance_init;
   2429   info.value_table = NULL;
   2430 
   2431   return g_type_register_static (parent_type, type_name, &info, flags);
   2432 }
   2433 
   2434 /**
   2435  * g_type_register_static:
   2436  * @parent_type: Type from which this type will be derived.
   2437  * @type_name: 0-terminated string used as the name of the new type.
   2438  * @info: The #GTypeInfo structure for this type.
   2439  * @flags: Bitwise combination of #GTypeFlags values.
   2440  *
   2441  * Registers @type_name as the name of a new static type derived from
   2442  * @parent_type.  The type system uses the information contained in the
   2443  * #GTypeInfo structure pointed to by @info to manage the type and its
   2444  * instances (if not abstract).  The value of @flags determines the nature
   2445  * (e.g. abstract or not) of the type.
   2446  *
   2447  * Returns: The new type identifier.
   2448  */
   2449 GType
   2450 g_type_register_static (GType            parent_type,
   2451 			const gchar     *type_name,
   2452 			const GTypeInfo *info,
   2453 			GTypeFlags	 flags)
   2454 {
   2455   TypeNode *pnode, *node;
   2456   GType type = 0;
   2457 
   2458   g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
   2459   g_return_val_if_fail (parent_type > 0, 0);
   2460   g_return_val_if_fail (type_name != NULL, 0);
   2461   g_return_val_if_fail (info != NULL, 0);
   2462 
   2463   if (!check_type_name_I (type_name) ||
   2464       !check_derivation_I (parent_type, type_name))
   2465     return 0;
   2466   if (info->class_finalize)
   2467     {
   2468       g_warning ("class finalizer specified for static type `%s'",
   2469 		 type_name);
   2470       return 0;
   2471     }
   2472 
   2473   pnode = lookup_type_node_I (parent_type);
   2474   G_WRITE_LOCK (&type_rw_lock);
   2475   type_data_ref_Wm (pnode);
   2476   if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info))
   2477     {
   2478       node = type_node_new_W (pnode, type_name, NULL);
   2479       type_add_flags_W (node, flags);
   2480       type = NODE_TYPE (node);
   2481       type_data_make_W (node, info,
   2482 			check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
   2483     }
   2484   G_WRITE_UNLOCK (&type_rw_lock);
   2485 
   2486   return type;
   2487 }
   2488 
   2489 /**
   2490  * g_type_register_dynamic:
   2491  * @parent_type: Type from which this type will be derived.
   2492  * @type_name: 0-terminated string used as the name of the new type.
   2493  * @plugin: The #GTypePlugin structure to retrieve the #GTypeInfo from.
   2494  * @flags: Bitwise combination of #GTypeFlags values.
   2495  *
   2496  * Registers @type_name as the name of a new dynamic type derived from
   2497  * @parent_type.  The type system uses the information contained in the
   2498  * #GTypePlugin structure pointed to by @plugin to manage the type and its
   2499  * instances (if not abstract).  The value of @flags determines the nature
   2500  * (e.g. abstract or not) of the type.
   2501  *
   2502  * Returns: The new type identifier or #G_TYPE_INVALID if registration failed.
   2503  */
   2504 GType
   2505 g_type_register_dynamic (GType        parent_type,
   2506 			 const gchar *type_name,
   2507 			 GTypePlugin *plugin,
   2508 			 GTypeFlags   flags)
   2509 {
   2510   TypeNode *pnode, *node;
   2511   GType type;
   2512 
   2513   g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
   2514   g_return_val_if_fail (parent_type > 0, 0);
   2515   g_return_val_if_fail (type_name != NULL, 0);
   2516   g_return_val_if_fail (plugin != NULL, 0);
   2517 
   2518   if (!check_type_name_I (type_name) ||
   2519       !check_derivation_I (parent_type, type_name) ||
   2520       !check_plugin_U (plugin, TRUE, FALSE, type_name))
   2521     return 0;
   2522 
   2523   G_WRITE_LOCK (&type_rw_lock);
   2524   pnode = lookup_type_node_I (parent_type);
   2525   node = type_node_new_W (pnode, type_name, plugin);
   2526   type_add_flags_W (node, flags);
   2527   type = NODE_TYPE (node);
   2528   G_WRITE_UNLOCK (&type_rw_lock);
   2529 
   2530   return type;
   2531 }
   2532 
   2533 /**
   2534  * g_type_add_interface_static:
   2535  * @instance_type: #GType value of an instantiable type.
   2536  * @interface_type: #GType value of an interface type.
   2537  * @info: The #GInterfaceInfo structure for this
   2538  *        (@instance_type, @interface_type) combination.
   2539  *
   2540  * Adds the static @interface_type to @instantiable_type.  The information
   2541  * contained in the #GTypeInterfaceInfo structure pointed to by @info
   2542  * is used to manage the relationship.
   2543  */
   2544 void
   2545 g_type_add_interface_static (GType                 instance_type,
   2546 			     GType                 interface_type,
   2547 			     const GInterfaceInfo *info)
   2548 {
   2549   /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
   2550   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
   2551   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
   2552 
   2553   /* we only need to lock class_init_rec_mutex if instance_type already has its
   2554    * class initialized, however this function is rarely enough called to take
   2555    * the simple route and always acquire class_init_rec_mutex.
   2556    */
   2557   g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
   2558   G_WRITE_LOCK (&type_rw_lock);
   2559   if (check_add_interface_L (instance_type, interface_type))
   2560     {
   2561       TypeNode *node = lookup_type_node_I (instance_type);
   2562       TypeNode *iface = lookup_type_node_I (interface_type);
   2563       if (check_interface_info_I (iface, NODE_TYPE (node), info))
   2564         type_add_interface_Wm (node, iface, info, NULL);
   2565     }
   2566   G_WRITE_UNLOCK (&type_rw_lock);
   2567   g_static_rec_mutex_unlock (&class_init_rec_mutex);
   2568 }
   2569 
   2570 /**
   2571  * g_type_add_interface_dynamic:
   2572  * @instance_type: the #GType value of an instantiable type.
   2573  * @interface_type: the #GType value of an interface type.
   2574  * @plugin: the #GTypePlugin structure to retrieve the #GInterfaceInfo from.
   2575  *
   2576  * Adds the dynamic @interface_type to @instantiable_type. The information
   2577  * contained in the #GTypePlugin structure pointed to by @plugin
   2578  * is used to manage the relationship.
   2579  */
   2580 void
   2581 g_type_add_interface_dynamic (GType        instance_type,
   2582 			      GType        interface_type,
   2583 			      GTypePlugin *plugin)
   2584 {
   2585   TypeNode *node;
   2586   /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
   2587   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
   2588   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
   2589 
   2590   node = lookup_type_node_I (instance_type);
   2591   if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
   2592     return;
   2593 
   2594   /* see comment in g_type_add_interface_static() about class_init_rec_mutex */
   2595   g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
   2596   G_WRITE_LOCK (&type_rw_lock);
   2597   if (check_add_interface_L (instance_type, interface_type))
   2598     {
   2599       TypeNode *iface = lookup_type_node_I (interface_type);
   2600       type_add_interface_Wm (node, iface, NULL, plugin);
   2601     }
   2602   G_WRITE_UNLOCK (&type_rw_lock);
   2603   g_static_rec_mutex_unlock (&class_init_rec_mutex);
   2604 }
   2605 
   2606 
   2607 /* --- public API functions --- */
   2608 /**
   2609  * g_type_class_ref:
   2610  * @type: Type ID of a classed type.
   2611  *
   2612  * Increments the reference count of the class structure belonging to
   2613  * @type. This function will demand-create the class if it doesn't
   2614  * exist already.
   2615  *
   2616  * Returns: The #GTypeClass structure for the given type ID.
   2617  */
   2618 gpointer
   2619 g_type_class_ref (GType type)
   2620 {
   2621   TypeNode *node;
   2622   GType ptype;
   2623 
   2624   /* optimize for common code path */
   2625   G_WRITE_LOCK (&type_rw_lock);
   2626   node = lookup_type_node_I (type);
   2627   if (node && node->is_classed && node->data &&
   2628       node->data->class.class &&
   2629       node->data->class.init_state == INITIALIZED)
   2630     {
   2631       type_data_ref_Wm (node);
   2632       G_WRITE_UNLOCK (&type_rw_lock);
   2633       return node->data->class.class;
   2634     }
   2635   if (!node || !node->is_classed ||
   2636       (node->data && node->data->common.ref_count < 1))
   2637     {
   2638       G_WRITE_UNLOCK (&type_rw_lock);
   2639       g_warning ("cannot retrieve class for invalid (unclassed) type `%s'",
   2640 		 type_descriptive_name_I (type));
   2641       return NULL;
   2642     }
   2643   type_data_ref_Wm (node);
   2644   ptype = NODE_PARENT_TYPE (node);
   2645   G_WRITE_UNLOCK (&type_rw_lock);
   2646 
   2647   g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
   2648   /* here, we either have node->data->class.class == NULL, or a recursive
   2649    * call to g_type_class_ref() with a partly initialized class, or
   2650    * node->data->class.init_state == INITIALIZED, because any
   2651    * concurrently running initialization was guarded by class_init_rec_mutex.
   2652    */
   2653   if (!node->data->class.class) /* class uninitialized */
   2654     {
   2655       /* acquire reference on parent class */
   2656       GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL;
   2657       G_WRITE_LOCK (&type_rw_lock);
   2658       if (node->data->class.class) /* class was initialized during parent class initialization? */
   2659         INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
   2660       type_class_init_Wm (node, pclass);
   2661       G_WRITE_UNLOCK (&type_rw_lock);
   2662     }
   2663   g_static_rec_mutex_unlock (&class_init_rec_mutex);
   2664 
   2665   return node->data->class.class;
   2666 }
   2667 
   2668 /**
   2669  * g_type_class_unref:
   2670  * @g_class: The #GTypeClass structure to unreference.
   2671  *
   2672  * Decrements the reference count of the class structure being passed in.
   2673  * Once the last reference count of a class has been released, classes
   2674  * may be finalized by the type system, so further dereferencing of a
   2675  * class pointer after g_type_class_unref() are invalid.
   2676  */
   2677 void
   2678 g_type_class_unref (gpointer g_class)
   2679 {
   2680   TypeNode *node;
   2681   GTypeClass *class = g_class;
   2682 
   2683   g_return_if_fail (g_class != NULL);
   2684 
   2685   node = lookup_type_node_I (class->g_type);
   2686   G_WRITE_LOCK (&type_rw_lock);
   2687   if (node && node->is_classed && node->data &&
   2688       node->data->class.class == class && node->data->common.ref_count > 0)
   2689     type_data_unref_WmREC (node, FALSE);
   2690   else
   2691     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
   2692 	       type_descriptive_name_I (class->g_type));
   2693   G_WRITE_UNLOCK (&type_rw_lock);
   2694 }
   2695 
   2696 /**
   2697  * g_type_class_unref_uncached:
   2698  * @g_class: The #GTypeClass structure to unreference.
   2699  *
   2700  * A variant of g_type_class_unref() for use in #GTypeClassCacheFunc
   2701  * implementations. It unreferences a class without consulting the chain
   2702  * of #GTypeClassCacheFunc<!-- -->s, avoiding the recursion which would occur
   2703  * otherwise.
   2704  */
   2705 void
   2706 g_type_class_unref_uncached (gpointer g_class)
   2707 {
   2708   TypeNode *node;
   2709   GTypeClass *class = g_class;
   2710 
   2711   g_return_if_fail (g_class != NULL);
   2712 
   2713   G_WRITE_LOCK (&type_rw_lock);
   2714   node = lookup_type_node_I (class->g_type);
   2715   if (node && node->is_classed && node->data &&
   2716       node->data->class.class == class && node->data->common.ref_count > 0)
   2717     type_data_unref_WmREC (node, TRUE);
   2718   else
   2719     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
   2720 	       type_descriptive_name_I (class->g_type));
   2721   G_WRITE_UNLOCK (&type_rw_lock);
   2722 }
   2723 
   2724 /**
   2725  * g_type_class_peek:
   2726  * @type: Type ID of a classed type.
   2727  *
   2728  * This function is essentially the same as g_type_class_ref(), except that
   2729  * the classes reference count isn't incremented. As a consequence, this function
   2730  * may return %NULL if the class of the type passed in does not currently
   2731  * exist (hasn't been referenced before).
   2732  *
   2733  * Returns: The #GTypeClass structure for the given type ID or %NULL
   2734  *  if the class does not currently exist.
   2735  */
   2736 gpointer
   2737 g_type_class_peek (GType type)
   2738 {
   2739   TypeNode *node;
   2740   gpointer class;
   2741 
   2742   node = lookup_type_node_I (type);
   2743   G_READ_LOCK (&type_rw_lock);
   2744   if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
   2745     class = node->data->class.class;
   2746   else
   2747     class = NULL;
   2748   G_READ_UNLOCK (&type_rw_lock);
   2749 
   2750   return class;
   2751 }
   2752 
   2753 /**
   2754  * g_type_class_peek_static:
   2755  * @type: Type ID of a classed type.
   2756  *
   2757  * A more efficient version of g_type_class_peek() which works only for
   2758  * static types.
   2759  *
   2760  * Since: 2.4
   2761  * Returns: The #GTypeClass structure for the given type ID or %NULL
   2762  *  if the class does not currently exist or is dynamically loaded.
   2763  */
   2764 gpointer
   2765 g_type_class_peek_static (GType type)
   2766 {
   2767   TypeNode *node;
   2768   gpointer class;
   2769 
   2770   node = lookup_type_node_I (type);
   2771   G_READ_LOCK (&type_rw_lock);
   2772   if (node && node->is_classed && node->data &&
   2773       /* peek only static types: */ node->plugin == NULL &&
   2774       node->data->class.class) /* common.ref_count _may_ be 0 */
   2775     class = node->data->class.class;
   2776   else
   2777     class = NULL;
   2778   G_READ_UNLOCK (&type_rw_lock);
   2779 
   2780   return class;
   2781 }
   2782 
   2783 /**
   2784  * g_type_class_peek_parent:
   2785  * @g_class: The #GTypeClass structure to retrieve the parent class for.
   2786  *
   2787  * This is a convenience function often needed in class initializers.
   2788  * It returns the class structure of the immediate parent type of the
   2789  * class passed in.  Since derived classes hold a reference count on
   2790  * their parent classes as long as they are instantiated, the returned
   2791  * class will always exist. This function is essentially equivalent
   2792  * to:
   2793  *
   2794  * <programlisting>
   2795  * g_type_class_peek (g_type_parent (G_TYPE_FROM_CLASS (g_class)));
   2796  * </programlisting>
   2797  *
   2798  * Returns: The parent class of @g_class.
   2799  */
   2800 gpointer
   2801 g_type_class_peek_parent (gpointer g_class)
   2802 {
   2803   TypeNode *node;
   2804   gpointer class = NULL;
   2805 
   2806   g_return_val_if_fail (g_class != NULL, NULL);
   2807 
   2808   node = lookup_type_node_I (G_TYPE_FROM_CLASS (g_class));
   2809   /* We used to acquire a read lock here. That is not necessary, since
   2810    * parent->data->class.class is constant as long as the derived class
   2811    * exists.
   2812    */
   2813   if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
   2814     {
   2815       node = lookup_type_node_I (NODE_PARENT_TYPE (node));
   2816       class = node->data->class.class;
   2817     }
   2818   else if (NODE_PARENT_TYPE (node))
   2819     g_warning (G_STRLOC ": invalid class pointer `%p'", g_class);
   2820 
   2821   return class;
   2822 }
   2823 
   2824 /**
   2825  * g_type_interface_peek:
   2826  * @instance_class: A #GTypeClass structure.
   2827  * @iface_type: An interface ID which this class conforms to.
   2828  *
   2829  * Returns the #GTypeInterface structure of an interface to which the
   2830  * passed in class conforms.
   2831  *
   2832  * Returns: The GTypeInterface structure of iface_type if implemented
   2833  *          by @instance_class, %NULL otherwise
   2834  */
   2835 gpointer
   2836 g_type_interface_peek (gpointer instance_class,
   2837 		       GType    iface_type)
   2838 {
   2839   TypeNode *node;
   2840   TypeNode *iface;
   2841   gpointer vtable = NULL;
   2842   GTypeClass *class = instance_class;
   2843 
   2844   g_return_val_if_fail (instance_class != NULL, NULL);
   2845 
   2846   node = lookup_type_node_I (class->g_type);
   2847   iface = lookup_type_node_I (iface_type);
   2848   if (node && node->is_instantiatable && iface)
   2849     {
   2850       IFaceEntry *entry;
   2851 
   2852       G_READ_LOCK (&type_rw_lock);
   2853 
   2854       entry = type_lookup_iface_entry_L (node, iface);
   2855       if (entry && entry->vtable)	/* entry is relocatable */
   2856 	vtable = entry->vtable;
   2857 
   2858       G_READ_UNLOCK (&type_rw_lock);
   2859     }
   2860   else
   2861     g_warning (G_STRLOC ": invalid class pointer `%p'", class);
   2862 
   2863   return vtable;
   2864 }
   2865 
   2866 /**
   2867  * g_type_interface_peek_parent:
   2868  * @g_iface: A #GTypeInterface structure.
   2869  *
   2870  * Returns the corresponding #GTypeInterface structure of the parent type
   2871  * of the instance type to which @g_iface belongs. This is useful when
   2872  * deriving the implementation of an interface from the parent type and
   2873  * then possibly overriding some methods.
   2874  *
   2875  * Returns: The corresponding #GTypeInterface structure of the parent
   2876  *          type of the instance type to which @g_iface belongs, or
   2877  *          %NULL if the parent type doesn't conform to the interface.
   2878  */
   2879 gpointer
   2880 g_type_interface_peek_parent (gpointer g_iface)
   2881 {
   2882   TypeNode *node;
   2883   TypeNode *iface;
   2884   gpointer vtable = NULL;
   2885   GTypeInterface *iface_class = g_iface;
   2886 
   2887   g_return_val_if_fail (g_iface != NULL, NULL);
   2888 
   2889   iface = lookup_type_node_I (iface_class->g_type);
   2890   node = lookup_type_node_I (iface_class->g_instance_type);
   2891   if (node)
   2892     node = lookup_type_node_I (NODE_PARENT_TYPE (node));
   2893   if (node && node->is_instantiatable && iface)
   2894     {
   2895       IFaceEntry *entry;
   2896 
   2897       G_READ_LOCK (&type_rw_lock);
   2898 
   2899       entry = type_lookup_iface_entry_L (node, iface);
   2900       if (entry && entry->vtable)	/* entry is relocatable */
   2901 	vtable = entry->vtable;
   2902 
   2903       G_READ_UNLOCK (&type_rw_lock);
   2904     }
   2905   else if (node)
   2906     g_warning (G_STRLOC ": invalid interface pointer `%p'", g_iface);
   2907 
   2908   return vtable;
   2909 }
   2910 
   2911 /**
   2912  * g_type_default_interface_ref:
   2913  * @g_type: an interface type
   2914  *
   2915  * Increments the reference count for the interface type @g_type,
   2916  * and returns the default interface vtable for the type.
   2917  *
   2918  * If the type is not currently in use, then the default vtable
   2919  * for the type will be created and initalized by calling
   2920  * the base interface init and default vtable init functions for
   2921  * the type (the @<structfield>base_init</structfield>
   2922  * and <structfield>class_init</structfield> members of #GTypeInfo).
   2923  * Calling g_type_default_interface_ref() is useful when you
   2924  * want to make sure that signals and properties for an interface
   2925  * have been installed.
   2926  *
   2927  * Since: 2.4
   2928  *
   2929  * Returns: the default vtable for the interface; call
   2930  *          g_type_default_interface_unref() when you are done using
   2931  *          the interface.
   2932  */
   2933 gpointer
   2934 g_type_default_interface_ref (GType g_type)
   2935 {
   2936   TypeNode *node;
   2937   gpointer dflt_vtable;
   2938 
   2939   G_WRITE_LOCK (&type_rw_lock);
   2940 
   2941   node = lookup_type_node_I (g_type);
   2942   if (!node || !NODE_IS_IFACE (node) ||
   2943       (node->data && node->data->common.ref_count < 1))
   2944     {
   2945       G_WRITE_UNLOCK (&type_rw_lock);
   2946       g_warning ("cannot retrieve default vtable for invalid or non-interface type '%s'",
   2947 		 type_descriptive_name_I (g_type));
   2948       return NULL;
   2949     }
   2950 
   2951   if (!node->data || !node->data->iface.dflt_vtable)
   2952     {
   2953       G_WRITE_UNLOCK (&type_rw_lock);
   2954       g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
   2955       G_WRITE_LOCK (&type_rw_lock);
   2956       node = lookup_type_node_I (g_type);
   2957       type_data_ref_Wm (node);
   2958       type_iface_ensure_dflt_vtable_Wm (node);
   2959       g_static_rec_mutex_unlock (&class_init_rec_mutex);
   2960     }
   2961   else
   2962     type_data_ref_Wm (node); /* ref_count >= 1 already */
   2963 
   2964   dflt_vtable = node->data->iface.dflt_vtable;
   2965   G_WRITE_UNLOCK (&type_rw_lock);
   2966 
   2967   return dflt_vtable;
   2968 }
   2969 
   2970 /**
   2971  * g_type_default_interface_peek:
   2972  * @g_type: an interface type
   2973  *
   2974  * If the interface type @g_type is currently in use, returns its
   2975  * default interface vtable.
   2976  *
   2977  * Since: 2.4
   2978  *
   2979  * Returns: the default vtable for the interface, or %NULL
   2980  *          if the type is not currently in use.
   2981  */
   2982 gpointer
   2983 g_type_default_interface_peek (GType g_type)
   2984 {
   2985   TypeNode *node;
   2986   gpointer vtable;
   2987 
   2988   node = lookup_type_node_I (g_type);
   2989   G_READ_LOCK (&type_rw_lock);
   2990   if (node && NODE_IS_IFACE (node) && node->data && node->data->iface.dflt_vtable)
   2991     vtable = node->data->iface.dflt_vtable;
   2992   else
   2993     vtable = NULL;
   2994   G_READ_UNLOCK (&type_rw_lock);
   2995 
   2996   return vtable;
   2997 }
   2998 
   2999 /**
   3000  * g_type_default_interface_unref:
   3001  * @g_iface: the default vtable structure for a interface, as
   3002  *           returned by g_type_default_interface_ref()
   3003  *
   3004  * Decrements the reference count for the type corresponding to the
   3005  * interface default vtable @g_iface. If the type is dynamic, then
   3006  * when no one is using the interface and all references have
   3007  * been released, the finalize function for the interface's default
   3008  * vtable (the <structfield>class_finalize</structfield> member of
   3009  * #GTypeInfo) will be called.
   3010  *
   3011  * Since: 2.4
   3012  */
   3013 void
   3014 g_type_default_interface_unref (gpointer g_iface)
   3015 {
   3016   TypeNode *node;
   3017   GTypeInterface *vtable = g_iface;
   3018 
   3019   g_return_if_fail (g_iface != NULL);
   3020 
   3021   node = lookup_type_node_I (vtable->g_type);
   3022   G_WRITE_LOCK (&type_rw_lock);
   3023   if (node && NODE_IS_IFACE (node) &&
   3024       node->data->iface.dflt_vtable == g_iface &&
   3025       node->data->common.ref_count > 0)
   3026     type_data_unref_WmREC (node, FALSE);
   3027   else
   3028     g_warning ("cannot unreference invalid interface default vtable for '%s'",
   3029 	       type_descriptive_name_I (vtable->g_type));
   3030   G_WRITE_UNLOCK (&type_rw_lock);
   3031 }
   3032 
   3033 /**
   3034  * g_type_name:
   3035  * @type: Type to return name for.
   3036  *
   3037  * Get the unique name that is assigned to a type ID.  Note that this
   3038  * function (like all other GType API) cannot cope with invalid type
   3039  * IDs. %G_TYPE_INVALID may be passed to this function, as may be any
   3040  * other validly registered type ID, but randomized type IDs should
   3041  * not be passed in and will most likely lead to a crash.
   3042  *
   3043  * Returns: Static type name or %NULL.
   3044  */
   3045 G_CONST_RETURN gchar*
   3046 g_type_name (GType type)
   3047 {
   3048   TypeNode *node;
   3049 
   3050   g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, NULL);
   3051 
   3052   node = lookup_type_node_I (type);
   3053 
   3054   return node ? NODE_NAME (node) : NULL;
   3055 }
   3056 
   3057 /**
   3058  * g_type_qname:
   3059  * @type: Type to return quark of type name for.
   3060  *
   3061  * Get the corresponding quark of the type IDs name.
   3062  *
   3063  * Returns: The type names quark or 0.
   3064  */
   3065 GQuark
   3066 g_type_qname (GType type)
   3067 {
   3068   TypeNode *node;
   3069 
   3070   node = lookup_type_node_I (type);
   3071 
   3072   return node ? node->qname : 0;
   3073 }
   3074 
   3075 /**
   3076  * g_type_from_name:
   3077  * @name: Type name to lookup.
   3078  *
   3079  * Lookup the type ID from a given type name, returning 0 if no type
   3080  * has been registered under this name (this is the preferred method
   3081  * to find out by name whether a specific type has been registered
   3082  * yet).
   3083  *
   3084  * Returns: Corresponding type ID or 0.
   3085  */
   3086 GType
   3087 g_type_from_name (const gchar *name)
   3088 {
   3089   GType type = 0;
   3090   GQuark quark;
   3091 
   3092   g_return_val_if_fail (name != NULL, 0);
   3093 
   3094   quark = g_quark_try_string (name);
   3095   if (quark)
   3096     {
   3097       G_READ_LOCK (&type_rw_lock);
   3098       type = (GType) g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark));
   3099       G_READ_UNLOCK (&type_rw_lock);
   3100     }
   3101 
   3102   return type;
   3103 }
   3104 
   3105 /**
   3106  * g_type_parent:
   3107  * @type: The derived type.
   3108  *
   3109  * Return the direct parent type of the passed in type.  If the passed
   3110  * in type has no parent, i.e. is a fundamental type, 0 is returned.
   3111  *
   3112  * Returns: The parent type.
   3113  */
   3114 GType
   3115 g_type_parent (GType type)
   3116 {
   3117   TypeNode *node;
   3118 
   3119   node = lookup_type_node_I (type);
   3120 
   3121   return node ? NODE_PARENT_TYPE (node) : 0;
   3122 }
   3123 
   3124 /**
   3125  * g_type_depth:
   3126  * @type: A #GType value.
   3127  *
   3128  * Returns the length of the ancestry of the passed in type. This
   3129  * includes the type itself, so that e.g. a fundamental type has depth 1.
   3130  *
   3131  * Returns: The depth of @type.
   3132  */
   3133 guint
   3134 g_type_depth (GType type)
   3135 {
   3136   TypeNode *node;
   3137 
   3138   node = lookup_type_node_I (type);
   3139 
   3140   return node ? node->n_supers + 1 : 0;
   3141 }
   3142 
   3143 /**
   3144  * g_type_next_base:
   3145  * @leaf_type: Descendant of @root_type and the type to be returned.
   3146  * @root_type: Immediate parent of the returned type.
   3147  *
   3148  * Given a @leaf_type and a @root_type which is contained in its
   3149  * anchestry, return the type that @root_type is the immediate parent
   3150  * of.  In other words, this function determines the type that is
   3151  * derived directly from @root_type which is also a base class of
   3152  * @leaf_type.  Given a root type and a leaf type, this function can
   3153  * be used to determine the types and order in which the leaf type is
   3154  * descended from the root type.
   3155  *
   3156  * Returns: Immediate child of @root_type and anchestor of @leaf_type.
   3157  */
   3158 GType
   3159 g_type_next_base (GType type,
   3160 		  GType base_type)
   3161 {
   3162   GType atype = 0;
   3163   TypeNode *node;
   3164 
   3165   node = lookup_type_node_I (type);
   3166   if (node)
   3167     {
   3168       TypeNode *base_node = lookup_type_node_I (base_type);
   3169 
   3170       if (base_node && base_node->n_supers < node->n_supers)
   3171 	{
   3172 	  guint n = node->n_supers - base_node->n_supers;
   3173 
   3174 	  if (node->supers[n] == base_type)
   3175 	    atype = node->supers[n - 1];
   3176 	}
   3177     }
   3178 
   3179   return atype;
   3180 }
   3181 
   3182 static inline gboolean
   3183 type_node_check_conformities_UorL (TypeNode *node,
   3184 				   TypeNode *iface_node,
   3185 				   /*        support_inheritance */
   3186 				   gboolean  support_interfaces,
   3187 				   gboolean  support_prerequisites,
   3188 				   gboolean  have_lock)
   3189 {
   3190   gboolean match;
   3191 
   3192   if (/* support_inheritance && */
   3193       NODE_IS_ANCESTOR (iface_node, node))
   3194     return TRUE;
   3195 
   3196   support_interfaces = support_interfaces && node->is_instantiatable && NODE_IS_IFACE (iface_node);
   3197   support_prerequisites = support_prerequisites && NODE_IS_IFACE (node);
   3198   match = FALSE;
   3199   if (support_interfaces || support_prerequisites)
   3200     {
   3201       if (!have_lock)
   3202 	G_READ_LOCK (&type_rw_lock);
   3203       if (support_interfaces && type_lookup_iface_entry_L (node, iface_node))
   3204 	match = TRUE;
   3205       else if (support_prerequisites && type_lookup_prerequisite_L (node, NODE_TYPE (iface_node)))
   3206 	match = TRUE;
   3207       if (!have_lock)
   3208 	G_READ_UNLOCK (&type_rw_lock);
   3209     }
   3210   return match;
   3211 }
   3212 
   3213 static gboolean
   3214 type_node_is_a_L (TypeNode *node,
   3215 		  TypeNode *iface_node)
   3216 {
   3217   return type_node_check_conformities_UorL (node, iface_node, TRUE, TRUE, TRUE);
   3218 }
   3219 
   3220 static inline gboolean
   3221 type_node_conforms_to_U (TypeNode *node,
   3222 			 TypeNode *iface_node,
   3223 			 gboolean  support_interfaces,
   3224 			 gboolean  support_prerequisites)
   3225 {
   3226   return type_node_check_conformities_UorL (node, iface_node, support_interfaces, support_prerequisites, FALSE);
   3227 }
   3228 
   3229 /**
   3230  * g_type_is_a:
   3231  * @type: Type to check anchestry for.
   3232  * @is_a_type: Possible anchestor of @type or interface @type could conform to.
   3233  *
   3234  * If @is_a_type is a derivable type, check whether @type is a
   3235  * descendant of @is_a_type.  If @is_a_type is an interface, check
   3236  * whether @type conforms to it.
   3237  *
   3238  * Returns: %TRUE if @type is_a @is_a_type holds true.
   3239  */
   3240 gboolean
   3241 g_type_is_a (GType type,
   3242 	     GType iface_type)
   3243 {
   3244   TypeNode *node, *iface_node;
   3245   gboolean is_a;
   3246 
   3247   node = lookup_type_node_I (type);
   3248   iface_node = lookup_type_node_I (iface_type);
   3249   is_a = node && iface_node && type_node_conforms_to_U (node, iface_node, TRUE, TRUE);
   3250 
   3251   return is_a;
   3252 }
   3253 
   3254 /**
   3255  * g_type_children:
   3256  * @type: The parent type.
   3257  * @n_children: Optional #guint pointer to contain the number of child types.
   3258  *
   3259  * Return a newly allocated and 0-terminated array of type IDs, listing the
   3260  * child types of @type. The return value has to be g_free()ed after use.
   3261  *
   3262  * Returns: Newly allocated and 0-terminated array of child types.
   3263  */
   3264 GType*
   3265 g_type_children (GType  type,
   3266 		 guint *n_children)
   3267 {
   3268   TypeNode *node;
   3269 
   3270   node = lookup_type_node_I (type);
   3271   if (node)
   3272     {
   3273       GType *children;
   3274 
   3275       G_READ_LOCK (&type_rw_lock);	/* ->children is relocatable */
   3276       children = g_new (GType, node->n_children + 1);
   3277       memcpy (children, node->children, sizeof (GType) * node->n_children);
   3278       children[node->n_children] = 0;
   3279 
   3280       if (n_children)
   3281 	*n_children = node->n_children;
   3282       G_READ_UNLOCK (&type_rw_lock);
   3283 
   3284       return children;
   3285     }
   3286   else
   3287     {
   3288       if (n_children)
   3289 	*n_children = 0;
   3290 
   3291       return NULL;
   3292     }
   3293 }
   3294 
   3295 /**
   3296  * g_type_interfaces:
   3297  * @type: The type to list interface types for.
   3298  * @n_interfaces: Optional #guint pointer to contain the number of
   3299  *                interface types.
   3300  *
   3301  * Return a newly allocated and 0-terminated array of type IDs, listing the
   3302  * interface types that @type conforms to. The return value has to be
   3303  * g_free()ed after use.
   3304  *
   3305  * Returns: Newly allocated and 0-terminated array of interface types.
   3306  */
   3307 GType*
   3308 g_type_interfaces (GType  type,
   3309 		   guint *n_interfaces)
   3310 {
   3311   TypeNode *node;
   3312 
   3313   node = lookup_type_node_I (type);
   3314   if (node && node->is_instantiatable)
   3315     {
   3316       GType *ifaces;
   3317       guint i;
   3318 
   3319       G_READ_LOCK (&type_rw_lock);
   3320       ifaces = g_new (GType, CLASSED_NODE_N_IFACES (node) + 1);
   3321       for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
   3322 	ifaces[i] = CLASSED_NODE_IFACES_ENTRIES (node)[i].iface_type;
   3323       ifaces[i] = 0;
   3324 
   3325       if (n_interfaces)
   3326 	*n_interfaces = CLASSED_NODE_N_IFACES (node);
   3327       G_READ_UNLOCK (&type_rw_lock);
   3328 
   3329       return ifaces;
   3330     }
   3331   else
   3332     {
   3333       if (n_interfaces)
   3334 	*n_interfaces = 0;
   3335 
   3336       return NULL;
   3337     }
   3338 }
   3339 
   3340 typedef struct _QData QData;
   3341 struct _GData
   3342 {
   3343   guint  n_qdatas;
   3344   QData *qdatas;
   3345 };
   3346 struct _QData
   3347 {
   3348   GQuark   quark;
   3349   gpointer data;
   3350 };
   3351 
   3352 static inline gpointer
   3353 type_get_qdata_L (TypeNode *node,
   3354 		  GQuark    quark)
   3355 {
   3356   GData *gdata = node->global_gdata;
   3357 
   3358   if (quark && gdata && gdata->n_qdatas)
   3359     {
   3360       QData *qdatas = gdata->qdatas - 1;
   3361       guint n_qdatas = gdata->n_qdatas;
   3362 
   3363       do
   3364 	{
   3365 	  guint i;
   3366 	  QData *check;
   3367 
   3368 	  i = (n_qdatas + 1) / 2;
   3369 	  check = qdatas + i;
   3370 	  if (quark == check->quark)
   3371 	    return check->data;
   3372 	  else if (quark > check->quark)
   3373 	    {
   3374 	      n_qdatas -= i;
   3375 	      qdatas = check;
   3376 	    }
   3377 	  else /* if (quark < check->quark) */
   3378 	    n_qdatas = i - 1;
   3379 	}
   3380       while (n_qdatas);
   3381     }
   3382   return NULL;
   3383 }
   3384 
   3385 /**
   3386  * g_type_get_qdata:
   3387  * @type: a #GType
   3388  * @quark: a #GQuark id to identify the data
   3389  *
   3390  * Obtains data which has previously been attached to @type
   3391  * with g_type_set_qdata().
   3392  *
   3393  * Returns: the data, or %NULL if no data was found
   3394  */
   3395 gpointer
   3396 g_type_get_qdata (GType  type,
   3397 		  GQuark quark)
   3398 {
   3399   TypeNode *node;
   3400   gpointer data;
   3401 
   3402   node = lookup_type_node_I (type);
   3403   if (node)
   3404     {
   3405       G_READ_LOCK (&type_rw_lock);
   3406       data = type_get_qdata_L (node, quark);
   3407       G_READ_UNLOCK (&type_rw_lock);
   3408     }
   3409   else
   3410     {
   3411       g_return_val_if_fail (node != NULL, NULL);
   3412       data = NULL;
   3413     }
   3414   return data;
   3415 }
   3416 
   3417 static inline void
   3418 type_set_qdata_W (TypeNode *node,
   3419 		  GQuark    quark,
   3420 		  gpointer  data)
   3421 {
   3422   GData *gdata;
   3423   QData *qdata;
   3424   guint i;
   3425 
   3426   /* setup qdata list if necessary */
   3427   if (!node->global_gdata)
   3428     node->global_gdata = g_new0 (GData, 1);
   3429   gdata = node->global_gdata;
   3430 
   3431   /* try resetting old data */
   3432   qdata = gdata->qdatas;
   3433   for (i = 0; i < gdata->n_qdatas; i++)
   3434     if (qdata[i].quark == quark)
   3435       {
   3436 	qdata[i].data = data;
   3437 	return;
   3438       }
   3439 
   3440   /* add new entry */
   3441   gdata->n_qdatas++;
   3442   gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
   3443   qdata = gdata->qdatas;
   3444   for (i = 0; i < gdata->n_qdatas - 1; i++)
   3445     if (qdata[i].quark > quark)
   3446       break;
   3447   g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
   3448   qdata[i].quark = quark;
   3449   qdata[i].data = data;
   3450 }
   3451 
   3452 /**
   3453  * g_type_set_qdata:
   3454  * @type: a #GType
   3455  * @quark: a #GQuark id to identify the data
   3456  * @data: the data
   3457  *
   3458  * Attaches arbitrary data to a type.
   3459  */
   3460 void
   3461 g_type_set_qdata (GType    type,
   3462 		  GQuark   quark,
   3463 		  gpointer data)
   3464 {
   3465   TypeNode *node;
   3466 
   3467   g_return_if_fail (quark != 0);
   3468 
   3469   node = lookup_type_node_I (type);
   3470   if (node)
   3471     {
   3472       G_WRITE_LOCK (&type_rw_lock);
   3473       type_set_qdata_W (node, quark, data);
   3474       G_WRITE_UNLOCK (&type_rw_lock);
   3475     }
   3476   else
   3477     g_return_if_fail (node != NULL);
   3478 }
   3479 
   3480 static void
   3481 type_add_flags_W (TypeNode  *node,
   3482 		  GTypeFlags flags)
   3483 {
   3484   guint dflags;
   3485 
   3486   g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
   3487   g_return_if_fail (node != NULL);
   3488 
   3489   if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class)
   3490     g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
   3491   dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
   3492   dflags |= flags;
   3493   type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
   3494 }
   3495 
   3496 /**
   3497  * g_type_query:
   3498  * @type: the #GType value of a static, classed type.
   3499  * @query: A user provided structure that is filled in with constant values
   3500  *  upon success.
   3501  *
   3502  * Queries the type system for information about a specific type.
   3503  * This function will fill in a user-provided structure to hold
   3504  * type-specific information. If an invalid #GType is passed in, the
   3505  * @type member of the #GTypeQuery is 0. All members filled into the
   3506  * #GTypeQuery structure should be considered constant and have to be
   3507  * left untouched.
   3508  */
   3509 void
   3510 g_type_query (GType       type,
   3511 	      GTypeQuery *query)
   3512 {
   3513   TypeNode *node;
   3514 
   3515   g_return_if_fail (query != NULL);
   3516 
   3517   /* if node is not static and classed, we won't allow query */
   3518   query->type = 0;
   3519   node = lookup_type_node_I (type);
   3520   if (node && node->is_classed && !node->plugin)
   3521     {
   3522       /* type is classed and probably even instantiatable */
   3523       G_READ_LOCK (&type_rw_lock);
   3524       if (node->data)	/* type is static or referenced */
   3525 	{
   3526 	  query->type = NODE_TYPE (node);
   3527 	  query->type_name = NODE_NAME (node);
   3528 	  query->class_size = node->data->class.class_size;
   3529 	  query->instance_size = node->is_instantiatable ? node->data->instance.instance_size : 0;
   3530 	}
   3531       G_READ_UNLOCK (&type_rw_lock);
   3532     }
   3533 }
   3534 
   3535 
   3536 /* --- implementation details --- */
   3537 gboolean
   3538 g_type_test_flags (GType type,
   3539 		   guint flags)
   3540 {
   3541   TypeNode *node;
   3542   gboolean result = FALSE;
   3543 
   3544   node = lookup_type_node_I (type);
   3545   if (node)
   3546     {
   3547       guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
   3548       guint tflags = flags & TYPE_FLAG_MASK;
   3549 
   3550       if (fflags)
   3551 	{
   3552 	  GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (node);
   3553 
   3554 	  fflags = (finfo->type_flags & fflags) == fflags;
   3555 	}
   3556       else
   3557 	fflags = TRUE;
   3558 
   3559       if (tflags)
   3560 	{
   3561 	  G_READ_LOCK (&type_rw_lock);
   3562 	  tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
   3563 	  G_READ_UNLOCK (&type_rw_lock);
   3564 	}
   3565       else
   3566 	tflags = TRUE;
   3567 
   3568       result = tflags && fflags;
   3569     }
   3570 
   3571   return result;
   3572 }
   3573 
   3574 /**
   3575  * g_type_get_plugin:
   3576  * @type: The #GType to retrieve the plugin for.
   3577  *
   3578  * Returns the #GTypePlugin structure for @type or
   3579  * %NULL if @type does not have a #GTypePlugin structure.
   3580  *
   3581  * Returns: The corresponding plugin if @type is a dynamic type,
   3582  *  %NULL otherwise.
   3583  */
   3584 GTypePlugin*
   3585 g_type_get_plugin (GType type)
   3586 {
   3587   TypeNode *node;
   3588 
   3589   node = lookup_type_node_I (type);
   3590 
   3591   return node ? node->plugin : NULL;
   3592 }
   3593 
   3594 /**
   3595  * g_type_interface_get_plugin:
   3596  * @instance_type: the #GType value of an instantiatable type.
   3597  * @interface_type: the #GType value of an interface type.
   3598  *
   3599  * Returns the #GTypePlugin structure for the dynamic interface
   3600  * @interface_type which has been added to @instance_type, or %NULL if
   3601  * @interface_type has not been added to @instance_type or does not
   3602  * have a #GTypePlugin structure. See g_type_add_interface_dynamic().
   3603  *
   3604  * Returns: the #GTypePlugin for the dynamic interface @interface_type
   3605  *  of @instance_type.
   3606  */
   3607 GTypePlugin*
   3608 g_type_interface_get_plugin (GType instance_type,
   3609 			     GType interface_type)
   3610 {
   3611   TypeNode *node;
   3612   TypeNode *iface;
   3613 
   3614   g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);	/* G_TYPE_IS_INTERFACE() is an external call: _U */
   3615 
   3616   node = lookup_type_node_I (instance_type);
   3617   iface = lookup_type_node_I (interface_type);
   3618   if (node && iface)
   3619     {
   3620       IFaceHolder *iholder;
   3621       GTypePlugin *plugin;
   3622 
   3623       G_READ_LOCK (&type_rw_lock);
   3624 
   3625       iholder = iface_node_get_holders_L (iface);
   3626       while (iholder && iholder->instance_type != instance_type)
   3627 	iholder = iholder->next;
   3628       plugin = iholder ? iholder->plugin : NULL;
   3629 
   3630       G_READ_UNLOCK (&type_rw_lock);
   3631 
   3632       return plugin;
   3633     }
   3634 
   3635   g_return_val_if_fail (node == NULL, NULL);
   3636   g_return_val_if_fail (iface == NULL, NULL);
   3637 
   3638   g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
   3639 
   3640   return NULL;
   3641 }
   3642 
   3643 /**
   3644  * g_type_fundamental_next:
   3645  *
   3646  * Returns the next free fundamental type id which can be used to
   3647  * register a new fundamental type with g_type_register_fundamental().
   3648  * The returned type ID represents the highest currently registered
   3649  * fundamental type identifier.
   3650  *
   3651  * Returns: The nextmost fundamental type ID to be registered,
   3652  *          or 0 if the type system ran out of fundamental type IDs.
   3653  */
   3654 GType
   3655 g_type_fundamental_next (void)
   3656 {
   3657   GType type;
   3658 
   3659   G_READ_LOCK (&type_rw_lock);
   3660   type = static_fundamental_next;
   3661   G_READ_UNLOCK (&type_rw_lock);
   3662   type = G_TYPE_MAKE_FUNDAMENTAL (type);
   3663   return type <= G_TYPE_FUNDAMENTAL_MAX ? type : 0;
   3664 }
   3665 
   3666 /**
   3667  * g_type_fundamental:
   3668  * @type_id: valid type ID
   3669  *
   3670  * Internal function, used to extract the fundamental type ID portion.
   3671  * use G_TYPE_FUNDAMENTAL() instead.
   3672  *
   3673  * Returns: fundamental type ID
   3674  */
   3675 GType
   3676 g_type_fundamental (GType type_id)
   3677 {
   3678   TypeNode *node = lookup_type_node_I (type_id);
   3679 
   3680   return node ? NODE_FUNDAMENTAL_TYPE (node) : 0;
   3681 }
   3682 
   3683 gboolean
   3684 g_type_check_instance_is_a (GTypeInstance *type_instance,
   3685 			    GType          iface_type)
   3686 {
   3687   TypeNode *node, *iface;
   3688   gboolean check;
   3689 
   3690   if (!type_instance || !type_instance->g_class)
   3691     return FALSE;
   3692 
   3693   node = lookup_type_node_I (type_instance->g_class->g_type);
   3694   iface = lookup_type_node_I (iface_type);
   3695   check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
   3696 
   3697   return check;
   3698 }
   3699 
   3700 gboolean
   3701 g_type_check_class_is_a (GTypeClass *type_class,
   3702 			 GType       is_a_type)
   3703 {
   3704   TypeNode *node, *iface;
   3705   gboolean check;
   3706 
   3707   if (!type_class)
   3708     return FALSE;
   3709 
   3710   node = lookup_type_node_I (type_class->g_type);
   3711   iface = lookup_type_node_I (is_a_type);
   3712   check = node && node->is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
   3713 
   3714   return check;
   3715 }
   3716 
   3717 GTypeInstance*
   3718 g_type_check_instance_cast (GTypeInstance *type_instance,
   3719 			    GType          iface_type)
   3720 {
   3721   if (type_instance)
   3722     {
   3723       if (type_instance->g_class)
   3724 	{
   3725 	  TypeNode *node, *iface;
   3726 	  gboolean is_instantiatable, check;
   3727 
   3728 	  node = lookup_type_node_I (type_instance->g_class->g_type);
   3729 	  is_instantiatable = node && node->is_instantiatable;
   3730 	  iface = lookup_type_node_I (iface_type);
   3731 	  check = is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
   3732 	  if (check)
   3733 	    return type_instance;
   3734 
   3735 	  if (is_instantiatable)
   3736 	    g_warning ("invalid cast from `%s' to `%s'",
   3737 		       type_descriptive_name_I (type_instance->g_class->g_type),
   3738 		       type_descriptive_name_I (iface_type));
   3739 	  else
   3740 	    g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
   3741 		       type_descriptive_name_I (type_instance->g_class->g_type),
   3742 		       type_descriptive_name_I (iface_type));
   3743 	}
   3744       else
   3745 	g_warning ("invalid unclassed pointer in cast to `%s'",
   3746 		   type_descriptive_name_I (iface_type));
   3747     }
   3748 
   3749   return type_instance;
   3750 }
   3751 
   3752 GTypeClass*
   3753 g_type_check_class_cast (GTypeClass *type_class,
   3754 			 GType       is_a_type)
   3755 {
   3756   if (type_class)
   3757     {
   3758       TypeNode *node, *iface;
   3759       gboolean is_classed, check;
   3760 
   3761       node = lookup_type_node_I (type_class->g_type);
   3762       is_classed = node && node->is_classed;
   3763       iface = lookup_type_node_I (is_a_type);
   3764       check = is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
   3765       if (check)
   3766 	return type_class;
   3767 
   3768       if (is_classed)
   3769 	g_warning ("invalid class cast from `%s' to `%s'",
   3770 		   type_descriptive_name_I (type_class->g_type),
   3771 		   type_descriptive_name_I (is_a_type));
   3772       else
   3773 	g_warning ("invalid unclassed type `%s' in class cast to `%s'",
   3774 		   type_descriptive_name_I (type_class->g_type),
   3775 		   type_descriptive_name_I (is_a_type));
   3776     }
   3777   else
   3778     g_warning ("invalid class cast from (NULL) pointer to `%s'",
   3779 	       type_descriptive_name_I (is_a_type));
   3780   return type_class;
   3781 }
   3782 
   3783 /**
   3784  * g_type_check_instance:
   3785  * @instance: A valid #GTypeInstance structure.
   3786  *
   3787  * Private helper function to aid implementation of the G_TYPE_CHECK_INSTANCE()
   3788  * macro.
   3789  *
   3790  * @Returns:  #TRUE if @instance is valid, #FALSE otherwise.
   3791  */
   3792 gboolean
   3793 g_type_check_instance (GTypeInstance *type_instance)
   3794 {
   3795   /* this function is just here to make the signal system
   3796    * conveniently elaborated on instance checks
   3797    */
   3798   if (type_instance)
   3799     {
   3800       if (type_instance->g_class)
   3801 	{
   3802 	  TypeNode *node = lookup_type_node_I (type_instance->g_class->g_type);
   3803 
   3804 	  if (node && node->is_instantiatable)
   3805 	    return TRUE;
   3806 
   3807 	  g_warning ("instance of invalid non-instantiatable type `%s'",
   3808 		     type_descriptive_name_I (type_instance->g_class->g_type));
   3809 	}
   3810       else
   3811 	g_warning ("instance with invalid (NULL) class pointer");
   3812     }
   3813   else
   3814     g_warning ("invalid (NULL) pointer instance");
   3815 
   3816   return FALSE;
   3817 }
   3818 
   3819 static inline gboolean
   3820 type_check_is_value_type_U (GType type)
   3821 {
   3822   GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT;
   3823   TypeNode *node;
   3824 
   3825   /* common path speed up */
   3826   node = lookup_type_node_I (type);
   3827   if (node && node->mutatable_check_cache)
   3828     return TRUE;
   3829 
   3830   G_READ_LOCK (&type_rw_lock);
   3831  restart_check:
   3832   if (node)
   3833     {
   3834       if (node->data && node->data->common.ref_count > 0 &&
   3835 	  node->data->common.value_table->value_init)
   3836 	tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
   3837       else if (NODE_IS_IFACE (node))
   3838 	{
   3839 	  guint i;
   3840 
   3841 	  for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
   3842 	    {
   3843 	      GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
   3844 	      TypeNode *prnode = lookup_type_node_I (prtype);
   3845 
   3846 	      if (prnode->is_instantiatable)
   3847 		{
   3848 		  type = prtype;
   3849 		  node = lookup_type_node_I (type);
   3850 		  goto restart_check;
   3851 		}
   3852 	    }
   3853 	}
   3854     }
   3855   G_READ_UNLOCK (&type_rw_lock);
   3856 
   3857   return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT);
   3858 }
   3859 
   3860 gboolean
   3861 g_type_check_is_value_type (GType type)
   3862 {
   3863   return type_check_is_value_type_U (type);
   3864 }
   3865 
   3866 gboolean
   3867 g_type_check_value (GValue *value)
   3868 {
   3869   return value && type_check_is_value_type_U (value->g_type);
   3870 }
   3871 
   3872 gboolean
   3873 g_type_check_value_holds (GValue *value,
   3874 			  GType   type)
   3875 {
   3876   return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type);
   3877 }
   3878 
   3879 /**
   3880  * g_type_value_table_peek:
   3881  * @type: A #GType value.
   3882  *
   3883  * Returns the location of the #GTypeValueTable associated with @type.
   3884  * <emphasis>Note that this function should only be used from source code
   3885  * that implements or has internal knowledge of the implementation of
   3886  * @type.</emphasis>
   3887  *
   3888  * Returns: Location of the #GTypeValueTable associated with @type or
   3889  *  %NULL if there is no #GTypeValueTable associated with @type.
   3890  */
   3891 GTypeValueTable*
   3892 g_type_value_table_peek (GType type)
   3893 {
   3894   GTypeValueTable *vtable = NULL;
   3895   TypeNode *node = lookup_type_node_I (type);
   3896   gboolean has_refed_data, has_table;
   3897   TypeData *data;
   3898 
   3899   /* speed up common code path, we're not 100% safe here,
   3900    * but we should only get called with referenced types anyway
   3901    */
   3902   data = node ? node->data : NULL;
   3903   if (node && node->mutatable_check_cache)
   3904     return data->common.value_table;
   3905 
   3906   G_READ_LOCK (&type_rw_lock);
   3907 
   3908  restart_table_peek:
   3909   has_refed_data = node && node->data && node->data->common.ref_count;
   3910   has_table = has_refed_data && node->data->common.value_table->value_init;
   3911   if (has_refed_data)
   3912     {
   3913       if (has_table)
   3914 	vtable = node->data->common.value_table;
   3915       else if (NODE_IS_IFACE (node))
   3916 	{
   3917 	  guint i;
   3918 
   3919 	  for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
   3920 	    {
   3921 	      GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
   3922 	      TypeNode *prnode = lookup_type_node_I (prtype);
   3923 
   3924 	      if (prnode->is_instantiatable)
   3925 		{
   3926 		  type = prtype;
   3927 		  node = lookup_type_node_I (type);
   3928 		  goto restart_table_peek;
   3929 		}
   3930 	    }
   3931 	}
   3932     }
   3933 
   3934   G_READ_UNLOCK (&type_rw_lock);
   3935 
   3936   if (vtable)
   3937     return vtable;
   3938 
   3939   if (!node)
   3940     g_warning (G_STRLOC ": type id `%" G_GSIZE_FORMAT "' is invalid", type);
   3941   if (!has_refed_data)
   3942     g_warning ("can't peek value table for type `%s' which is not currently referenced",
   3943 	       type_descriptive_name_I (type));
   3944 
   3945   return NULL;
   3946 }
   3947 
   3948 G_CONST_RETURN gchar*
   3949 g_type_name_from_instance (GTypeInstance *instance)
   3950 {
   3951   if (!instance)
   3952     return "<NULL-instance>";
   3953   else
   3954     return g_type_name_from_class (instance->g_class);
   3955 }
   3956 
   3957 G_CONST_RETURN gchar*
   3958 g_type_name_from_class (GTypeClass *g_class)
   3959 {
   3960   if (!g_class)
   3961     return "<NULL-class>";
   3962   else
   3963     return g_type_name (g_class->g_type);
   3964 }
   3965 
   3966 
   3967 /* --- initialization --- */
   3968 /**
   3969  * g_type_init_with_debug_flags:
   3970  * @debug_flags: Bitwise combination of #GTypeDebugFlags values for
   3971  *               debugging purposes.
   3972  *
   3973  * Similar to g_type_init(), but additionally sets debug flags.
   3974  */
   3975 void
   3976 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
   3977 {
   3978   G_LOCK_DEFINE_STATIC (type_init_lock);
   3979   const gchar *env_string;
   3980   GTypeInfo info;
   3981   TypeNode *node;
   3982   volatile GType votype;
   3983 
   3984   G_LOCK (type_init_lock);
   3985 
   3986   G_WRITE_LOCK (&type_rw_lock);
   3987 
   3988   if (static_quark_type_flags)
   3989     {
   3990       G_WRITE_UNLOCK (&type_rw_lock);
   3991       G_UNLOCK (type_init_lock);
   3992       return;
   3993     }
   3994 
   3995   /* setup GObject library wide debugging flags */
   3996   _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
   3997   env_string = g_getenv ("GOBJECT_DEBUG");
   3998   if (env_string != NULL)
   3999     {
   4000       static GDebugKey debug_keys[] = {
   4001 	{ "objects", G_TYPE_DEBUG_OBJECTS },
   4002 	{ "signals", G_TYPE_DEBUG_SIGNALS },
   4003       };
   4004 
   4005       _g_type_debug_flags |= g_parse_debug_string (env_string,
   4006 						   debug_keys,
   4007 						   sizeof (debug_keys) / sizeof (debug_keys[0]));
   4008       env_string = NULL;
   4009     }
   4010 
   4011   /* quarks */
   4012   static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
   4013   static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
   4014   static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
   4015 
   4016   /* type qname hash table */
   4017   static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
   4018 
   4019   /* invalid type G_TYPE_INVALID (0)
   4020    */
   4021   static_fundamental_type_nodes[0] = NULL;
   4022 
   4023   /* void type G_TYPE_NONE
   4024    */
   4025   node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0);
   4026   votype = NODE_TYPE (node);
   4027   g_assert (votype == G_TYPE_NONE);
   4028 
   4029   /* interface fundamental type G_TYPE_INTERFACE (!classed)
   4030    */
   4031   memset (&info, 0, sizeof (info));
   4032   node = type_node_fundamental_new_W (G_TYPE_INTERFACE, g_intern_static_string ("GInterface"), G_TYPE_FLAG_DERIVABLE);
   4033   votype = NODE_TYPE (node);
   4034   type_data_make_W (node, &info, NULL);
   4035   g_assert (votype == G_TYPE_INTERFACE);
   4036 
   4037   G_WRITE_UNLOCK (&type_rw_lock);
   4038 
   4039   g_value_c_init ();
   4040 
   4041   /* G_TYPE_TYPE_PLUGIN
   4042    */
   4043   votype = g_type_plugin_get_type ();
   4044 
   4045   /* G_TYPE_* value types
   4046    */
   4047   g_value_types_init ();
   4048 
   4049   /* G_TYPE_ENUM & G_TYPE_FLAGS
   4050    */
   4051   g_enum_types_init ();
   4052 
   4053   /* G_TYPE_BOXED
   4054    */
   4055   g_boxed_type_init ();
   4056 
   4057   /* G_TYPE_PARAM
   4058    */
   4059   g_param_type_init ();
   4060 
   4061   /* G_TYPE_OBJECT
   4062    */
   4063   g_object_type_init ();
   4064 
   4065   /* G_TYPE_PARAM_* pspec types
   4066    */
   4067   g_param_spec_types_init ();
   4068 
   4069   /* Value Transformations
   4070    */
   4071   g_value_transforms_init ();
   4072 
   4073   /* Signal system
   4074    */
   4075   g_signal_init ();
   4076 
   4077   G_UNLOCK (type_init_lock);
   4078 }
   4079 
   4080 /**
   4081  * g_type_init:
   4082  *
   4083  * Prior to any use of the type system, g_type_init() has to be called
   4084  * to initialize the type system and assorted other code portions
   4085  * (such as the various fundamental type implementations or the signal
   4086  * system).
   4087  */
   4088 void
   4089 g_type_init (void)
   4090 {
   4091   g_type_init_with_debug_flags (0);
   4092 }
   4093 
   4094 /**
   4095  * g_type_class_add_private:
   4096  * @g_class: class structure for an instantiatable type
   4097  * @private_size: size of private structure.
   4098  *
   4099  * Registers a private structure for an instantiatable type;
   4100  * when an object is allocated, the private structures for
   4101  * the type and all of its parent types are allocated
   4102  * sequentially in the same memory block as the public
   4103  * structures. This function should be called in the
   4104  * type's class_init() function. The private structure can
   4105  * be retrieved using the G_TYPE_INSTANCE_GET_PRIVATE() macro.
   4106  * The following example shows attaching a private structure
   4107  * <structname>MyObjectPrivate</structname> to an object
   4108  * <structname>MyObject</structname> defined in the standard GObject
   4109  * fashion.
   4110  *
   4111  * |[
   4112  * typedef struct _MyObjectPrivate MyObjectPrivate;
   4113  *
   4114  * struct _MyObjectPrivate {
   4115  *   int some_field;
   4116  * };
   4117  *
   4118  * #define MY_OBJECT_GET_PRIVATE(o)  \
   4119  *    (G_TYPE_INSTANCE_GET_PRIVATE ((o), MY_TYPE_OBJECT, MyObjectPrivate))
   4120  *
   4121  * static void
   4122  * my_object_class_init (MyObjectClass *klass)
   4123  * {
   4124  *   g_type_class_add_private (klass, sizeof (MyObjectPrivate));
   4125  * }
   4126  *
   4127  * static int
   4128  * my_object_get_some_field (MyObject *my_object)
   4129  * {
   4130  *   MyObjectPrivate *priv = MY_OBJECT_GET_PRIVATE (my_object);
   4131  *
   4132  *   return priv->some_field;
   4133  * }
   4134  * ]|
   4135  *
   4136  * Since: 2.4
   4137  */
   4138 void
   4139 g_type_class_add_private (gpointer g_class,
   4140 			  gsize    private_size)
   4141 {
   4142   GType instance_type = ((GTypeClass *)g_class)->g_type;
   4143   TypeNode *node = lookup_type_node_I (instance_type);
   4144   gsize offset;
   4145 
   4146   g_return_if_fail (private_size > 0);
   4147 
   4148   if (!node || !node->is_instantiatable || !node->data || node->data->class.class != g_class)
   4149     {
   4150       g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'",
   4151 		 type_descriptive_name_I (instance_type));
   4152       return;
   4153     }
   4154 
   4155   if (NODE_PARENT_TYPE (node))
   4156     {
   4157       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
   4158       if (node->data->instance.private_size != pnode->data->instance.private_size)
   4159 	{
   4160 	  g_warning ("g_type_add_private() called multiple times for the same type");
   4161 	  return;
   4162 	}
   4163     }
   4164 
   4165   G_WRITE_LOCK (&type_rw_lock);
   4166 
   4167   offset = ALIGN_STRUCT (node->data->instance.private_size);
   4168   node->data->instance.private_size = offset + private_size;
   4169 
   4170   G_WRITE_UNLOCK (&type_rw_lock);
   4171 }
   4172 
   4173 gpointer
   4174 g_type_instance_get_private (GTypeInstance *instance,
   4175 			     GType          private_type)
   4176 {
   4177   TypeNode *instance_node;
   4178   TypeNode *private_node;
   4179   TypeNode *parent_node;
   4180   GTypeClass *class;
   4181   gsize offset;
   4182 
   4183   g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
   4184 
   4185   /* while instances are initialized, their class pointers change,
   4186    * so figure the instances real class first
   4187    */
   4188   class = instance_real_class_get (instance);
   4189   if (!class)
   4190     class = instance->g_class;
   4191 
   4192   instance_node = lookup_type_node_I (class->g_type);
   4193   if (G_UNLIKELY (!instance_node || !instance_node->is_instantiatable))
   4194     {
   4195       g_warning ("instance of invalid non-instantiatable type `%s'",
   4196 		 type_descriptive_name_I (instance->g_class->g_type));
   4197       return NULL;
   4198     }
   4199 
   4200   private_node = lookup_type_node_I (private_type);
   4201   if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, instance_node)))
   4202     {
   4203       g_warning ("attempt to retrieve private data for invalid type '%s'",
   4204 		 type_descriptive_name_I (private_type));
   4205       return NULL;
   4206     }
   4207 
   4208   /* Note that we don't need a read lock, since instance existing
   4209    * means that the instance class and all parent classes
   4210    * exist, so the node->data, node->data->instance.instance_size,
   4211    * and node->data->instance.private_size are not going to be changed.
   4212    * for any of the relevant types.
   4213    */
   4214 
   4215   offset = ALIGN_STRUCT (instance_node->data->instance.instance_size);
   4216 
   4217   if (NODE_PARENT_TYPE (private_node))
   4218     {
   4219       parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
   4220       g_assert (parent_node->data && parent_node->data->common.ref_count);
   4221 
   4222       if (G_UNLIKELY (private_node->data->instance.private_size == parent_node->data->instance.private_size))
   4223 	{
   4224 	  g_warning ("g_type_instance_get_private() requires a prior call to g_type_class_add_private()");
   4225 	  return NULL;
   4226 	}
   4227 
   4228       offset += ALIGN_STRUCT (parent_node->data->instance.private_size);
   4229     }
   4230 
   4231   return G_STRUCT_MEMBER_P (instance, offset);
   4232 }
   4233 
   4234 #define __G_TYPE_C__
   4235 #include "gobjectaliasdef.c"
   4236