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