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 
2004   g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
2005 
2006   entry->init_state = IFACE_INIT;
2007 
2008   pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
2009   if (pnode)    /* want to copy over parent iface contents */
2010     {
2011       IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
2012 
2013       if (pentry)
2014     vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
2015     }
2016   if (!vtable)
2017     vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
2018   entry->vtable = vtable;
2019   vtable->g_type = NODE_TYPE (iface);
2020   vtable->g_instance_type = NODE_TYPE (node);
2021 
2022   if (iface->data->iface.vtable_init_base)
2023     {
2024       G_WRITE_UNLOCK (&type_rw_lock);
2025       iface->data->iface.vtable_init_base (vtable);
2026       G_WRITE_LOCK (&type_rw_lock);
2027     }
2028   return TRUE;  /* initialized the vtable */
2029 }
2030 
2031 /* Finishes what type_iface_vtable_base_init_Wm started by
2032  * calling the interface init function.
2033  * this function may only be called for types with their
2034  * own interface holder info, i.e. types for which
2035  * g_type_add_interface*() was called and not children thereof.
2036  */
2037 static void
2038 type_iface_vtable_iface_init_Wm (TypeNode *iface,
2039                  TypeNode *node)
2040 {
2041   IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
2042   IFaceHolder *iholder = type_iface_peek_holder_L (iface, NODE_TYPE (node));
2043   GTypeInterface *vtable = NULL;
2044   guint i;
2045 
2046   /* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */
2047   g_assert (iface->data && entry && iholder && iholder->info);
2048   g_assert (entry->init_state == IFACE_INIT); /* assert prior base_init() */
2049 
2050   entry->init_state = INITIALIZED;
2051 
2052   vtable = entry->vtable;
2053 
2054   if (iholder->info->interface_init)
2055     {
2056       G_WRITE_UNLOCK (&type_rw_lock);
2057       if (iholder->info->interface_init)
2058     iholder->info->interface_init (vtable, iholder->info->interface_data);
2059       G_WRITE_LOCK (&type_rw_lock);
2060     }
2061 
2062   for (i = 0; i < static_n_iface_check_funcs; i++)
2063     {
2064       GTypeInterfaceCheckFunc check_func = static_iface_check_funcs[i].check_func;
2065       gpointer check_data = static_iface_check_funcs[i].check_data;
2066 
2067       G_WRITE_UNLOCK (&type_rw_lock);
2068       check_func (check_data, (gpointer)vtable);
2069       G_WRITE_LOCK (&type_rw_lock);
2070     }
2071 }
2072 
2073 static gboolean
2074 type_iface_vtable_finalize_Wm (TypeNode       *iface,
2075                    TypeNode       *node,
2076                    GTypeInterface *vtable)
2077 {
2078   IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
2079   IFaceHolder *iholder;
2080 
2081   /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
2082   iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), FALSE);
2083   if (!iholder)
2084     return FALSE;   /* we don't modify write lock upon FALSE */
2085 
2086   g_assert (entry && entry->vtable == vtable && iholder->info);
2087 
2088   entry->vtable = NULL;
2089   entry->init_state = UNINITIALIZED;
2090   if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
2091     {
2092       G_WRITE_UNLOCK (&type_rw_lock);
2093       if (iholder->info->interface_finalize)
2094     iholder->info->interface_finalize (vtable, iholder->info->interface_data);
2095       if (iface->data->iface.vtable_finalize_base)
2096     iface->data->iface.vtable_finalize_base (vtable);
2097       G_WRITE_LOCK (&type_rw_lock);
2098     }
2099   vtable->g_type = 0;
2100   vtable->g_instance_type = 0;
2101   g_free (vtable);
2102 
2103   type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
2104 
2105   return TRUE;  /* write lock modified */
2106 }
2107 
2108 static void
2109 type_class_init_Wm (TypeNode   *node,
2110             GTypeClass *pclass)
2111 {
2112   GSList *slist, *init_slist = NULL;
2113   GTypeClass *class;
2114   IFaceEntries *entries;
2115   IFaceEntry *entry;
2116   TypeNode *bnode, *pnode;
2117   guint i;
2118 
2119   /* Accessing data->class will work for instantiable types
2120    * too because ClassData is a subset of InstanceData
2121    */
2122   g_assert (node->is_classed && node->data &&
2123         node->data->class.class_size &&
2124         !node->data->class.class &&
2125         node->data->class.init_state == UNINITIALIZED);
2126   if (node->data->class.class_private_size)
2127     class = g_malloc0 (ALIGN_STRUCT (node->data->class.class_size) + node->data->class.class_private_size);
2128   else
2129     class = g_malloc0 (node->data->class.class_size);
2130   node->data->class.class = class;
2131   g_atomic_int_set (&node->data->class.init_state, BASE_CLASS_INIT);
2132 
2133   if (pclass)
2134     {
2135       TypeNode *pnode = lookup_type_node_I (pclass->g_type);
2136 
2137       memcpy (class, pclass, pnode->data->class.class_size);
2138       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);
2139 
2140       if (node->is_instantiatable)
2141     {
2142       /* We need to initialize the private_size here rather than in
2143        * type_data_make_W() since the class init for the parent
2144        * class may have changed pnode->data->instance.private_size.
2145        */
2146       node->data->instance.private_size = pnode->data->instance.private_size;
2147     }
2148     }
2149   class->g_type = NODE_TYPE (node);
2150 
2151   G_WRITE_UNLOCK (&type_rw_lock);
2152 
2153   /* stack all base class initialization functions, so we
2154    * call them in ascending order.
2155    */
2156   for (bnode = node; bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
2157     if (bnode->data->class.class_init_base)
2158       init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
2159   for (slist = init_slist; slist; slist = slist->next)
2160     {
2161       GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
2162 
2163       class_init_base (class);
2164     }
2165   g_slist_free (init_slist);
2166 
2167   G_WRITE_LOCK (&type_rw_lock);
2168 
2169   g_atomic_int_set (&node->data->class.init_state, BASE_IFACE_INIT);
2170 
2171   /* Before we initialize the class, base initialize all interfaces, either
2172    * from parent, or through our holder info
2173    */
2174   pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
2175 
2176   i = 0;
2177   while ((entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node)) != NULL &&
2178       i < IFACE_ENTRIES_N_ENTRIES (entries))
2179     {
2180       entry = &entries->entry[i];
2181       while (i < IFACE_ENTRIES_N_ENTRIES (entries) &&
2182          entry->init_state == IFACE_INIT)
2183     {
2184       entry++;
2185       i++;
2186     }
2187 
2188       if (i == IFACE_ENTRIES_N_ENTRIES (entries))
2189     break;
2190 
2191       if (!type_iface_vtable_base_init_Wm (lookup_type_node_I (entry->iface_type), node))
2192     {
2193       guint j;
2194       IFaceEntries *pentries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (pnode);
2195 
2196       /* need to get this interface from parent, type_iface_vtable_base_init_Wm()
2197        * doesn't modify write lock upon FALSE, so entry is still valid;
2198        */
2199       g_assert (pnode != NULL);
2200 
2201       if (pentries)
2202         for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (pentries); j++)
2203           {
2204         IFaceEntry *pentry = &pentries->entry[j];
2205 
2206         if (pentry->iface_type == entry->iface_type)
2207           {
2208             entry->vtable = pentry->vtable;
2209             entry->init_state = INITIALIZED;
2210             break;
2211           }
2212           }
2213       g_assert (entry->vtable != NULL);
2214     }
2215 
2216       /* If the write lock was released, additional interface entries might
2217        * have been inserted into CLASSED_NODE_IFACES_ENTRIES (node); they'll
2218        * be base-initialized when inserted, so we don't have to worry that
2219        * we might miss them. Uninitialized entries can only be moved higher
2220        * when new ones are inserted.
2221        */
2222       i++;
2223     }
2224 
2225   g_atomic_int_set (&node->data->class.init_state, CLASS_INIT);
2226 
2227   G_WRITE_UNLOCK (&type_rw_lock);
2228 
2229   if (node->data->class.class_init)
2230     node->data->class.class_init (class, (gpointer) node->data->class.class_data);
2231 
2232   G_WRITE_LOCK (&type_rw_lock);
2233 
2234   g_atomic_int_set (&node->data->class.init_state, IFACE_INIT);
2235 
2236   /* finish initializing the interfaces through our holder info.
2237    * inherited interfaces are already init_state == INITIALIZED, because
2238    * they either got setup in the above base_init loop, or during
2239    * class_init from within type_add_interface_Wm() for this or
2240    * an anchestor type.
2241    */
2242   i = 0;
2243   while ((entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node)) != NULL)
2244     {
2245       entry = &entries->entry[i];
2246       while (i < IFACE_ENTRIES_N_ENTRIES (entries) &&
2247          entry->init_state == INITIALIZED)
2248     {
2249       entry++;
2250       i++;
2251     }
2252 
2253       if (i == IFACE_ENTRIES_N_ENTRIES (entries))
2254     break;
2255 
2256       type_iface_vtable_iface_init_Wm (lookup_type_node_I (entry->iface_type), node);
2257 
2258       /* As in the loop above, additional initialized entries might be inserted
2259        * if the write lock is released, but that's harmless because the entries
2260        * we need to initialize only move higher in the list.
2261        */
2262       i++;
2263     }
2264 
2265   g_atomic_int_set (&node->data->class.init_state, INITIALIZED);
2266 }
2267 
2268 static void
2269 type_data_finalize_class_ifaces_Wm (TypeNode *node)
2270 {
2271   guint i;
2272   IFaceEntries *entries;
2273 
2274   g_assert (node->is_instantiatable && node->data && node->data->class.class && NODE_REFCOUNT (node) == 0);
2275 
2276  reiterate:
2277   entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node);
2278   for (i = 0; entries != NULL && i < IFACE_ENTRIES_N_ENTRIES (entries); i++)
2279     {
2280       IFaceEntry *entry = &entries->entry[i];
2281       if (entry->vtable)
2282     {
2283           if (type_iface_vtable_finalize_Wm (lookup_type_node_I (entry->iface_type), node, entry->vtable))
2284             {
2285               /* refetch entries, IFACES_ENTRIES might be modified */
2286               goto reiterate;
2287             }
2288           else
2289             {
2290               /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
2291                * iface vtable came from parent
2292                */
2293               entry->vtable = NULL;
2294               entry->init_state = UNINITIALIZED;
2295             }
2296     }
2297     }
2298 }
2299 
2300 static void
2301 type_data_finalize_class_U (TypeNode  *node,
2302                 ClassData *cdata)
2303 {
2304   GTypeClass *class = cdata->class;
2305   TypeNode *bnode;
2306 
2307   g_assert (cdata->class && NODE_REFCOUNT (node) == 0);
2308 
2309   if (cdata->class_finalize)
2310     cdata->class_finalize (class, (gpointer) cdata->class_data);
2311 
2312   /* call all base class destruction functions in descending order
2313    */
2314   if (cdata->class_finalize_base)
2315     cdata->class_finalize_base (class);
2316   for (bnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
2317     if (bnode->data->class.class_finalize_base)
2318       bnode->data->class.class_finalize_base (class);
2319 
2320   g_free (cdata->class);
2321 }
2322 
2323 static void
2324 type_data_last_unref_Wm (TypeNode *node,
2325              gboolean  uncached)
2326 {
2327   g_return_if_fail (node != NULL && node->plugin != NULL);
2328 
2329   if (!node->data || NODE_REFCOUNT (node) == 0)
2330     {
2331       g_warning ("cannot drop last reference to unreferenced type '%s'",
2332          NODE_NAME (node));
2333       return;
2334     }
2335 
2336   /* call class cache hooks */
2337   if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs && !uncached)
2338     {
2339       guint i;
2340 
2341       G_WRITE_UNLOCK (&type_rw_lock);
2342       G_READ_LOCK (&type_rw_lock);
2343       for (i = 0; i < static_n_class_cache_funcs; i++)
2344     {
2345       GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func;
2346       gpointer cache_data = static_class_cache_funcs[i].cache_data;
2347       gboolean need_break;
2348 
2349       G_READ_UNLOCK (&type_rw_lock);
2350       need_break = cache_func (cache_data, node->data->class.class);
2351       G_READ_LOCK (&type_rw_lock);
2352       if (!node->data || NODE_REFCOUNT (node) == 0)
2353         INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
2354       if (need_break)
2355         break;
2356     }
2357       G_READ_UNLOCK (&type_rw_lock);
2358       G_WRITE_LOCK (&type_rw_lock);
2359     }
2360 
2361   /* may have been re-referenced meanwhile */
2362   if (g_atomic_int_dec_and_test ((int *) &node->ref_count))
2363     {
2364       GType ptype = NODE_PARENT_TYPE (node);
2365       TypeData *tdata;
2366 
2367       if (node->is_instantiatable)
2368     {
2369       /* destroy node->data->instance.mem_chunk */
2370     }
2371 
2372       tdata = node->data;
2373       if (node->is_classed && tdata->class.class)
2374     {
2375       if (CLASSED_NODE_IFACES_ENTRIES_LOCKED (node) != NULL)
2376         type_data_finalize_class_ifaces_Wm (node);
2377       node->mutatable_check_cache = FALSE;
2378       node->data = NULL;
2379       G_WRITE_UNLOCK (&type_rw_lock);
2380       type_data_finalize_class_U (node, &tdata->class);
2381       G_WRITE_LOCK (&type_rw_lock);
2382     }
2383       else if (NODE_IS_IFACE (node) && tdata->iface.dflt_vtable)
2384         {
2385           node->mutatable_check_cache = FALSE;
2386           node->data = NULL;
2387           if (tdata->iface.dflt_finalize || tdata->iface.vtable_finalize_base)
2388             {
2389               G_WRITE_UNLOCK (&type_rw_lock);
2390               if (tdata->iface.dflt_finalize)
2391                 tdata->iface.dflt_finalize (tdata->iface.dflt_vtable, (gpointer) tdata->iface.dflt_data);
2392               if (tdata->iface.vtable_finalize_base)
2393                 tdata->iface.vtable_finalize_base (tdata->iface.dflt_vtable);
2394               G_WRITE_LOCK (&type_rw_lock);
2395             }
2396           g_free (tdata->iface.dflt_vtable);
2397         }
2398       else
2399         {
2400           node->mutatable_check_cache = FALSE;
2401           node->data = NULL;
2402         }
2403 
2404       /* freeing tdata->common.value_table and its contents is taken care of
2405        * by allocating it in one chunk with tdata
2406        */
2407       g_free (tdata);
2408 
2409       G_WRITE_UNLOCK (&type_rw_lock);
2410       g_type_plugin_unuse (node->plugin);
2411       if (ptype)
2412     type_data_unref_U (lookup_type_node_I (ptype), FALSE);
2413       G_WRITE_LOCK (&type_rw_lock);
2414     }
2415 }
2416 
2417 static inline void
2418 type_data_unref_U (TypeNode *node,
2419                    gboolean  uncached)
2420 {
2421   guint current;
2422 
2423   do {
2424     current = NODE_REFCOUNT (node);
2425 
2426     if (current <= 1)
2427     {
2428       if (!node->plugin)
2429     {
2430       g_warning ("static type '%s' unreferenced too often",
2431              NODE_NAME (node));
2432       return;
2433     }
2434       else
2435         {
2436           /* This is the last reference of a type from a plugin.  We are
2437            * experimentally disabling support for unloading type
2438            * plugins, so don't allow the last ref to drop.
2439            */
2440           return;
2441         }
2442 
2443       g_assert (current > 0);
2444 
2445       g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2446       G_WRITE_LOCK (&type_rw_lock);
2447       type_data_last_unref_Wm (node, uncached);
2448       G_WRITE_UNLOCK (&type_rw_lock);
2449       g_rec_mutex_unlock (&class_init_rec_mutex);
2450       return;
2451     }
2452   } while (!g_atomic_int_compare_and_exchange ((int *) &node->ref_count, current, current - 1));
2453 }
2454 
2455 /**
2456  * g_type_add_class_cache_func: (skip)
2457  * @cache_data: data to be passed to @cache_func
2458  * @cache_func: a #GTypeClassCacheFunc
2459  *
2460  * Adds a #GTypeClassCacheFunc to be called before the reference count of a
2461  * class goes from one to zero. This can be used to prevent premature class
2462  * destruction. All installed #GTypeClassCacheFunc functions will be chained
2463  * until one of them returns %TRUE. The functions have to check the class id
2464  * passed in to figure whether they actually want to cache the class of this
2465  * type, since all classes are routed through the same #GTypeClassCacheFunc
2466  * chain.
2467  */
2468 void
2469 g_type_add_class_cache_func (gpointer            cache_data,
2470                  GTypeClassCacheFunc cache_func)
2471 {
2472   guint i;
2473 
2474   g_return_if_fail (cache_func != NULL);
2475 
2476   G_WRITE_LOCK (&type_rw_lock);
2477   i = static_n_class_cache_funcs++;
2478   static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
2479   static_class_cache_funcs[i].cache_data = cache_data;
2480   static_class_cache_funcs[i].cache_func = cache_func;
2481   G_WRITE_UNLOCK (&type_rw_lock);
2482 }
2483 
2484 /**
2485  * g_type_remove_class_cache_func: (skip)
2486  * @cache_data: data that was given when adding @cache_func
2487  * @cache_func: a #GTypeClassCacheFunc
2488  *
2489  * Removes a previously installed #GTypeClassCacheFunc. The cache
2490  * maintained by @cache_func has to be empty when calling
2491  * g_type_remove_class_cache_func() to avoid leaks.
2492  */
2493 void
2494 g_type_remove_class_cache_func (gpointer            cache_data,
2495                 GTypeClassCacheFunc cache_func)
2496 {
2497   gboolean found_it = FALSE;
2498   guint i;
2499 
2500   g_return_if_fail (cache_func != NULL);
2501 
2502   G_WRITE_LOCK (&type_rw_lock);
2503   for (i = 0; i < static_n_class_cache_funcs; i++)
2504     if (static_class_cache_funcs[i].cache_data == cache_data &&
2505     static_class_cache_funcs[i].cache_func == cache_func)
2506       {
2507     static_n_class_cache_funcs--;
2508     memmove (static_class_cache_funcs + i,
2509                  static_class_cache_funcs + i + 1,
2510                  sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
2511     static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
2512     found_it = TRUE;
2513     break;
2514       }
2515   G_WRITE_UNLOCK (&type_rw_lock);
2516 
2517   if (!found_it)
2518     g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
2519            cache_func, cache_data);
2520 }
2521 
2522 
2523 /**
2524  * g_type_add_interface_check: (skip)
2525  * @check_data: data to pass to @check_func
2526  * @check_func: function to be called after each interface
2527  *     is initialized
2528  *
2529  * Adds a function to be called after an interface vtable is
2530  * initialized for any class (i.e. after the @interface_init
2531  * member of #GInterfaceInfo has been called).
2532  *
2533  * This function is useful when you want to check an invariant
2534  * that depends on the interfaces of a class. For instance, the
2535  * implementation of #GObject uses this facility to check that an
2536  * object implements all of the properties that are defined on its
2537  * interfaces.
2538  *
2539  * Since: 2.4
2540  */
2541 void
2542 g_type_add_interface_check (gpointer                check_data,
2543                 GTypeInterfaceCheckFunc check_func)
2544 {
2545   guint i;
2546 
2547   g_return_if_fail (check_func != NULL);
2548 
2549   G_WRITE_LOCK (&type_rw_lock);
2550   i = static_n_iface_check_funcs++;
2551   static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
2552   static_iface_check_funcs[i].check_data = check_data;
2553   static_iface_check_funcs[i].check_func = check_func;
2554   G_WRITE_UNLOCK (&type_rw_lock);
2555 }
2556 
2557 /**
2558  * g_type_remove_interface_check: (skip)
2559  * @check_data: callback data passed to g_type_add_interface_check()
2560  * @check_func: callback function passed to g_type_add_interface_check()
2561  *
2562  * Removes an interface check function added with
2563  * g_type_add_interface_check().
2564  *
2565  * Since: 2.4
2566  */
2567 void
2568 g_type_remove_interface_check (gpointer                check_data,
2569                    GTypeInterfaceCheckFunc check_func)
2570 {
2571   gboolean found_it = FALSE;
2572   guint i;
2573 
2574   g_return_if_fail (check_func != NULL);
2575 
2576   G_WRITE_LOCK (&type_rw_lock);
2577   for (i = 0; i < static_n_iface_check_funcs; i++)
2578     if (static_iface_check_funcs[i].check_data == check_data &&
2579     static_iface_check_funcs[i].check_func == check_func)
2580       {
2581     static_n_iface_check_funcs--;
2582     memmove (static_iface_check_funcs + i,
2583                  static_iface_check_funcs + i + 1,
2584                  sizeof (static_iface_check_funcs[0]) * (static_n_iface_check_funcs - i));
2585     static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
2586     found_it = TRUE;
2587     break;
2588       }
2589   G_WRITE_UNLOCK (&type_rw_lock);
2590 
2591   if (!found_it)
2592     g_warning (G_STRLOC ": cannot remove unregistered class check func %p with data %p",
2593            check_func, check_data);
2594 }
2595 
2596 /* --- type registration --- */
2597 /**
2598  * g_type_register_fundamental:
2599  * @type_id: a predefined type identifier
2600  * @type_name: 0-terminated string used as the name of the new type
2601  * @info: #GTypeInfo structure for this type
2602  * @finfo: #GTypeFundamentalInfo structure for this type
2603  * @flags: bitwise combination of #GTypeFlags values
2604  *
2605  * Registers @type_id as the predefined identifier and @type_name as the
2606  * name of a fundamental type. If @type_id is already registered, or a
2607  * type named @type_name is already registered, the behaviour is undefined.
2608  * The type system uses the information contained in the #GTypeInfo structure
2609  * pointed to by @info and the #GTypeFundamentalInfo structure pointed to by
2610  * @finfo to manage the type and its instances. The value of @flags determines
2611  * additional characteristics of the fundamental type.
2612  *
2613  * Returns: the predefined type identifier
2614  */
2615 GType
2616 g_type_register_fundamental (GType                       type_id,
2617                  const gchar                *type_name,
2618                  const GTypeInfo            *info,
2619                  const GTypeFundamentalInfo *finfo,
2620                  GTypeFlags          flags)
2621 {
2622   TypeNode *node;
2623 
2624   g_assert_type_system_initialized ();
2625   g_return_val_if_fail (type_id > 0, 0);
2626   g_return_val_if_fail (type_name != NULL, 0);
2627   g_return_val_if_fail (info != NULL, 0);
2628   g_return_val_if_fail (finfo != NULL, 0);
2629 
2630   if (!check_type_name_I (type_name))
2631     return 0;
2632   if ((type_id & TYPE_ID_MASK) ||
2633       type_id > G_TYPE_FUNDAMENTAL_MAX)
2634     {
2635       g_warning ("attempt to register fundamental type '%s' with invalid type id (%" G_GSIZE_FORMAT ")",
2636          type_name,
2637          type_id);
2638       return 0;
2639     }
2640   if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
2641       !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
2642     {
2643       g_warning ("cannot register instantiatable fundamental type '%s' as non-classed",
2644          type_name);
2645       return 0;
2646     }
2647   if (lookup_type_node_I (type_id))
2648     {
2649       g_warning ("cannot register existing fundamental type '%s' (as '%s')",
2650          type_descriptive_name_I (type_id),
2651          type_name);
2652       return 0;
2653     }
2654 
2655   G_WRITE_LOCK (&type_rw_lock);
2656   node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
2657   type_add_flags_W (node, flags);
2658 
2659   if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info))
2660     type_data_make_W (node, info,
2661               check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
2662   G_WRITE_UNLOCK (&type_rw_lock);
2663 
2664   return NODE_TYPE (node);
2665 }
2666 
2667 /**
2668  * g_type_register_static_simple: (skip)
2669  * @parent_type: type from which this type will be derived
2670  * @type_name: 0-terminated string used as the name of the new type
2671  * @class_size: size of the class structure (see #GTypeInfo)
2672  * @class_init: location of the class initialization function (see #GTypeInfo)
2673  * @instance_size: size of the instance structure (see #GTypeInfo)
2674  * @instance_init: location of the instance initialization function (see #GTypeInfo)
2675  * @flags: bitwise combination of #GTypeFlags values
2676  *
2677  * Registers @type_name as the name of a new static type derived from
2678  * @parent_type.  The value of @flags determines the nature (e.g.
2679  * abstract or not) of the type. It works by filling a #GTypeInfo
2680  * struct and calling g_type_register_static().
2681  *
2682  * Since: 2.12
2683  *
2684  * Returns: the new type identifier
2685  */
2686 GType
2687 g_type_register_static_simple (GType             parent_type,
2688                    const gchar      *type_name,
2689                    guint             class_size,
2690                    GClassInitFunc    class_init,
2691                    guint             instance_size,
2692                    GInstanceInitFunc instance_init,
2693                    GTypeFlags    flags)
2694 {
2695   GTypeInfo info;
2696 
2697   /* Instances are not allowed to be larger than this. If you have a big
2698    * fixed-length array or something, point to it instead.
2699    */
2700   g_return_val_if_fail (class_size <= G_MAXUINT16, G_TYPE_INVALID);
2701   g_return_val_if_fail (instance_size <= G_MAXUINT16, G_TYPE_INVALID);
2702 
2703   info.class_size = class_size;
2704   info.base_init = NULL;
2705   info.base_finalize = NULL;
2706   info.class_init = class_init;
2707   info.class_finalize = NULL;
2708   info.class_data = NULL;
2709   info.instance_size = instance_size;
2710   info.n_preallocs = 0;
2711   info.instance_init = instance_init;
2712   info.value_table = NULL;
2713 
2714   return g_type_register_static (parent_type, type_name, &info, flags);
2715 }
2716 
2717 /**
2718  * g_type_register_static:
2719  * @parent_type: type from which this type will be derived
2720  * @type_name: 0-terminated string used as the name of the new type
2721  * @info: #GTypeInfo structure for this type
2722  * @flags: bitwise combination of #GTypeFlags values
2723  *
2724  * Registers @type_name as the name of a new static type derived from
2725  * @parent_type. The type system uses the information contained in the
2726  * #GTypeInfo structure pointed to by @info to manage the type and its
2727  * instances (if not abstract). The value of @flags determines the nature
2728  * (e.g. abstract or not) of the type.
2729  *
2730  * Returns: the new type identifier
2731  */
2732 GType
2733 g_type_register_static (GType            parent_type,
2734             const gchar     *type_name,
2735             const GTypeInfo *info,
2736             GTypeFlags   flags)
2737 {
2738   TypeNode *pnode, *node;
2739   GType type = 0;
2740 
2741   g_assert_type_system_initialized ();
2742   g_return_val_if_fail (parent_type > 0, 0);
2743   g_return_val_if_fail (type_name != NULL, 0);
2744   g_return_val_if_fail (info != NULL, 0);
2745 
2746   if (!check_type_name_I (type_name) ||
2747       !check_derivation_I (parent_type, type_name))
2748     return 0;
2749   if (info->class_finalize)
2750     {
2751       g_warning ("class finalizer specified for static type '%s'",
2752          type_name);
2753       return 0;
2754     }
2755 
2756   pnode = lookup_type_node_I (parent_type);
2757   G_WRITE_LOCK (&type_rw_lock);
2758   type_data_ref_Wm (pnode);
2759   if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info))
2760     {
2761       node = type_node_new_W (pnode, type_name, NULL);
2762       type_add_flags_W (node, flags);
2763       type = NODE_TYPE (node);
2764       type_data_make_W (node, info,
2765             check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
2766     }
2767   G_WRITE_UNLOCK (&type_rw_lock);
2768 
2769   return type;
2770 }
2771 
2772 /**
2773  * g_type_register_dynamic:
2774  * @parent_type: type from which this type will be derived
2775  * @type_name: 0-terminated string used as the name of the new type
2776  * @plugin: #GTypePlugin structure to retrieve the #GTypeInfo from
2777  * @flags: bitwise combination of #GTypeFlags values
2778  *
2779  * Registers @type_name as the name of a new dynamic type derived from
2780  * @parent_type.  The type system uses the information contained in the
2781  * #GTypePlugin structure pointed to by @plugin to manage the type and its
2782  * instances (if not abstract).  The value of @flags determines the nature
2783  * (e.g. abstract or not) of the type.
2784  *
2785  * Returns: the new type identifier or #G_TYPE_INVALID if registration failed
2786  */
2787 GType
2788 g_type_register_dynamic (GType        parent_type,
2789              const gchar *type_name,
2790              GTypePlugin *plugin,
2791              GTypeFlags   flags)
2792 {
2793   TypeNode *pnode, *node;
2794   GType type;
2795 
2796   g_assert_type_system_initialized ();
2797   g_return_val_if_fail (parent_type > 0, 0);
2798   g_return_val_if_fail (type_name != NULL, 0);
2799   g_return_val_if_fail (plugin != NULL, 0);
2800 
2801   if (!check_type_name_I (type_name) ||
2802       !check_derivation_I (parent_type, type_name) ||
2803       !check_plugin_U (plugin, TRUE, FALSE, type_name))
2804     return 0;
2805 
2806   G_WRITE_LOCK (&type_rw_lock);
2807   pnode = lookup_type_node_I (parent_type);
2808   node = type_node_new_W (pnode, type_name, plugin);
2809   type_add_flags_W (node, flags);
2810   type = NODE_TYPE (node);
2811   G_WRITE_UNLOCK (&type_rw_lock);
2812 
2813   return type;
2814 }
2815 
2816 /**
2817  * g_type_add_interface_static:
2818  * @instance_type: #GType value of an instantiable type
2819  * @interface_type: #GType value of an interface type
2820  * @info: #GInterfaceInfo structure for this
2821  *        (@instance_type, @interface_type) combination
2822  *
2823  * Adds the static @interface_type to @instantiable_type.
2824  * The information contained in the #GInterfaceInfo structure
2825  * pointed to by @info is used to manage the relationship.
2826  */
2827 void
2828 g_type_add_interface_static (GType                 instance_type,
2829                  GType                 interface_type,
2830                  const GInterfaceInfo *info)
2831 {
2832   /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2833   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2834   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2835 
2836   /* we only need to lock class_init_rec_mutex if instance_type already has its
2837    * class initialized, however this function is rarely enough called to take
2838    * the simple route and always acquire class_init_rec_mutex.
2839    */
2840   g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2841   G_WRITE_LOCK (&type_rw_lock);
2842   if (check_add_interface_L (instance_type, interface_type))
2843     {
2844       TypeNode *node = lookup_type_node_I (instance_type);
2845       TypeNode *iface = lookup_type_node_I (interface_type);
2846       if (check_interface_info_I (iface, NODE_TYPE (node), info))
2847         type_add_interface_Wm (node, iface, info, NULL);
2848     }
2849   G_WRITE_UNLOCK (&type_rw_lock);
2850   g_rec_mutex_unlock (&class_init_rec_mutex);
2851 }
2852 
2853 /**
2854  * g_type_add_interface_dynamic:
2855  * @instance_type: #GType value of an instantiable type
2856  * @interface_type: #GType value of an interface type
2857  * @plugin: #GTypePlugin structure to retrieve the #GInterfaceInfo from
2858  *
2859  * Adds the dynamic @interface_type to @instantiable_type. The information
2860  * contained in the #GTypePlugin structure pointed to by @plugin
2861  * is used to manage the relationship.
2862  */
2863 void
2864 g_type_add_interface_dynamic (GType        instance_type,
2865                   GType        interface_type,
2866                   GTypePlugin *plugin)
2867 {
2868   TypeNode *node;
2869   /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2870   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2871   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2872 
2873   node = lookup_type_node_I (instance_type);
2874   if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
2875     return;
2876 
2877   /* see comment in g_type_add_interface_static() about class_init_rec_mutex */
2878   g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2879   G_WRITE_LOCK (&type_rw_lock);
2880   if (check_add_interface_L (instance_type, interface_type))
2881     {
2882       TypeNode *iface = lookup_type_node_I (interface_type);
2883       type_add_interface_Wm (node, iface, NULL, plugin);
2884     }
2885   G_WRITE_UNLOCK (&type_rw_lock);
2886   g_rec_mutex_unlock (&class_init_rec_mutex);
2887 }
2888 
2889 
2890 /* --- public API functions --- */
2891 /**
2892  * g_type_class_ref:
2893  * @type: type ID of a classed type
2894  *
2895  * Increments the reference count of the class structure belonging to
2896  * @type. This function will demand-create the class if it doesn't
2897  * exist already.
2898  *
2899  * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
2900  *     structure for the given type ID
2901  */
2902 gpointer
2903 g_type_class_ref (GType type)
2904 {
2905   TypeNode *node;
2906   GType ptype;
2907   gboolean holds_ref;
2908   GTypeClass *pclass;
2909 
2910   /* optimize for common code path */
2911   node = lookup_type_node_I (type);
2912   if (!node || !node->is_classed)
2913     {
2914       g_warning ("cannot retrieve class for invalid (unclassed) type '%s'",
2915          type_descriptive_name_I (type));
2916       return NULL;
2917     }
2918 
2919   if (G_LIKELY (type_data_ref_U (node)))
2920     {
2921       if (G_LIKELY (g_atomic_int_get (&node->data->class.init_state) == INITIALIZED))
2922         return node->data->class.class;
2923       holds_ref = TRUE;
2924     }
2925   else
2926     holds_ref = FALSE;
2927 
2928   /* here, we either have node->data->class.class == NULL, or a recursive
2929    * call to g_type_class_ref() with a partly initialized class, or
2930    * node->data->class.init_state == INITIALIZED, because any
2931    * concurrently running initialization was guarded by class_init_rec_mutex.
2932    */
2933   g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2934 
2935   /* we need an initialized parent class for initializing derived classes */
2936   ptype = NODE_PARENT_TYPE (node);
2937   pclass = ptype ? g_type_class_ref (ptype) : NULL;
2938 
2939   G_WRITE_LOCK (&type_rw_lock);
2940 
2941   if (!holds_ref)
2942     type_data_ref_Wm (node);
2943 
2944   if (!node->data->class.class) /* class uninitialized */
2945     type_class_init_Wm (node, pclass);
2946 
2947   G_WRITE_UNLOCK (&type_rw_lock);
2948 
2949   if (pclass)
2950     g_type_class_unref (pclass);
2951 
2952   g_rec_mutex_unlock (&class_init_rec_mutex);
2953 
2954   return node->data->class.class;
2955 }
2956 
2957 /**
2958  * g_type_class_unref:
2959  * @g_class: (type GObject.TypeClass): a #GTypeClass structure to unref
2960  *
2961  * Decrements the reference count of the class structure being passed in.
2962  * Once the last reference count of a class has been released, classes
2963  * may be finalized by the type system, so further dereferencing of a
2964  * class pointer after g_type_class_unref() are invalid.
2965  */
2966 void
2967 g_type_class_unref (gpointer g_class)
2968 {
2969   TypeNode *node;
2970   GTypeClass *class = g_class;
2971 
2972   g_return_if_fail (g_class != NULL);
2973 
2974   node = lookup_type_node_I (class->g_type);
2975   if (node && node->is_classed && NODE_REFCOUNT (node))
2976     type_data_unref_U (node, FALSE);
2977   else
2978     g_warning ("cannot unreference class of invalid (unclassed) type '%s'",
2979            type_descriptive_name_I (class->g_type));
2980 }
2981 
2982 /**
2983  * g_type_class_unref_uncached: (skip)
2984  * @g_class: (type GObject.TypeClass): a #GTypeClass structure to unref
2985  *
2986  * A variant of g_type_class_unref() for use in #GTypeClassCacheFunc
2987  * implementations. It unreferences a class without consulting the chain
2988  * of #GTypeClassCacheFuncs, avoiding the recursion which would occur
2989  * otherwise.
2990  */
2991 void
2992 g_type_class_unref_uncached (gpointer g_class)
2993 {
2994   TypeNode *node;
2995   GTypeClass *class = g_class;
2996 
2997   g_return_if_fail (g_class != NULL);
2998 
2999   node = lookup_type_node_I (class->g_type);
3000   if (node && node->is_classed && NODE_REFCOUNT (node))
3001     type_data_unref_U (node, TRUE);
3002   else
3003     g_warning ("cannot unreference class of invalid (unclassed) type '%s'",
3004            type_descriptive_name_I (class->g_type));
3005 }
3006 
3007 /**
3008  * g_type_class_peek:
3009  * @type: type ID of a classed type
3010  *
3011  * This function is essentially the same as g_type_class_ref(),
3012  * except that the classes reference count isn't incremented.
3013  * As a consequence, this function may return %NULL if the class
3014  * of the type passed in does not currently exist (hasn't been
3015  * referenced before).
3016  *
3017  * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
3018  *     structure for the given type ID or %NULL if the class does not
3019  *     currently exist
3020  */
3021 gpointer
3022 g_type_class_peek (GType type)
3023 {
3024   TypeNode *node;
3025   gpointer class;
3026 
3027   node = lookup_type_node_I (type);
3028   if (node && node->is_classed && NODE_REFCOUNT (node) &&
3029       g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
3030     /* ref_count _may_ be 0 */
3031     class = node->data->class.class;
3032   else
3033     class = NULL;
3034 
3035   return class;
3036 }
3037 
3038 /**
3039  * g_type_class_peek_static:
3040  * @type: type ID of a classed type
3041  *
3042  * A more efficient version of g_type_class_peek() which works only for
3043  * static types.
3044  *
3045  * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
3046  *     structure for the given type ID or %NULL if the class does not
3047  *     currently exist or is dynamically loaded
3048  *
3049  * Since: 2.4
3050  */
3051 gpointer
3052 g_type_class_peek_static (GType type)
3053 {
3054   TypeNode *node;
3055   gpointer class;
3056 
3057   node = lookup_type_node_I (type);
3058   if (node && node->is_classed && NODE_REFCOUNT (node) &&
3059       /* peek only static types: */ node->plugin == NULL &&
3060       g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
3061     /* ref_count _may_ be 0 */
3062     class = node->data->class.class;
3063   else
3064     class = NULL;
3065 
3066   return class;
3067 }
3068 
3069 /**
3070  * g_type_class_peek_parent:
3071  * @g_class: (type GObject.TypeClass): the #GTypeClass structure to
3072  *     retrieve the parent class for
3073  *
3074  * This is a convenience function often needed in class initializers.
3075  * It returns the class structure of the immediate parent type of the
3076  * class passed in.  Since derived classes hold a reference count on
3077  * their parent classes as long as they are instantiated, the returned
3078  * class will always exist.
3079  *
3080  * This function is essentially equivalent to:
3081  * g_type_class_peek (g_type_parent (G_TYPE_FROM_CLASS (g_class)))
3082  *
3083  * Returns: (type GObject.TypeClass) (transfer none): the parent class
3084  *     of @g_class
3085  */
3086 gpointer
3087 g_type_class_peek_parent (gpointer g_class)
3088 {
3089   TypeNode *node;
3090   gpointer class = NULL;
3091 
3092   g_return_val_if_fail (g_class != NULL, NULL);
3093 
3094   node = lookup_type_node_I (G_TYPE_FROM_CLASS (g_class));
3095   /* We used to acquire a read lock here. That is not necessary, since
3096    * parent->data->class.class is constant as long as the derived class
3097    * exists.
3098    */
3099   if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
3100     {
3101       node = lookup_type_node_I (NODE_PARENT_TYPE (node));
3102       class = node->data->class.class;
3103     }
3104   else if (NODE_PARENT_TYPE (node))
3105     g_warning (G_STRLOC ": invalid class pointer '%p'", g_class);
3106 
3107   return class;
3108 }
3109 
3110 /**
3111  * g_type_interface_peek:
3112  * @instance_class: (type GObject.TypeClass): a #GTypeClass structure
3113  * @iface_type: an interface ID which this class conforms to
3114  *
3115  * Returns the #GTypeInterface structure of an interface to which the
3116  * passed in class conforms.
3117  *
3118  * Returns: (type GObject.TypeInterface) (transfer none): the #GTypeInterface
3119  *     structure of @iface_type if implemented by @instance_class, %NULL
3120  *     otherwise
3121  */
3122 gpointer
3123 g_type_interface_peek (gpointer instance_class,
3124                GType    iface_type)
3125 {
3126   TypeNode *node;
3127   TypeNode *iface;
3128   gpointer vtable = NULL;
3129   GTypeClass *class = instance_class;
3130 
3131   g_return_val_if_fail (instance_class != NULL, NULL);
3132 
3133   node = lookup_type_node_I (class->g_type);
3134   iface = lookup_type_node_I (iface_type);
3135   if (node && node->is_instantiatable && iface)
3136     type_lookup_iface_vtable_I (node, iface, &vtable);
3137   else
3138     g_warning (G_STRLOC ": invalid class pointer '%p'", class);
3139 
3140   return vtable;
3141 }
3142 
3143 /**
3144  * g_type_interface_peek_parent:
3145  * @g_iface: (type GObject.TypeInterface): a #GTypeInterface structure
3146  *
3147  * Returns the corresponding #GTypeInterface structure of the parent type
3148  * of the instance type to which @g_iface belongs. This is useful when
3149  * deriving the implementation of an interface from the parent type and
3150  * then possibly overriding some methods.
3151  *
3152  * Returns: (transfer none) (type GObject.TypeInterface): the
3153  *     corresponding #GTypeInterface structure of the parent type of the
3154  *     instance type to which @g_iface belongs, or %NULL if the parent
3155  *     type doesn't conform to the interface
3156  */
3157 gpointer
3158 g_type_interface_peek_parent (gpointer g_iface)
3159 {
3160   TypeNode *node;
3161   TypeNode *iface;
3162   gpointer vtable = NULL;
3163   GTypeInterface *iface_class = g_iface;
3164 
3165   g_return_val_if_fail (g_iface != NULL, NULL);
3166 
3167   iface = lookup_type_node_I (iface_class->g_type);
3168   node = lookup_type_node_I (iface_class->g_instance_type);
3169   if (node)
3170     node = lookup_type_node_I (NODE_PARENT_TYPE (node));
3171   if (node && node->is_instantiatable && iface)
3172     type_lookup_iface_vtable_I (node, iface, &vtable);
3173   else if (node)
3174     g_warning (G_STRLOC ": invalid interface pointer '%p'", g_iface);
3175 
3176   return vtable;
3177 }
3178 
3179 /**
3180  * g_type_default_interface_ref:
3181  * @g_type: an interface type
3182  *
3183  * Increments the reference count for the interface type @g_type,
3184  * and returns the default interface vtable for the type.
3185  *
3186  * If the type is not currently in use, then the default vtable
3187  * for the type will be created and initalized by calling
3188  * the base interface init and default vtable init functions for
3189  * the type (the @base_init and @class_init members of #GTypeInfo).
3190  * Calling g_type_default_interface_ref() is useful when you
3191  * want to make sure that signals and properties for an interface
3192  * have been installed.
3193  *
3194  * Since: 2.4
3195  *
3196  * Returns: (type GObject.TypeInterface) (transfer none): the default
3197  *     vtable for the interface; call g_type_default_interface_unref()
3198  *     when you are done using the interface.
3199  */
3200 gpointer
3201 g_type_default_interface_ref (GType g_type)
3202 {
3203   TypeNode *node;
3204   gpointer dflt_vtable;
3205 
3206   G_WRITE_LOCK (&type_rw_lock);
3207 
3208   node = lookup_type_node_I (g_type);
3209   if (!node || !NODE_IS_IFACE (node) ||
3210       (node->data && NODE_REFCOUNT (node) == 0))
3211     {
3212       G_WRITE_UNLOCK (&type_rw_lock);
3213       g_warning ("cannot retrieve default vtable for invalid or non-interface type '%s'",
3214          type_descriptive_name_I (g_type));
3215       return NULL;
3216     }
3217 
3218   if (!node->data || !node->data->iface.dflt_vtable)
3219     {
3220       G_WRITE_UNLOCK (&type_rw_lock);
3221       g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
3222       G_WRITE_LOCK (&type_rw_lock);
3223       node = lookup_type_node_I (g_type);
3224       type_data_ref_Wm (node);
3225       type_iface_ensure_dflt_vtable_Wm (node);
3226       g_rec_mutex_unlock (&class_init_rec_mutex);
3227     }
3228   else
3229     type_data_ref_Wm (node); /* ref_count >= 1 already */
3230 
3231   dflt_vtable = node->data->iface.dflt_vtable;
3232   G_WRITE_UNLOCK (&type_rw_lock);
3233 
3234   return dflt_vtable;
3235 }
3236 
3237 /**
3238  * g_type_default_interface_peek:
3239  * @g_type: an interface type
3240  *
3241  * If the interface type @g_type is currently in use, returns its
3242  * default interface vtable.
3243  *
3244  * Since: 2.4
3245  *
3246  * Returns: (type GObject.TypeInterface) (transfer none): the default
3247  *     vtable for the interface, or %NULL if the type is not currently
3248  *     in use
3249  */
3250 gpointer
3251 g_type_default_interface_peek (GType g_type)
3252 {
3253   TypeNode *node;
3254   gpointer vtable;
3255 
3256   node = lookup_type_node_I (g_type);
3257   if (node && NODE_IS_IFACE (node) && NODE_REFCOUNT (node))
3258     vtable = node->data->iface.dflt_vtable;
3259   else
3260     vtable = NULL;
3261 
3262   return vtable;
3263 }
3264 
3265 /**
3266  * g_type_default_interface_unref:
3267  * @g_iface: (type GObject.TypeInterface): the default vtable
3268  *     structure for a interface, as returned by g_type_default_interface_ref()
3269  *
3270  * Decrements the reference count for the type corresponding to the
3271  * interface default vtable @g_iface. If the type is dynamic, then
3272  * when no one is using the interface and all references have
3273  * been released, the finalize function for the interface's default
3274  * vtable (the @class_finalize member of #GTypeInfo) will be called.
3275  *
3276  * Since: 2.4
3277  */
3278 void
3279 g_type_default_interface_unref (gpointer g_iface)
3280 {
3281   TypeNode *node;
3282   GTypeInterface *vtable = g_iface;
3283 
3284   g_return_if_fail (g_iface != NULL);
3285 
3286   node = lookup_type_node_I (vtable->g_type);
3287   if (node && NODE_IS_IFACE (node))
3288     type_data_unref_U (node, FALSE);
3289   else
3290     g_warning ("cannot unreference invalid interface default vtable for '%s'",
3291            type_descriptive_name_I (vtable->g_type));
3292 }
3293 
3294 /**
3295  * g_type_name:
3296  * @type: type to return name for
3297  *
3298  * Get the unique name that is assigned to a type ID.  Note that this
3299  * function (like all other GType API) cannot cope with invalid type
3300  * IDs. %G_TYPE_INVALID may be passed to this function, as may be any
3301  * other validly registered type ID, but randomized type IDs should
3302  * not be passed in and will most likely lead to a crash.
3303  *
3304  * Returns: static type name or %NULL
3305  */
3306 const gchar *
3307 g_type_name (GType type)
3308 {
3309   TypeNode *node;
3310 
3311   g_assert_type_system_initialized ();
3312 
3313   node = lookup_type_node_I (type);
3314 
3315   return node ? NODE_NAME (node) : NULL;
3316 }
3317 
3318 /**
3319  * g_type_qname:
3320  * @type: type to return quark of type name for
3321  *
3322  * Get the corresponding quark of the type IDs name.
3323  *
3324  * Returns: the type names quark or 0
3325  */
3326 GQuark
3327 g_type_qname (GType type)
3328 {
3329   TypeNode *node;
3330 
3331   node = lookup_type_node_I (type);
3332 
3333   return node ? node->qname : 0;
3334 }
3335 
3336 /**
3337  * g_type_from_name:
3338  * @name: type name to lookup
3339  *
3340  * Lookup the type ID from a given type name, returning 0 if no type
3341  * has been registered under this name (this is the preferred method
3342  * to find out by name whether a specific type has been registered
3343  * yet).
3344  *
3345  * Returns: corresponding type ID or 0
3346  */
3347 GType
3348 g_type_from_name (const gchar *name)
3349 {
3350   GType type = 0;
3351 
3352   g_return_val_if_fail (name != NULL, 0);
3353 
3354   G_READ_LOCK (&type_rw_lock);
3355   type = (GType) g_hash_table_lookup (static_type_nodes_ht, name);
3356   G_READ_UNLOCK (&type_rw_lock);
3357 
3358   return type;
3359 }
3360 
3361 /**
3362  * g_type_parent:
3363  * @type: the derived type
3364  *
3365  * Return the direct parent type of the passed in type. If the passed
3366  * in type has no parent, i.e. is a fundamental type, 0 is returned.
3367  *
3368  * Returns: the parent type
3369  */
3370 GType
3371 g_type_parent (GType type)
3372 {
3373   TypeNode *node;
3374 
3375   node = lookup_type_node_I (type);
3376 
3377   return node ? NODE_PARENT_TYPE (node) : 0;
3378 }
3379 
3380 /**
3381  * g_type_depth:
3382  * @type: a #GType
3383  *
3384  * Returns the length of the ancestry of the passed in type. This
3385  * includes the type itself, so that e.g. a fundamental type has depth 1.
3386  *
3387  * Returns: the depth of @type
3388  */
3389 guint
3390 g_type_depth (GType type)
3391 {
3392   TypeNode *node;
3393 
3394   node = lookup_type_node_I (type);
3395 
3396   return node ? node->n_supers + 1 : 0;
3397 }
3398 
3399 /**
3400  * g_type_next_base:
3401  * @leaf_type: descendant of @root_type and the type to be returned
3402  * @root_type: immediate parent of the returned type
3403  *
3404  * Given a @leaf_type and a @root_type which is contained in its
3405  * anchestry, return the type that @root_type is the immediate parent
3406  * of. In other words, this function determines the type that is
3407  * derived directly from @root_type which is also a base class of
3408  * @leaf_type.  Given a root type and a leaf type, this function can
3409  * be used to determine the types and order in which the leaf type is
3410  * descended from the root type.
3411  *
3412  * Returns: immediate child of @root_type and anchestor of @leaf_type
3413  */
3414 GType
3415 g_type_next_base (GType type,
3416           GType base_type)
3417 {
3418   GType atype = 0;
3419   TypeNode *node;
3420 
3421   node = lookup_type_node_I (type);
3422   if (node)
3423     {
3424       TypeNode *base_node = lookup_type_node_I (base_type);
3425 
3426       if (base_node && base_node->n_supers < node->n_supers)
3427     {
3428       guint n = node->n_supers - base_node->n_supers;
3429 
3430       if (node->supers[n] == base_type)
3431         atype = node->supers[n - 1];
3432     }
3433     }
3434 
3435   return atype;
3436 }
3437 
3438 static inline gboolean
3439 type_node_check_conformities_UorL (TypeNode *node,
3440                    TypeNode *iface_node,
3441                    /*        support_inheritance */
3442                    gboolean  support_interfaces,
3443                    gboolean  support_prerequisites,
3444                    gboolean  have_lock)
3445 {
3446   gboolean match;
3447 
3448   if (/* support_inheritance && */
3449       NODE_IS_ANCESTOR (iface_node, node))
3450     return TRUE;
3451 
3452   support_interfaces = support_interfaces && node->is_instantiatable && NODE_IS_IFACE (iface_node);
3453   support_prerequisites = support_prerequisites && NODE_IS_IFACE (node);
3454   match = FALSE;
3455   if (support_interfaces)
3456     {
3457       if (have_lock)
3458     {
3459       if (type_lookup_iface_entry_L (node, iface_node))
3460         match = TRUE;
3461     }
3462       else
3463     {
3464       if (type_lookup_iface_vtable_I (node, iface_node, NULL))
3465         match = TRUE;
3466     }
3467     }
3468   if (!match &&
3469       support_prerequisites)
3470     {
3471       if (!have_lock)
3472     G_READ_LOCK (&type_rw_lock);
3473       if (support_prerequisites && type_lookup_prerequisite_L (node, NODE_TYPE (iface_node)))
3474     match = TRUE;
3475       if (!have_lock)
3476     G_READ_UNLOCK (&type_rw_lock);
3477     }
3478   return match;
3479 }
3480 
3481 static gboolean
3482 type_node_is_a_L (TypeNode *node,
3483           TypeNode *iface_node)
3484 {
3485   return type_node_check_conformities_UorL (node, iface_node, TRUE, TRUE, TRUE);
3486 }
3487 
3488 static inline gboolean
3489 type_node_conforms_to_U (TypeNode *node,
3490              TypeNode *iface_node,
3491              gboolean  support_interfaces,
3492              gboolean  support_prerequisites)
3493 {
3494   return type_node_check_conformities_UorL (node, iface_node, support_interfaces, support_prerequisites, FALSE);
3495 }
3496 
3497 /**
3498  * g_type_is_a:
3499  * @type: type to check anchestry for
3500  * @is_a_type: possible anchestor of @type or interface that @type
3501  *     could conform to
3502  *
3503  * If @is_a_type is a derivable type, check whether @type is a
3504  * descendant of @is_a_type. If @is_a_type is an interface, check
3505  * whether @type conforms to it.
3506  *
3507  * Returns: %TRUE if @type is a @is_a_type
3508  */
3509 gboolean
3510 g_type_is_a (GType type,
3511          GType iface_type)
3512 {
3513   TypeNode *node, *iface_node;
3514   gboolean is_a;
3515 
3516   if (type == iface_type)
3517     return TRUE;
3518 
3519   node = lookup_type_node_I (type);
3520   iface_node = lookup_type_node_I (iface_type);
3521   is_a = node && iface_node && type_node_conforms_to_U (node, iface_node, TRUE, TRUE);
3522 
3523   return is_a;
3524 }
3525 
3526 /**
3527  * g_type_children:
3528  * @type: the parent type
3529  * @n_children: (out) (allow-none): location to store the length of
3530  *     the returned array, or %NULL
3531  *
3532  * Return a newly allocated and 0-terminated array of type IDs, listing
3533  * the child types of @type.
3534  *
3535  * Returns: (array length=n_children) (transfer full): Newly allocated
3536  *     and 0-terminated array of child types, free with g_free()
3537  */
3538 GType*
3539 g_type_children (GType  type,
3540          guint *n_children)
3541 {
3542   TypeNode *node;
3543 
3544   node = lookup_type_node_I (type);
3545   if (node)
3546     {
3547       GType *children;
3548 
3549       G_READ_LOCK (&type_rw_lock);  /* ->children is relocatable */
3550       children = g_new (GType, node->n_children + 1);
3551       memcpy (children, node->children, sizeof (GType) * node->n_children);
3552       children[node->n_children] = 0;
3553 
3554       if (n_children)
3555     *n_children = node->n_children;
3556       G_READ_UNLOCK (&type_rw_lock);
3557 
3558       return children;
3559     }
3560   else
3561     {
3562       if (n_children)
3563     *n_children = 0;
3564 
3565       return NULL;
3566     }
3567 }
3568 
3569 /**
3570  * g_type_interfaces:
3571  * @type: the type to list interface types for
3572  * @n_interfaces: (out) (allow-none): location to store the length of
3573  *     the returned array, or %NULL
3574  *
3575  * Return a newly allocated and 0-terminated array of type IDs, listing
3576  * the interface types that @type conforms to.
3577  *
3578  * Returns: (array length=n_interfaces) (transfer full): Newly allocated
3579  *     and 0-terminated array of interface types, free with g_free()
3580  */
3581 GType*
3582 g_type_interfaces (GType  type,
3583            guint *n_interfaces)
3584 {
3585   TypeNode *node;
3586 
3587   node = lookup_type_node_I (type);
3588   if (node && node->is_instantiatable)
3589     {
3590       IFaceEntries *entries;
3591       GType *ifaces;
3592       guint i;
3593 
3594       G_READ_LOCK (&type_rw_lock);
3595       entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node);
3596       if (entries)
3597     {
3598       ifaces = g_new (GType, IFACE_ENTRIES_N_ENTRIES (entries) + 1);
3599       for (i = 0; i < IFACE_ENTRIES_N_ENTRIES (entries); i++)
3600         ifaces[i] = entries->entry[i].iface_type;
3601     }
3602       else
3603     {
3604       ifaces = g_new (GType, 1);
3605       i = 0;
3606     }
3607       ifaces[i] = 0;
3608 
3609       if (n_interfaces)
3610     *n_interfaces = i;
3611       G_READ_UNLOCK (&type_rw_lock);
3612 
3613       return ifaces;
3614     }
3615   else
3616     {
3617       if (n_interfaces)
3618     *n_interfaces = 0;
3619 
3620       return NULL;
3621     }
3622 }
3623 
3624 typedef struct _QData QData;
3625 struct _GData
3626 {
3627   guint  n_qdatas;
3628   QData *qdatas;
3629 };
3630 struct _QData
3631 {
3632   GQuark   quark;
3633   gpointer data;
3634 };
3635 
3636 static inline gpointer
3637 type_get_qdata_L (TypeNode *node,
3638           GQuark    quark)
3639 {
3640   GData *gdata = node->global_gdata;
3641 
3642   if (quark && gdata && gdata->n_qdatas)
3643     {
3644       QData *qdatas = gdata->qdatas - 1;
3645       guint n_qdatas = gdata->n_qdatas;
3646 
3647       do
3648     {
3649       guint i;
3650       QData *check;
3651 
3652       i = (n_qdatas + 1) / 2;
3653       check = qdatas + i;
3654       if (quark == check->quark)
3655         return check->data;
3656       else if (quark > check->quark)
3657         {
3658           n_qdatas -= i;
3659           qdatas = check;
3660         }
3661       else /* if (quark < check->quark) */
3662         n_qdatas = i - 1;
3663     }
3664       while (n_qdatas);
3665     }
3666   return NULL;
3667 }
3668 
3669 /**
3670  * g_type_get_qdata:
3671  * @type: a #GType
3672  * @quark: a #GQuark id to identify the data
3673  *
3674  * Obtains data which has previously been attached to @type
3675  * with g_type_set_qdata().
3676  *
3677  * Note that this does not take subtyping into account; data
3678  * attached to one type with g_type_set_qdata() cannot
3679  * be retrieved from a subtype using g_type_get_qdata().
3680  *
3681  * Returns: (transfer none): the data, or %NULL if no data was found
3682  */
3683 gpointer
3684 g_type_get_qdata (GType  type,
3685           GQuark quark)
3686 {
3687   TypeNode *node;
3688   gpointer data;
3689 
3690   node = lookup_type_node_I (type);
3691   if (node)
3692     {
3693       G_READ_LOCK (&type_rw_lock);
3694       data = type_get_qdata_L (node, quark);
3695       G_READ_UNLOCK (&type_rw_lock);
3696     }
3697   else
3698     {
3699       g_return_val_if_fail (node != NULL, NULL);
3700       data = NULL;
3701     }
3702   return data;
3703 }
3704 
3705 static inline void
3706 type_set_qdata_W (TypeNode *node,
3707           GQuark    quark,
3708           gpointer  data)
3709 {
3710   GData *gdata;
3711   QData *qdata;
3712   guint i;
3713 
3714   /* setup qdata list if necessary */
3715   if (!node->global_gdata)
3716     node->global_gdata = g_new0 (GData, 1);
3717   gdata = node->global_gdata;
3718 
3719   /* try resetting old data */
3720   qdata = gdata->qdatas;
3721   for (i = 0; i < gdata->n_qdatas; i++)
3722     if (qdata[i].quark == quark)
3723       {
3724     qdata[i].data = data;
3725     return;
3726       }
3727 
3728   /* add new entry */
3729   gdata->n_qdatas++;
3730   gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
3731   qdata = gdata->qdatas;
3732   for (i = 0; i < gdata->n_qdatas - 1; i++)
3733     if (qdata[i].quark > quark)
3734       break;
3735   memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
3736   qdata[i].quark = quark;
3737   qdata[i].data = data;
3738 }
3739 
3740 /**
3741  * g_type_set_qdata:
3742  * @type: a #GType
3743  * @quark: a #GQuark id to identify the data
3744  * @data: the data
3745  *
3746  * Attaches arbitrary data to a type.
3747  */
3748 void
3749 g_type_set_qdata (GType    type,
3750           GQuark   quark,
3751           gpointer data)
3752 {
3753   TypeNode *node;
3754 
3755   g_return_if_fail (quark != 0);
3756 
3757   node = lookup_type_node_I (type);
3758   if (node)
3759     {
3760       G_WRITE_LOCK (&type_rw_lock);
3761       type_set_qdata_W (node, quark, data);
3762       G_WRITE_UNLOCK (&type_rw_lock);
3763     }
3764   else
3765     g_return_if_fail (node != NULL);
3766 }
3767 
3768 static void
3769 type_add_flags_W (TypeNode  *node,
3770           GTypeFlags flags)
3771 {
3772   guint dflags;
3773 
3774   g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
3775   g_return_if_fail (node != NULL);
3776 
3777   if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class)
3778     g_warning ("tagging type '%s' as abstract after class initialization", NODE_NAME (node));
3779   dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
3780   dflags |= flags;
3781   type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
3782 }
3783 
3784 /**
3785  * g_type_query:
3786  * @type: #GType of a static, classed type
3787  * @query: (out caller-allocates): a user provided structure that is
3788  *     filled in with constant values upon success
3789  *
3790  * Queries the type system for information about a specific type.
3791  * This function will fill in a user-provided structure to hold
3792  * type-specific information. If an invalid #GType is passed in, the
3793  * @type member of the #GTypeQuery is 0. All members filled into the
3794  * #GTypeQuery structure should be considered constant and have to be
3795  * left untouched.
3796  */
3797 void
3798 g_type_query (GType       type,
3799           GTypeQuery *query)
3800 {
3801   TypeNode *node;
3802 
3803   g_return_if_fail (query != NULL);
3804 
3805   /* if node is not static and classed, we won't allow query */
3806   query->type = 0;
3807   node = lookup_type_node_I (type);
3808   if (node && node->is_classed && !node->plugin)
3809     {
3810       /* type is classed and probably even instantiatable */
3811       G_READ_LOCK (&type_rw_lock);
3812       if (node->data)   /* type is static or referenced */
3813     {
3814       query->type = NODE_TYPE (node);
3815       query->type_name = NODE_NAME (node);
3816       query->class_size = node->data->class.class_size;
3817       query->instance_size = node->is_instantiatable ? node->data->instance.instance_size : 0;
3818     }
3819       G_READ_UNLOCK (&type_rw_lock);
3820     }
3821 }
3822 
3823 
3824 /* --- implementation details --- */
3825 gboolean
3826 g_type_test_flags (GType type,
3827            guint flags)
3828 {
3829   TypeNode *node;
3830   gboolean result = FALSE;
3831 
3832   node = lookup_type_node_I (type);
3833   if (node)
3834     {
3835       guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
3836       guint tflags = flags & TYPE_FLAG_MASK;
3837 
3838       if (fflags)
3839     {
3840       GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (node);
3841 
3842       fflags = (finfo->type_flags & fflags) == fflags;
3843     }
3844       else
3845     fflags = TRUE;
3846 
3847       if (tflags)
3848     {
3849       G_READ_LOCK (&type_rw_lock);
3850       tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
3851       G_READ_UNLOCK (&type_rw_lock);
3852     }
3853       else
3854     tflags = TRUE;
3855 
3856       result = tflags && fflags;
3857     }
3858 
3859   return result;
3860 }
3861 
3862 /**
3863  * g_type_get_plugin:
3864  * @type: #GType to retrieve the plugin for
3865  *
3866  * Returns the #GTypePlugin structure for @type.
3867  *
3868  * Returns: (transfer none): the corresponding plugin
3869  *     if @type is a dynamic type, %NULL otherwise
3870  */
3871 GTypePlugin*
3872 g_type_get_plugin (GType type)
3873 {
3874   TypeNode *node;
3875 
3876   node = lookup_type_node_I (type);
3877 
3878   return node ? node->plugin : NULL;
3879 }
3880 
3881 /**
3882  * g_type_interface_get_plugin:
3883  * @instance_type: #GType of an instantiatable type
3884  * @interface_type: #GType of an interface type
3885  *
3886  * Returns the #GTypePlugin structure for the dynamic interface
3887  * @interface_type which has been added to @instance_type, or %NULL
3888  * if @interface_type has not been added to @instance_type or does
3889  * not have a #GTypePlugin structure. See g_type_add_interface_dynamic().
3890  *
3891  * Returns: (transfer none): the #GTypePlugin for the dynamic
3892  *     interface @interface_type of @instance_type
3893  */
3894 GTypePlugin*
3895 g_type_interface_get_plugin (GType instance_type,
3896                  GType interface_type)
3897 {
3898   TypeNode *node;
3899   TypeNode *iface;
3900 
3901   g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);    /* G_TYPE_IS_INTERFACE() is an external call: _U */
3902 
3903   node = lookup_type_node_I (instance_type);
3904   iface = lookup_type_node_I (interface_type);
3905   if (node && iface)
3906     {
3907       IFaceHolder *iholder;
3908       GTypePlugin *plugin;
3909 
3910       G_READ_LOCK (&type_rw_lock);
3911 
3912       iholder = iface_node_get_holders_L (iface);
3913       while (iholder && iholder->instance_type != instance_type)
3914     iholder = iholder->next;
3915       plugin = iholder ? iholder->plugin : NULL;
3916 
3917       G_READ_UNLOCK (&type_rw_lock);
3918 
3919       return plugin;
3920     }
3921 
3922   g_return_val_if_fail (node == NULL, NULL);
3923   g_return_val_if_fail (iface == NULL, NULL);
3924 
3925   g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
3926 
3927   return NULL;
3928 }
3929 
3930 /**
3931  * g_type_fundamental_next:
3932  *
3933  * Returns the next free fundamental type id which can be used to
3934  * register a new fundamental type with g_type_register_fundamental().
3935  * The returned type ID represents the highest currently registered
3936  * fundamental type identifier.
3937  *
3938  * Returns: the next available fundamental type ID to be registered,
3939  *     or 0 if the type system ran out of fundamental type IDs
3940  */
3941 GType
3942 g_type_fundamental_next (void)
3943 {
3944   GType type;
3945 
3946   G_READ_LOCK (&type_rw_lock);
3947   type = static_fundamental_next;
3948   G_READ_UNLOCK (&type_rw_lock);
3949   type = G_TYPE_MAKE_FUNDAMENTAL (type);
3950   return type <= G_TYPE_FUNDAMENTAL_MAX ? type : 0;
3951 }
3952 
3953 /**
3954  * g_type_fundamental:
3955  * @type_id: valid type ID
3956  *
3957  * Internal function, used to extract the fundamental type ID portion.
3958  * Use G_TYPE_FUNDAMENTAL() instead.
3959  *
3960  * Returns: fundamental type ID
3961  */
3962 GType
3963 g_type_fundamental (GType type_id)
3964 {
3965   TypeNode *node = lookup_type_node_I (type_id);
3966 
3967   return node ? NODE_FUNDAMENTAL_TYPE (node) : 0;
3968 }
3969 
3970 gboolean
3971 g_type_check_instance_is_a (GTypeInstance *type_instance,
3972                 GType          iface_type)
3973 {
3974   TypeNode *node, *iface;
3975   gboolean check;
3976 
3977   if (!type_instance || !type_instance->g_class)
3978     return FALSE;
3979 
3980   node = lookup_type_node_I (type_instance->g_class->g_type);
3981   iface = lookup_type_node_I (iface_type);
3982   check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
3983 
3984   return check;
3985 }
3986 
3987 gboolean
3988 g_type_check_instance_is_fundamentally_a (GTypeInstance *type_instance,
3989                                           GType          fundamental_type)
3990 {
3991   TypeNode *node;
3992   if (!type_instance || !type_instance->g_class)
3993     return FALSE;
3994   node = lookup_type_node_I (type_instance->g_class->g_type);
3995   return node && (NODE_FUNDAMENTAL_TYPE(node) == fundamental_type);
3996 }
3997 
3998 gboolean
3999 g_type_check_class_is_a (GTypeClass *type_class,
4000              GType       is_a_type)
4001 {
4002   TypeNode *node, *iface;
4003   gboolean check;
4004 
4005   if (!type_class)
4006     return FALSE;
4007 
4008   node = lookup_type_node_I (type_class->g_type);
4009   iface = lookup_type_node_I (is_a_type);
4010   check = node && node->is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
4011 
4012   return check;
4013 }
4014 
4015 GTypeInstance*
4016 g_type_check_instance_cast (GTypeInstance *type_instance,
4017                 GType          iface_type)
4018 {
4019   if (type_instance)
4020     {
4021       if (type_instance->g_class)
4022     {
4023       TypeNode *node, *iface;
4024       gboolean is_instantiatable, check;
4025 
4026       node = lookup_type_node_I (type_instance->g_class->g_type);
4027       is_instantiatable = node && node->is_instantiatable;
4028       iface = lookup_type_node_I (iface_type);
4029       check = is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
4030       if (check)
4031         return type_instance;
4032 
4033       if (is_instantiatable)
4034         g_warning ("invalid cast from '%s' to '%s'",
4035                type_descriptive_name_I (type_instance->g_class->g_type),
4036                type_descriptive_name_I (iface_type));
4037       else
4038         g_warning ("invalid uninstantiatable type '%s' in cast to '%s'",
4039                type_descriptive_name_I (type_instance->g_class->g_type),
4040                type_descriptive_name_I (iface_type));
4041     }
4042       else
4043     g_warning ("invalid unclassed pointer in cast to '%s'",
4044            type_descriptive_name_I (iface_type));
4045     }
4046 
4047   return type_instance;
4048 }
4049 
4050 GTypeClass*
4051 g_type_check_class_cast (GTypeClass *type_class,
4052              GType       is_a_type)
4053 {
4054   if (type_class)
4055     {
4056       TypeNode *node, *iface;
4057       gboolean is_classed, check;
4058 
4059       node = lookup_type_node_I (type_class->g_type);
4060       is_classed = node && node->is_classed;
4061       iface = lookup_type_node_I (is_a_type);
4062       check = is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
4063       if (check)
4064     return type_class;
4065 
4066       if (is_classed)
4067     g_warning ("invalid class cast from '%s' to '%s'",
4068            type_descriptive_name_I (type_class->g_type),
4069            type_descriptive_name_I (is_a_type));
4070       else
4071     g_warning ("invalid unclassed type '%s' in class cast to '%s'",
4072            type_descriptive_name_I (type_class->g_type),
4073            type_descriptive_name_I (is_a_type));
4074     }
4075   else
4076     g_warning ("invalid class cast from (NULL) pointer to '%s'",
4077            type_descriptive_name_I (is_a_type));
4078   return type_class;
4079 }
4080 
4081 /**
4082  * g_type_check_instance:
4083  * @instance: a valid #GTypeInstance structure
4084  *
4085  * Private helper function to aid implementation of the
4086  * G_TYPE_CHECK_INSTANCE() macro.
4087  *
4088  * Returns: %TRUE if @instance is valid, %FALSE otherwise
4089  */
4090 gboolean
4091 g_type_check_instance (GTypeInstance *type_instance)
4092 {
4093   /* this function is just here to make the signal system
4094    * conveniently elaborated on instance checks
4095    */
4096   if (type_instance)
4097     {
4098       if (type_instance->g_class)
4099     {
4100       TypeNode *node = lookup_type_node_I (type_instance->g_class->g_type);
4101 
4102       if (node && node->is_instantiatable)
4103         return TRUE;
4104 
4105       g_warning ("instance of invalid non-instantiatable type '%s'",
4106              type_descriptive_name_I (type_instance->g_class->g_type));
4107     }
4108       else
4109     g_warning ("instance with invalid (NULL) class pointer");
4110     }
4111   else
4112     g_warning ("invalid (NULL) pointer instance");
4113 
4114   return FALSE;
4115 }
4116 
4117 static inline gboolean
4118 type_check_is_value_type_U (GType type)
4119 {
4120   GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT;
4121   TypeNode *node;
4122 
4123   /* common path speed up */
4124   node = lookup_type_node_I (type);
4125   if (node && node->mutatable_check_cache)
4126     return TRUE;
4127 
4128   G_READ_LOCK (&type_rw_lock);
4129  restart_check:
4130   if (node)
4131     {
4132       if (node->data && NODE_REFCOUNT (node) > 0 &&
4133       node->data->common.value_table->value_init)
4134     tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
4135       else if (NODE_IS_IFACE (node))
4136     {
4137       guint i;
4138 
4139       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
4140         {
4141           GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
4142           TypeNode *prnode = lookup_type_node_I (prtype);
4143 
4144           if (prnode->is_instantiatable)
4145         {
4146           type = prtype;
4147           node = lookup_type_node_I (type);
4148           goto restart_check;
4149         }
4150         }
4151     }
4152     }
4153   G_READ_UNLOCK (&type_rw_lock);
4154 
4155   return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT);
4156 }
4157 
4158 gboolean
4159 g_type_check_is_value_type (GType type)
4160 {
4161   return type_check_is_value_type_U (type);
4162 }
4163 
4164 gboolean
4165 g_type_check_value (GValue *value)
4166 {
4167   return value && type_check_is_value_type_U (value->g_type);
4168 }
4169 
4170 gboolean
4171 g_type_check_value_holds (GValue *value,
4172               GType   type)
4173 {
4174   return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type);
4175 }
4176 
4177 /**
4178  * g_type_value_table_peek: (skip)
4179  * @type: a #GType
4180  *
4181  * Returns the location of the #GTypeValueTable associated with @type.
4182  *
4183  * Note that this function should only be used from source code
4184  * that implements or has internal knowledge of the implementation of
4185  * @type.
4186  *
4187  * Returns: location of the #GTypeValueTable associated with @type or
4188  *     %NULL if there is no #GTypeValueTable associated with @type
4189  */
4190 GTypeValueTable*
4191 g_type_value_table_peek (GType type)
4192 {
4193   GTypeValueTable *vtable = NULL;
4194   TypeNode *node = lookup_type_node_I (type);
4195   gboolean has_refed_data, has_table;
4196 
4197   if (node && NODE_REFCOUNT (node) && node->mutatable_check_cache)
4198     return node->data->common.value_table;
4199 
4200   G_READ_LOCK (&type_rw_lock);
4201 
4202  restart_table_peek:
4203   has_refed_data = node && node->data && NODE_REFCOUNT (node) > 0;
4204   has_table = has_refed_data && node->data->common.value_table->value_init;
4205   if (has_refed_data)
4206     {
4207       if (has_table)
4208     vtable = node->data->common.value_table;
4209       else if (NODE_IS_IFACE (node))
4210     {
4211       guint i;
4212 
4213       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
4214         {
4215           GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
4216           TypeNode *prnode = lookup_type_node_I (prtype);
4217 
4218           if (prnode->is_instantiatable)
4219         {
4220           type = prtype;
4221           node = lookup_type_node_I (type);
4222           goto restart_table_peek;
4223         }
4224         }
4225     }
4226     }
4227 
4228   G_READ_UNLOCK (&type_rw_lock);
4229 
4230   if (vtable)
4231     return vtable;
4232 
4233   if (!node)
4234     g_warning (G_STRLOC ": type id '%" G_GSIZE_FORMAT "' is invalid", type);
4235   if (!has_refed_data)
4236     g_warning ("can't peek value table for type '%s' which is not currently referenced",
4237            type_descriptive_name_I (type));
4238 
4239   return NULL;
4240 }
4241 
4242 const gchar *
4243 g_type_name_from_instance (GTypeInstance *instance)
4244 {
4245   if (!instance)
4246     return "<NULL-instance>";
4247   else
4248     return g_type_name_from_class (instance->g_class);
4249 }
4250 
4251 const gchar *
4252 g_type_name_from_class (GTypeClass *g_class)
4253 {
4254   if (!g_class)
4255     return "<NULL-class>";
4256   else
4257     return g_type_name (g_class->g_type);
4258 }
4259 
4260 
4261 /* --- private api for gboxed.c --- */
4262 gpointer
4263 _g_type_boxed_copy (GType type, gpointer value)
4264 {
4265   TypeNode *node = lookup_type_node_I (type);
4266 
4267   return node->data->boxed.copy_func (value);
4268 }
4269 
4270 void
4271 _g_type_boxed_free (GType type, gpointer value)
4272 {
4273   TypeNode *node = lookup_type_node_I (type);
4274 
4275   node->data->boxed.free_func (value);
4276 }
4277 
4278 void
4279 _g_type_boxed_init (GType          type,
4280                     GBoxedCopyFunc copy_func,
4281                     GBoxedFreeFunc free_func)
4282 {
4283   TypeNode *node = lookup_type_node_I (type);
4284 
4285   node->data->boxed.copy_func = copy_func;
4286   node->data->boxed.free_func = free_func;
4287 }
4288 
4289 /* --- initialization --- */
4290 /**
4291  * g_type_init_with_debug_flags:
4292  * @debug_flags: bitwise combination of #GTypeDebugFlags values for
4293  *     debugging purposes
4294  *
4295  * This function used to initialise the type system with debugging
4296  * flags.  Since GLib 2.36, the type system is initialised automatically
4297  * and this function does nothing.
4298  *
4299  * If you need to enable debugging features, use the GOBJECT_DEBUG
4300  * environment variable.
4301  *
4302  * Deprecated: 2.36: the type system is now initialised automatically
4303  */
4304 void
4305 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
4306 {
4307   g_assert_type_system_initialized ();
4308 
4309   if (debug_flags)
4310     g_message ("g_type_init_with_debug_flags() is no longer supported.  Use the GOBJECT_DEBUG environment variable.");
4311 }
4312 
4313 /**
4314  * g_type_init:
4315  *
4316  * This function used to initialise the type system.  Since GLib 2.36,
4317  * the type system is initialised automatically and this function does
4318  * nothing.
4319  *
4320  * Deprecated: 2.36: the type system is now initialised automatically
4321  */
4322 #if !(defined(GSTREAMER_LITE) && defined(G_OS_WIN32))
4323 void
4324 g_type_init (void)
4325 {
4326   g_assert_type_system_initialized ();
4327 }
4328 #endif // GSTREAMER_LITE
4329 
4330 #if defined(GSTREAMER_LITE) && defined(G_OS_WIN32)
4331 // We cannot due static initialization, since it will crash due to
4332 // threading system is not initialized yet.
4333 static void gobject_init_ctor (void);
4334 void
4335 g_type_init (void)
4336 {
4337   gobject_init_ctor ();
4338 }
4339 #else GSTREAMER_LITE
4340 #if defined (G_HAS_CONSTRUCTORS)
4341 #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
4342 #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(gobject_init_ctor)
4343 #endif
4344 G_DEFINE_CONSTRUCTOR(gobject_init_ctor)
4345 #else
4346 # error Your platform/compiler is missing constructor support
4347 #endif
4348 #endif // GSTREAMER_LITE
4349 
4350 static void
4351 gobject_init_ctor (void)
4352 {
4353   const gchar *env_string;
4354   GTypeInfo info;
4355   TypeNode *node;
4356   GType type;
4357 
4358   G_WRITE_LOCK (&type_rw_lock);
4359 
4360   /* setup GObject library wide debugging flags */
4361   env_string = g_getenv ("GOBJECT_DEBUG");
4362   if (env_string != NULL)
4363     {
4364       GDebugKey debug_keys[] = {
4365         { "objects", G_TYPE_DEBUG_OBJECTS },
4366         { "signals", G_TYPE_DEBUG_SIGNALS },
4367       };
4368 
4369       _g_type_debug_flags = g_parse_debug_string (env_string, debug_keys, G_N_ELEMENTS (debug_keys));
4370     }
4371 
4372   /* quarks */
4373   static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
4374   static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
4375   static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
4376 
4377   /* type qname hash table */
4378   static_type_nodes_ht = g_hash_table_new (g_str_hash, g_str_equal);
4379 
4380   /* invalid type G_TYPE_INVALID (0)
4381    */
4382   static_fundamental_type_nodes[0] = NULL;
4383 
4384   /* void type G_TYPE_NONE
4385    */
4386   node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0);
4387   type = NODE_TYPE (node);
4388   g_assert (type == G_TYPE_NONE);
4389 
4390   /* interface fundamental type G_TYPE_INTERFACE (!classed)
4391    */
4392   memset (&info, 0, sizeof (info));
4393   node = type_node_fundamental_new_W (G_TYPE_INTERFACE, g_intern_static_string ("GInterface"), G_TYPE_FLAG_DERIVABLE);
4394   type = NODE_TYPE (node);
4395   type_data_make_W (node, &info, NULL);
4396   g_assert (type == G_TYPE_INTERFACE);
4397 
4398   G_WRITE_UNLOCK (&type_rw_lock);
4399 
4400   _g_value_c_init ();
4401 
4402   /* G_TYPE_TYPE_PLUGIN
4403    */
4404   g_type_ensure (g_type_plugin_get_type ());
4405 
4406   /* G_TYPE_* value types
4407    */
4408   _g_value_types_init ();
4409 
4410   /* G_TYPE_ENUM & G_TYPE_FLAGS
4411    */
4412   _g_enum_types_init ();
4413 
4414   /* G_TYPE_BOXED
4415    */
4416   _g_boxed_type_init ();
4417 
4418   /* G_TYPE_PARAM
4419    */
4420   _g_param_type_init ();
4421 
4422   /* G_TYPE_OBJECT
4423    */
4424   _g_object_type_init ();
4425 
4426   /* G_TYPE_PARAM_* pspec types
4427    */
4428   _g_param_spec_types_init ();
4429 
4430   /* Value Transformations
4431    */
4432   _g_value_transforms_init ();
4433 
4434   /* Signal system
4435    */
4436   _g_signal_init ();
4437 }
4438 
4439 /**
4440  * g_type_class_add_private:
4441  * @g_class: class structure for an instantiatable type
4442  * @private_size: size of private structure
4443  *
4444  * Registers a private structure for an instantiatable type.
4445  *
4446  * When an object is allocated, the private structures for
4447  * the type and all of its parent types are allocated
4448  * sequentially in the same memory block as the public
4449  * structures, and are zero-filled.
4450  *
4451  * Note that the accumulated size of the private structures of
4452  * a type and all its parent types cannot exceed 64 KiB.
4453  *
4454  * This function should be called in the type's class_init() function.
4455  * The private structure can be retrieved using the
4456  * G_TYPE_INSTANCE_GET_PRIVATE() macro.
4457  *
4458  * The following example shows attaching a private structure
4459  * MyObjectPrivate to an object MyObject defined in the standard
4460  * GObject fashion in the type's class_init() function.
4461  *
4462  * Note the use of a structure member "priv" to avoid the overhead
4463  * of repeatedly calling MY_OBJECT_GET_PRIVATE().
4464  *
4465  * |[<!-- language="C" -->
4466  * typedef struct _MyObject        MyObject;
4467  * typedef struct _MyObjectPrivate MyObjectPrivate;
4468  *
4469  * struct _MyObject {
4470  *  GObject parent;
4471  *
4472  *  MyObjectPrivate *priv;
4473  * };
4474  *
4475  * struct _MyObjectPrivate {
4476  *   int some_field;
4477  * };
4478  *
4479  * static void
4480  * my_object_class_init (MyObjectClass *klass)
4481  * {
4482  *   g_type_class_add_private (klass, sizeof (MyObjectPrivate));
4483  * }
4484  *
4485  * static void
4486  * my_object_init (MyObject *my_object)
4487  * {
4488  *   my_object->priv = G_TYPE_INSTANCE_GET_PRIVATE (my_object,
4489  *                                                  MY_TYPE_OBJECT,
4490  *                                                  MyObjectPrivate);
4491  *   // my_object->priv->some_field will be automatically initialised to 0
4492  * }
4493  *
4494  * static int
4495  * my_object_get_some_field (MyObject *my_object)
4496  * {
4497  *   MyObjectPrivate *priv;
4498  *
4499  *   g_return_val_if_fail (MY_IS_OBJECT (my_object), 0);
4500  *
4501  *   priv = my_object->priv;
4502  *
4503  *   return priv->some_field;
4504  * }
4505  * ]|
4506  *
4507  * Since: 2.4
4508  */
4509 void
4510 g_type_class_add_private (gpointer g_class,
4511               gsize    private_size)
4512 {
4513   GType instance_type = ((GTypeClass *)g_class)->g_type;
4514   TypeNode *node = lookup_type_node_I (instance_type);
4515 
4516   g_return_if_fail (private_size > 0);
4517   g_return_if_fail (private_size <= 0xffff);
4518 
4519   if (!node || !node->is_instantiatable || !node->data || node->data->class.class != g_class)
4520     {
4521       g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'",
4522          type_descriptive_name_I (instance_type));
4523       return;
4524     }
4525 
4526   if (NODE_PARENT_TYPE (node))
4527     {
4528       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
4529       if (node->data->instance.private_size != pnode->data->instance.private_size)
4530     {
4531       g_warning ("g_type_class_add_private() called multiple times for the same type");
4532       return;
4533     }
4534     }
4535 
4536   G_WRITE_LOCK (&type_rw_lock);
4537 
4538   private_size = ALIGN_STRUCT (node->data->instance.private_size + private_size);
4539   g_assert (private_size <= 0xffff);
4540   node->data->instance.private_size = private_size;
4541 
4542   G_WRITE_UNLOCK (&type_rw_lock);
4543 }
4544 
4545 /* semi-private, called only by the G_ADD_PRIVATE macro */
4546 gint
4547 g_type_add_instance_private (GType class_gtype,
4548                              gsize private_size)
4549 {
4550   TypeNode *node = lookup_type_node_I (class_gtype);
4551 
4552   g_return_val_if_fail (private_size > 0, 0);
4553   g_return_val_if_fail (private_size <= 0xffff, 0);
4554 
4555   if (!node || !node->is_classed || !node->is_instantiatable || !node->data)
4556     {
4557       g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'",
4558          type_descriptive_name_I (class_gtype));
4559       return 0;
4560     }
4561 
4562   if (node->plugin != NULL)
4563     {
4564       g_warning ("cannot use g_type_add_instance_private() with dynamic type '%s'",
4565                  type_descriptive_name_I (class_gtype));
4566       return 0;
4567     }
4568 
4569   /* in the future, we want to register the private data size of a type
4570    * directly from the get_type() implementation so that we can take full
4571    * advantage of the type definition macros that we already have.
4572    *
4573    * unfortunately, this does not behave correctly if a class in the middle
4574    * of the type hierarchy uses the "old style" of private data registration
4575    * from the class_init() implementation, as the private data offset is not
4576    * going to be known until the full class hierarchy is initialized.
4577    *
4578    * in order to transition our code to the Glorious New Futureā„¢, we proceed
4579    * with a two-step implementation: first, we provide this new function to
4580    * register the private data size in the get_type() implementation and we
4581    * hide it behind a macro. the function will return the private size, instead
4582    * of the offset, which will be stored inside a static variable defined by
4583    * the G_DEFINE_TYPE_EXTENDED macro. the G_DEFINE_TYPE_EXTENDED macro will
4584    * check the variable and call g_type_class_add_instance_private(), which
4585    * will use the data size and actually register the private data, then
4586    * return the computed offset of the private data, which will be stored
4587    * inside the static variable, so we can use it to retrieve the pointer
4588    * to the private data structure.
4589    *
4590    * once all our code has been migrated to the new idiomatic form of private
4591    * data registration, we will change the g_type_add_instance_private()
4592    * function to actually perform the registration and return the offset
4593    * of the private data; g_type_class_add_instance_private() already checks
4594    * if the passed argument is negative (meaning that it's an offset in the
4595    * GTypeInstance allocation) and becomes a no-op if that's the case. this
4596    * should make the migration fully transparent even if we're effectively
4597    * copying this macro into everybody's code.
4598    */
4599   return private_size;
4600 }
4601 
4602 /* semi-private function, should only be used by G_DEFINE_TYPE_EXTENDED */
4603 void
4604 g_type_class_adjust_private_offset (gpointer  g_class,
4605                                     gint     *private_size_or_offset)
4606 {
4607   GType class_gtype = ((GTypeClass *) g_class)->g_type;
4608   TypeNode *node = lookup_type_node_I (class_gtype);
4609   gssize private_size;
4610 
4611   g_return_if_fail (private_size_or_offset != NULL);
4612 
4613   /* if we have been passed the offset instead of the private data size,
4614    * then we consider this as a no-op, and just return the value. see the
4615    * comment in g_type_add_instance_private() for the full explanation.
4616    */
4617   if (*private_size_or_offset > 0)
4618     g_return_if_fail (*private_size_or_offset <= 0xffff);
4619   else
4620     return;
4621 
4622   if (!node || !node->is_classed || !node->is_instantiatable || !node->data)
4623     {
4624       g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'",
4625          type_descriptive_name_I (class_gtype));
4626       *private_size_or_offset = 0;
4627       return;
4628     }
4629 
4630   if (NODE_PARENT_TYPE (node))
4631     {
4632       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
4633       if (node->data->instance.private_size != pnode->data->instance.private_size)
4634     {
4635       g_warning ("g_type_add_instance_private() called multiple times for the same type");
4636           *private_size_or_offset = 0;
4637       return;
4638     }
4639     }
4640 
4641   G_WRITE_LOCK (&type_rw_lock);
4642 
4643   private_size = ALIGN_STRUCT (node->data->instance.private_size + *private_size_or_offset);
4644   g_assert (private_size <= 0xffff);
4645   node->data->instance.private_size = private_size;
4646 
4647   *private_size_or_offset = -(gint) node->data->instance.private_size;
4648 
4649   G_WRITE_UNLOCK (&type_rw_lock);
4650 }
4651 
4652 gpointer
4653 g_type_instance_get_private (GTypeInstance *instance,
4654                  GType          private_type)
4655 {
4656   TypeNode *node;
4657 
4658   g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
4659 
4660   node = lookup_type_node_I (private_type);
4661   if (G_UNLIKELY (!node || !node->is_instantiatable))
4662     {
4663       g_warning ("instance of invalid non-instantiatable type '%s'",
4664                  type_descriptive_name_I (instance->g_class->g_type));
4665       return NULL;
4666     }
4667 
4668   return ((gchar *) instance) - node->data->instance.private_size;
4669 }
4670 
4671 /**
4672  * g_type_class_get_instance_private_offset: (skip)
4673  * @g_class: a #GTypeClass
4674  *
4675  * Gets the offset of the private data for instances of @g_class.
4676  *
4677  * This is how many bytes you should add to the instance pointer of a
4678  * class in order to get the private data for the type represented by
4679  * @g_class.
4680  *
4681  * You can only call this function after you have registered a private
4682  * data area for @g_class using g_type_class_add_private().
4683  *
4684  * Returns: the offset, in bytes
4685  *
4686  * Since: 2.38
4687  **/
4688 gint
4689 g_type_class_get_instance_private_offset (gpointer g_class)
4690 {
4691   GType instance_type;
4692   guint16 parent_size;
4693   TypeNode *node;
4694 
4695   g_assert (g_class != NULL);
4696 
4697   instance_type = ((GTypeClass *) g_class)->g_type;
4698   node = lookup_type_node_I (instance_type);
4699 
4700   g_assert (node != NULL);
4701   g_assert (node->is_instantiatable);
4702 
4703   if (NODE_PARENT_TYPE (node))
4704     {
4705       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
4706 
4707       parent_size = pnode->data->instance.private_size;
4708     }
4709   else
4710     parent_size = 0;
4711 
4712   if (node->data->instance.private_size == parent_size)
4713     g_error ("g_type_class_get_instance_private_offset() called on class %s but it has no private data",
4714              g_type_name (instance_type));
4715 
4716   return -(gint) node->data->instance.private_size;
4717 }
4718 
4719 /**
4720  * g_type_add_class_private:
4721  * @class_type: GType of an classed type
4722  * @private_size: size of private structure
4723  *
4724  * Registers a private class structure for a classed type;
4725  * when the class is allocated, the private structures for
4726  * the class and all of its parent types are allocated
4727  * sequentially in the same memory block as the public
4728  * structures, and are zero-filled.
4729  *
4730  * This function should be called in the
4731  * type's get_type() function after the type is registered.
4732  * The private structure can be retrieved using the
4733  * G_TYPE_CLASS_GET_PRIVATE() macro.
4734  *
4735  * Since: 2.24
4736  */
4737 void
4738 g_type_add_class_private (GType    class_type,
4739               gsize    private_size)
4740 {
4741   TypeNode *node = lookup_type_node_I (class_type);
4742   gsize offset;
4743 
4744   g_return_if_fail (private_size > 0);
4745 
4746   if (!node || !node->is_classed || !node->data)
4747     {
4748       g_warning ("cannot add class private field to invalid type '%s'",
4749          type_descriptive_name_I (class_type));
4750       return;
4751     }
4752 
4753   if (NODE_PARENT_TYPE (node))
4754     {
4755       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
4756       if (node->data->class.class_private_size != pnode->data->class.class_private_size)
4757     {
4758       g_warning ("g_type_add_class_private() called multiple times for the same type");
4759       return;
4760     }
4761     }
4762 
4763   G_WRITE_LOCK (&type_rw_lock);
4764 
4765   offset = ALIGN_STRUCT (node->data->class.class_private_size);
4766   node->data->class.class_private_size = offset + private_size;
4767 
4768   G_WRITE_UNLOCK (&type_rw_lock);
4769 }
4770 
4771 gpointer
4772 g_type_class_get_private (GTypeClass *klass,
4773               GType       private_type)
4774 {
4775   TypeNode *class_node;
4776   TypeNode *private_node;
4777   TypeNode *parent_node;
4778   gsize offset;
4779 
4780   g_return_val_if_fail (klass != NULL, NULL);
4781 
4782   class_node = lookup_type_node_I (klass->g_type);
4783   if (G_UNLIKELY (!class_node || !class_node->is_classed))
4784     {
4785       g_warning ("class of invalid type '%s'",
4786          type_descriptive_name_I (klass->g_type));
4787       return NULL;
4788     }
4789 
4790   private_node = lookup_type_node_I (private_type);
4791   if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, class_node)))
4792     {
4793       g_warning ("attempt to retrieve private data for invalid type '%s'",
4794          type_descriptive_name_I (private_type));
4795       return NULL;
4796     }
4797 
4798   offset = ALIGN_STRUCT (class_node->data->class.class_size);
4799 
4800   if (NODE_PARENT_TYPE (private_node))
4801     {
4802       parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
4803       g_assert (parent_node->data && NODE_REFCOUNT (parent_node) > 0);
4804 
4805       if (G_UNLIKELY (private_node->data->class.class_private_size == parent_node->data->class.class_private_size))
4806     {
4807       g_warning ("g_type_instance_get_class_private() requires a prior call to g_type_add_class_private()");
4808       return NULL;
4809     }
4810 
4811       offset += ALIGN_STRUCT (parent_node->data->class.class_private_size);
4812     }
4813 
4814   return G_STRUCT_MEMBER_P (klass, offset);
4815 }
4816 
4817 /**
4818  * g_type_ensure:
4819  * @type: a #GType
4820  *
4821  * Ensures that the indicated @type has been registered with the
4822  * type system, and its _class_init() method has been run.
4823  *
4824  * In theory, simply calling the type's _get_type() method (or using
4825  * the corresponding macro) is supposed take care of this. However,
4826  * _get_type() methods are often marked %G_GNUC_CONST for performance
4827  * reasons, even though this is technically incorrect (since
4828  * %G_GNUC_CONST requires that the function not have side effects,
4829  * which _get_type() methods do on the first call). As a result, if
4830  * you write a bare call to a _get_type() macro, it may get optimized
4831  * out by the compiler. Using g_type_ensure() guarantees that the
4832  * type's _get_type() method is called.
4833  *
4834  * Since: 2.34
4835  */
4836 void
4837 g_type_ensure (GType type)
4838 {
4839   /* In theory, @type has already been resolved and so there's nothing
4840    * to do here. But this protects us in the case where the function
4841    * gets inlined (as it might in gobject_init_ctor() above).
4842    */
4843   if (G_UNLIKELY (type == (GType)-1))
4844     g_error ("can't happen");
4845 }