LCOV - code coverage report
Current view: top level - gobject - gtype.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 78.2 % 1721 1346
Test Date: 2024-11-26 05:23:01 Functions: 90.1 % 121 109
Branches: - 0 0

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

Generated by: LCOV version 2.0-1