LCOV - code coverage report
Current view: top level - glib/gobject - gtype.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 1345 1721 78.2 %
Date: 2023-11-28 05:14:24 Functions: 109 121 90.1 %
Branches: 760 1196 63.5 %

           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                 :  892648229 : lookup_type_node_I (GType utype)
     369                 :            : {
     370         [ +  + ]:  892648229 :   if (utype > G_TYPE_FUNDAMENTAL_MAX)
     371                 :  712376855 :     return (TypeNode*) (utype & ~TYPE_ID_MASK);
     372                 :            :   else
     373                 :  180271374 :     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                 :      37810 : 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                 :      37810 :   guint i, node_size = 0;
     406                 :            : 
     407         [ +  + ]:      37810 :   n_supers = pnode ? pnode->n_supers + 1 : 0;
     408                 :            :   
     409         [ +  + ]:      37810 :   if (!pnode)
     410                 :      10670 :     node_size += SIZEOF_FUNDAMENTAL_INFO;             /* fundamental type info */
     411                 :      37810 :   node_size += SIZEOF_BASE_TYPE_NODE ();              /* TypeNode structure */
     412                 :      37810 :   node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */
     413                 :      37810 :   node = g_malloc0 (node_size);
     414         [ +  + ]:      37810 :   if (!pnode)                                         /* offset fundamental types */
     415                 :            :     {
     416                 :      10670 :       node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
     417                 :      10670 :       static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;
     418                 :      10670 :       type = ftype;
     419                 :            : 
     420                 :            : #if ENABLE_VALGRIND
     421                 :      10670 :       VALGRIND_MALLOCLIKE_BLOCK (node, node_size - SIZEOF_FUNDAMENTAL_INFO, FALSE, TRUE);
     422                 :            : #endif
     423                 :            :     }
     424                 :            :   else
     425                 :      27140 :     type = GPOINTER_TO_TYPE (node);
     426                 :            :   
     427                 :      37810 :   g_assert ((type & TYPE_ID_MASK) == 0);
     428                 :            :   
     429                 :      37810 :   node->n_supers = n_supers;
     430         [ +  + ]:      37810 :   if (!pnode)
     431                 :            :     {
     432                 :      10670 :       node->supers[0] = type;
     433                 :      10670 :       node->supers[1] = 0;
     434                 :            :       
     435                 :      10670 :       node->is_abstract = (type_flags & G_TYPE_FLAG_ABSTRACT) != 0;
     436                 :      10670 :       node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
     437                 :      10670 :       node->is_deprecated = (type_flags & G_TYPE_FLAG_DEPRECATED) != 0;
     438                 :      10670 :       node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
     439                 :            :       
     440         [ +  + ]:      10670 :       if (NODE_IS_IFACE (node))
     441                 :            :         {
     442                 :        508 :           IFACE_NODE_N_PREREQUISITES (node) = 0;
     443                 :        508 :           IFACE_NODE_PREREQUISITES (node) = NULL;
     444                 :            :         }
     445                 :            :       else
     446                 :      10162 :         _g_atomic_array_init (CLASSED_NODE_IFACES_ENTRIES (node));
     447                 :            :     }
     448                 :            :   else
     449                 :            :     {
     450                 :      27140 :       node->supers[0] = type;
     451                 :      27140 :       memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
     452                 :            :       
     453                 :      27140 :       node->is_abstract = (type_flags & G_TYPE_FLAG_ABSTRACT) != 0;
     454                 :      27140 :       node->is_classed = pnode->is_classed;
     455                 :      27140 :       node->is_deprecated = (type_flags & G_TYPE_FLAG_DEPRECATED) != 0;
     456                 :      27140 :       node->is_instantiatable = pnode->is_instantiatable;
     457                 :            : 
     458                 :      27140 :       node->is_deprecated |= pnode->is_deprecated;
     459                 :            : 
     460         [ +  + ]:      27140 :       if (NODE_IS_IFACE (node))
     461                 :            :         {
     462                 :       3231 :           IFACE_NODE_N_PREREQUISITES (node) = 0;
     463                 :       3231 :           IFACE_NODE_PREREQUISITES (node) = NULL;
     464                 :            :         }
     465                 :            :       else
     466                 :            :         {
     467                 :            :           guint j;
     468                 :            :           IFaceEntries *entries;
     469                 :            : 
     470                 :      23909 :           entries = _g_atomic_array_copy (CLASSED_NODE_IFACES_ENTRIES (pnode),
     471                 :            :                                           IFACE_ENTRIES_HEADER_SIZE,
     472                 :            :                                           0);
     473         [ +  + ]:      23909 :           if (entries)
     474                 :            :             {
     475         [ +  + ]:       2825 :               for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (entries); j++)
     476                 :            :                 {
     477                 :       1642 :                   entries->entry[j].vtable = NULL;
     478                 :       1642 :                   entries->entry[j].init_state = UNINITIALIZED;
     479                 :            :                 }
     480                 :       1183 :               _g_atomic_array_update (CLASSED_NODE_IFACES_ENTRIES (node),
     481                 :            :                                       entries);
     482                 :            :             }
     483                 :            :         }
     484                 :            : 
     485                 :      27140 :       i = pnode->n_children++;
     486                 :      27140 :       pnode->children = g_renew (GType, pnode->children, pnode->n_children);
     487                 :      27140 :       pnode->children[i] = type;
     488                 :            :     }
     489                 :            : 
     490                 :      37810 :   TRACE(GOBJECT_TYPE_NEW(name, node->supers[1], type));
     491                 :            : 
     492                 :      37810 :   node->plugin = plugin;
     493                 :      37810 :   node->n_children = 0;
     494                 :      37810 :   node->children = NULL;
     495                 :      37810 :   node->data = NULL;
     496                 :      37810 :   node->qname = g_quark_from_string (name);
     497                 :      37810 :   node->global_gdata = NULL;
     498                 :      37810 :   g_hash_table_insert (static_type_nodes_ht,
     499                 :      37810 :                        (gpointer) g_quark_to_string (node->qname),
     500                 :            :                        GTYPE_TO_POINTER (type));
     501                 :            : 
     502                 :      37810 :   g_atomic_int_inc ((gint *)&type_registration_serial);
     503                 :            : 
     504                 :      37810 :   return node;
     505                 :            : }
     506                 :            : 
     507                 :            : static inline GTypeFundamentalInfo*
     508                 :      74608 : type_node_fundamental_info_I (TypeNode *node)
     509                 :            : {
     510                 :      74608 :   GType ftype = NODE_FUNDAMENTAL_TYPE (node);
     511                 :            :   
     512         [ +  + ]:      74608 :   if (ftype != NODE_TYPE (node))
     513                 :       4192 :     node = lookup_type_node_I (ftype);
     514                 :            :   
     515         [ +  - ]:      74608 :   return node ? G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO) : NULL;
     516                 :            : }
     517                 :            : 
     518                 :            : static TypeNode*
     519                 :      10670 : type_node_fundamental_new_W (GType                 ftype,
     520                 :            :                              const gchar          *name,
     521                 :            :                              GTypeFundamentalFlags type_flags)
     522                 :            : {
     523                 :            :   GTypeFundamentalInfo *finfo;
     524                 :            :   TypeNode *node;
     525                 :            : 
     526                 :      10670 :   g_assert ((ftype & TYPE_ID_MASK) == 0);
     527                 :      10670 :   g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX);
     528                 :            : 
     529         [ +  + ]:      10670 :   if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next)
     530                 :          2 :     static_fundamental_next++;
     531                 :            : 
     532                 :      10670 :   node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
     533                 :            : 
     534                 :      10670 :   finfo = type_node_fundamental_info_I (node);
     535                 :      10670 :   finfo->type_flags = type_flags & TYPE_FUNDAMENTAL_FLAG_MASK;
     536                 :            : 
     537                 :      10670 :   return node;
     538                 :            : }
     539                 :            : 
     540                 :            : static TypeNode*
     541                 :      27140 : type_node_new_W (TypeNode    *pnode,
     542                 :            :                  const gchar *name,
     543                 :            :                  GTypePlugin *plugin)
     544                 :            :      
     545                 :            : {
     546                 :      27140 :   g_assert (pnode);
     547                 :      27140 :   g_assert (pnode->n_supers < MAX_N_SUPERS);
     548                 :      27140 :   g_assert (pnode->n_children < MAX_N_CHILDREN);
     549                 :            :   
     550                 :      27140 :   return type_node_any_new_W (pnode, NODE_FUNDAMENTAL_TYPE (pnode), name, plugin, 0);
     551                 :            : }
     552                 :            : 
     553                 :            : static inline IFaceEntry*
     554                 :    5250225 : 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         [ +  + ]:    5250225 :   if (entries == NULL)
     564                 :      11513 :     return NULL;
     565                 :            : 
     566   [ +  +  +  +  :    5238712 :   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                 :    5238712 :  return entry;
     592                 :            : }
     593                 :            : 
     594                 :            : static inline IFaceEntry*
     595                 :      25476 : type_lookup_iface_entry_L (TypeNode *node,
     596                 :            :                            TypeNode *iface_node)
     597                 :            : {
     598         [ -  + ]:      25476 :   if (!NODE_IS_IFACE (iface_node))
     599                 :          0 :     return NULL;
     600                 :            : 
     601                 :      25476 :   return lookup_iface_entry_I (CLASSED_NODE_IFACES_ENTRIES_LOCKED (node),
     602                 :            :                                iface_node);
     603                 :            : }
     604                 :            : 
     605                 :            : 
     606                 :            : static inline gboolean
     607                 :    5223986 : type_lookup_iface_vtable_I (TypeNode *node,
     608                 :            :                             TypeNode *iface_node,
     609                 :            :                             gpointer *vtable_ptr)
     610                 :            : {
     611                 :            :   IFaceEntry *entry;
     612                 :            :   gboolean res;
     613                 :            : 
     614         [ -  + ]:    5223986 :   if (!NODE_IS_IFACE (iface_node))
     615                 :            :     {
     616         [ #  # ]:          0 :       if (vtable_ptr)
     617                 :          0 :         *vtable_ptr = NULL;
     618                 :          0 :       return FALSE;
     619                 :            :     }
     620                 :            : 
     621   [ +  +  +  +  :    5224277 :   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                 :    5226200 :   return res;
     636                 :            : }
     637                 :            : 
     638                 :            : static inline gboolean
     639                 :       7533 : type_lookup_prerequisite_L (TypeNode *iface,
     640                 :            :                             GType     prerequisite_type)
     641                 :            : {
     642   [ +  -  +  + ]:       7533 :   if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface))
     643                 :            :     {
     644                 :       4827 :       GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1;
     645                 :       4827 :       guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface);
     646                 :            :       
     647                 :            :       do
     648                 :            :         {
     649                 :            :           guint i;
     650                 :            :           GType *check;
     651                 :            :           
     652                 :       4832 :           i = (n_prerequisites + 1) >> 1;
     653                 :       4832 :           check = prerequisites + i;
     654         [ +  + ]:       4832 :           if (prerequisite_type == *check)
     655                 :       3237 :             return TRUE;
     656         [ +  + ]:       1595 :           else if (prerequisite_type > *check)
     657                 :            :             {
     658                 :        964 :               n_prerequisites -= i;
     659                 :        964 :               prerequisites = check;
     660                 :            :             }
     661                 :            :           else /* if (prerequisite_type < *check) */
     662                 :        631 :             n_prerequisites = i - 1;
     663                 :            :         }
     664         [ +  + ]:       1595 :       while (n_prerequisites);
     665                 :            :     }
     666                 :       4296 :   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                 :      36795 : check_type_name_I (const gchar *type_name)
     721                 :            : {
     722                 :            :   static const gchar extra_chars[] = "-_+";
     723                 :      36795 :   const gchar *p = type_name;
     724                 :            :   gboolean name_valid;
     725                 :            :   
     726   [ +  -  +  -  :      36795 :   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   [ +  -  +  +  :      36795 :   name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
          +  -  -  +  -  
                      - ]
     733         [ +  + ]:     431860 :   for (p = type_name + 1; *p; p++)
     734         [ +  + ]:     785579 :     name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
     735   [ +  +  -  + ]:     326376 :                    (p[0] >= 'a' && p[0] <= 'z') ||
     736   [ +  +  +  +  :     790131 :                    (p[0] >= '0' && p[0] <= '9') ||
                   -  + ]
     737         [ +  - ]:          1 :                    strchr (extra_chars, p[0]));
     738         [ -  + ]:      36795 :   if (!name_valid)
     739                 :            :     {
     740                 :          0 :       g_critical ("type name '%s' contains invalid characters", type_name);
     741                 :          0 :       return FALSE;
     742                 :            :     }
     743         [ -  + ]:      36795 :   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                 :      36795 :   return TRUE;
     750                 :            : }
     751                 :            : 
     752                 :            : static gboolean
     753                 :      27141 : check_derivation_I (GType        parent_type,
     754                 :            :                     const gchar *type_name)
     755                 :            : {
     756                 :            :   TypeNode *pnode;
     757                 :            :   GTypeFundamentalInfo* finfo;
     758                 :            :   
     759                 :      27141 :   pnode = lookup_type_node_I (parent_type);
     760         [ -  + ]:      27141 :   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         [ +  + ]:      27141 :   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                 :      27140 :   finfo = type_node_fundamental_info_I (pnode);
     775                 :            :   /* ensure flat derivability */
     776         [ -  + ]:      27140 :   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         [ +  + ]:      27140 :   if (parent_type != NODE_FUNDAMENTAL_TYPE (pnode) &&
     785         [ -  + ]:       4188 :       !(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                 :      27140 :   return TRUE;
     794                 :            : }
     795                 :            : 
     796                 :            : static gboolean
     797                 :      20550 : check_collect_format_I (const gchar *collect_format)
     798                 :            : {
     799                 :      20550 :   const gchar *p = collect_format;
     800                 :      20550 :   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         [ +  + ]:      41100 :   while (*p)
     805         [ -  + ]:      20550 :     if (!strchr (valid_format, *p++))
     806                 :          0 :       return FALSE;
     807                 :      20550 :   return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
     808                 :            : }
     809                 :            : 
     810                 :            : static gboolean
     811                 :      36794 : check_value_table_I (const gchar           *type_name,
     812                 :            :                      const GTypeValueTable *value_table)
     813                 :            : {
     814         [ +  + ]:      36794 :   if (!value_table)
     815                 :      26515 :     return FALSE;
     816         [ +  + ]:      10279 :   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                 :      10275 :       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         [ -  + ]:      10275 :       if (!value_table->value_copy)
     836                 :            :         {
     837                 :          0 :           g_critical ("missing 'value_copy()' for type '%s'", type_name);
     838                 :          0 :           return FALSE;
     839                 :            :         }
     840   [ -  +  -  - ]:      10275 :       if ((value_table->collect_format || value_table->collect_value) &&
     841   [ +  -  -  + ]:      10275 :           (!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   [ +  -  -  + ]:      10275 :       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   [ -  +  -  - ]:      10275 :       if ((value_table->lcopy_format || value_table->lcopy_value) &&
     855   [ +  -  -  + ]:      10275 :           (!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   [ +  -  -  + ]:      10275 :       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                 :      10275 :   return TRUE;
     870                 :            : }
     871                 :            : 
     872                 :            : static gboolean
     873                 :      36794 : check_type_info_I (TypeNode        *pnode,
     874                 :            :                    GType            ftype,
     875                 :            :                    const gchar     *type_name,
     876                 :            :                    const GTypeInfo *info)
     877                 :            : {
     878                 :      36794 :   GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (lookup_type_node_I (ftype));
     879                 :      36794 :   gboolean is_interface = ftype == G_TYPE_INTERFACE;
     880                 :            :   
     881                 :      36794 :   g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX && !(ftype & TYPE_ID_MASK));
     882                 :            :   
     883                 :            :   /* check instance members */
     884         [ +  + ]:      36794 :   if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
     885   [ +  -  -  + ]:      15236 :       (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   [ +  +  +  + ]:      36794 :   if (!((finfo->type_flags & G_TYPE_FLAG_CLASSED) || is_interface) &&
     898   [ +  -  +  -  :       9262 :       (info->class_init || info->class_finalize || info->class_data ||
                   +  - ]
     899   [ +  -  +  -  :       9262 :        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   [ +  +  -  + ]:      36794 :   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         [ +  + ]:      36794 :   if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
     919                 :            :     {
     920         [ -  + ]:      24301 :       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   [ +  +  -  + ]:      24301 :       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         [ +  + ]:      36794 :   if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
     937                 :            :     {
     938         [ -  + ]:      21558 :       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   [ +  +  -  + ]:      21558 :       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                 :      36794 :   return TRUE;
     955                 :            : }
     956                 :            : 
     957                 :            : static TypeNode*
     958                 :       4735 : find_conforming_child_type_L (TypeNode *pnode,
     959                 :            :                               TypeNode *iface)
     960                 :            : {
     961                 :       4735 :   TypeNode *node = NULL;
     962                 :            :   guint i;
     963                 :            :   
     964         [ -  + ]:       4735 :   if (type_lookup_iface_entry_L (pnode, iface))
     965                 :          0 :     return pnode;
     966                 :            :   
     967   [ -  +  -  - ]:       4735 :   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                 :       4735 :   return node;
     971                 :            : }
     972                 :            : 
     973                 :            : static gboolean
     974                 :       5761 : check_add_interface_L (GType instance_type,
     975                 :            :                        GType iface_type)
     976                 :            : {
     977                 :       5761 :   TypeNode *node = lookup_type_node_I (instance_type);
     978                 :       5761 :   TypeNode *iface = lookup_type_node_I (iface_type);
     979                 :            :   IFaceEntry *entry;
     980                 :            :   TypeNode *tnode;
     981                 :            :   GType *prerequisites;
     982                 :            :   guint i;
     983                 :            : 
     984                 :            :   
     985   [ +  -  -  + ]:       5761 :   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   [ +  -  -  + ]:       5761 :   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   [ +  +  -  + ]:       5761 :   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                 :       5761 :   tnode = lookup_type_node_I (NODE_PARENT_TYPE (iface));
    1005   [ -  +  -  - ]:       5761 :   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                 :       5761 :   entry = type_lookup_iface_entry_L (node, iface);
    1016   [ +  +  +  -  :       5761 :   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                 :       1026 :       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                 :       4735 :   tnode = find_conforming_child_type_L (node, iface);  /* tnode is_a node */
    1028         [ -  + ]:       4735 :   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                 :       4735 :   prerequisites = IFACE_NODE_PREREQUISITES (iface);
    1037         [ +  + ]:      10521 :   for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
    1038                 :            :     {
    1039                 :       5786 :       tnode = lookup_type_node_I (prerequisites[i]);
    1040         [ -  + ]:       5786 :       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                 :       4735 :   return TRUE;
    1050                 :            : }
    1051                 :            : 
    1052                 :            : static gboolean
    1053                 :       5761 : check_interface_info_I (TypeNode             *iface,
    1054                 :            :                         GType                 instance_type,
    1055                 :            :                         const GInterfaceInfo *info)
    1056                 :            : {
    1057   [ +  -  +  +  :       5761 :   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                 :       5761 :   return TRUE;
    1066                 :            : }
    1067                 :            : 
    1068                 :            : /* --- type info (type node data) --- */
    1069                 :            : static void
    1070                 :      37302 : type_data_make_W (TypeNode              *node,
    1071                 :            :                   const GTypeInfo       *info,
    1072                 :            :                   const GTypeValueTable *value_table)
    1073                 :            : {
    1074                 :            :   TypeData *data;
    1075                 :      37302 :   GTypeValueTable *vtable = NULL;
    1076                 :      37302 :   guint vtable_size = 0;
    1077                 :            :   
    1078                 :      37302 :   g_assert (node->data == NULL && info != NULL);
    1079                 :            :   
    1080         [ +  + ]:      37302 :   if (!value_table)
    1081                 :            :     {
    1082                 :      27027 :       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
    1083                 :            :       
    1084         [ +  + ]:      27027 :       if (pnode)
    1085                 :      26009 :         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                 :       1018 :           value_table = &zero_vtable;
    1092                 :            :         }
    1093                 :            :     }
    1094         [ +  + ]:      37302 :   if (value_table)
    1095                 :            :     {
    1096                 :            :       /* need to setup vtable_size since we have to allocate it with data in one chunk */
    1097                 :      11293 :       vtable_size = sizeof (GTypeValueTable);
    1098         [ +  + ]:      11293 :       if (value_table->collect_format)
    1099                 :      10275 :         vtable_size += strlen (value_table->collect_format);
    1100         [ +  + ]:      11293 :       if (value_table->lcopy_format)
    1101                 :      10275 :         vtable_size += strlen (value_table->lcopy_format);
    1102                 :      11293 :       vtable_size += 2;
    1103                 :            :     }
    1104                 :            :    
    1105         [ +  + ]:      37302 :   if (node->is_instantiatable) /* careful, is_instantiatable is also is_classed */
    1106                 :            :     {
    1107                 :      21558 :       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
    1108                 :            : 
    1109                 :      21558 :       data = g_malloc0 (sizeof (InstanceData) + vtable_size);
    1110         [ +  + ]:      21558 :       if (vtable_size)
    1111                 :       1016 :         vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
    1112                 :      21558 :       data->instance.class_size = info->class_size;
    1113                 :      21558 :       data->instance.class_init_base = info->base_init;
    1114                 :      21558 :       data->instance.class_finalize_base = info->base_finalize;
    1115                 :      21558 :       data->instance.class_init = info->class_init;
    1116                 :      21558 :       data->instance.class_finalize = info->class_finalize;
    1117                 :      21558 :       data->instance.class_data = info->class_data;
    1118                 :      21558 :       data->instance.class = NULL;
    1119                 :      21558 :       data->instance.init_state = UNINITIALIZED;
    1120                 :      21558 :       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                 :      21558 :       data->instance.private_size = 0;
    1125                 :      21558 :       data->instance.class_private_size = 0;
    1126         [ +  + ]:      21558 :       if (pnode)
    1127                 :      20542 :         data->instance.class_private_size = pnode->data->instance.class_private_size;
    1128                 :      21558 :       data->instance.instance_init = info->instance_init;
    1129                 :            :     }
    1130         [ +  + ]:      15744 :   else if (node->is_classed) /* only classed */
    1131                 :            :     {
    1132                 :       2743 :       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
    1133                 :            : 
    1134                 :       2743 :       data = g_malloc0 (sizeof (ClassData) + vtable_size);
    1135         [ +  + ]:       2743 :       if (vtable_size)
    1136                 :       1016 :         vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
    1137                 :       2743 :       data->class.class_size = info->class_size;
    1138                 :       2743 :       data->class.class_init_base = info->base_init;
    1139                 :       2743 :       data->class.class_finalize_base = info->base_finalize;
    1140                 :       2743 :       data->class.class_init = info->class_init;
    1141                 :       2743 :       data->class.class_finalize = info->class_finalize;
    1142                 :       2743 :       data->class.class_data = info->class_data;
    1143                 :       2743 :       data->class.class = NULL;
    1144                 :       2743 :       data->class.class_private_size = 0;
    1145         [ +  + ]:       2743 :       if (pnode)
    1146                 :       1727 :         data->class.class_private_size = pnode->data->class.class_private_size;
    1147                 :       2743 :       data->class.init_state = UNINITIALIZED;
    1148                 :            :     }
    1149         [ +  + ]:      13001 :   else if (NODE_IS_IFACE (node))
    1150                 :            :     {
    1151                 :       3739 :       data = g_malloc0 (sizeof (IFaceData) + vtable_size);
    1152         [ +  + ]:       3739 :       if (vtable_size)
    1153                 :        508 :         vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
    1154                 :       3739 :       data->iface.vtable_size = info->class_size;
    1155                 :       3739 :       data->iface.vtable_init_base = info->base_init;
    1156                 :       3739 :       data->iface.vtable_finalize_base = info->base_finalize;
    1157                 :       3739 :       data->iface.dflt_init = info->class_init;
    1158                 :       3739 :       data->iface.dflt_finalize = info->class_finalize;
    1159                 :       3739 :       data->iface.dflt_data = info->class_data;
    1160                 :       3739 :       data->iface.dflt_vtable = NULL;
    1161                 :            :     }
    1162         [ +  + ]:       9262 :   else if (NODE_IS_BOXED (node))
    1163                 :            :     {
    1164                 :       1639 :       data = g_malloc0 (sizeof (BoxedData) + vtable_size);
    1165         [ +  - ]:       1639 :       if (vtable_size)
    1166                 :       1639 :         vtable = G_STRUCT_MEMBER_P (data, sizeof (BoxedData));
    1167                 :            :     }
    1168                 :            :   else
    1169                 :            :     {
    1170                 :       7623 :       data = g_malloc0 (sizeof (CommonData) + vtable_size);
    1171         [ +  + ]:       7623 :       if (vtable_size)
    1172                 :       7114 :         vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
    1173                 :            :     }
    1174                 :            :   
    1175                 :      37302 :   node->data = data;
    1176                 :            :   
    1177         [ +  + ]:      37302 :   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                 :      11293 :       *vtable = *value_table;
    1186                 :      11293 :       p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable));
    1187                 :      11293 :       p[0] = 0;
    1188                 :      11293 :       vtable->collect_format = p;
    1189         [ +  + ]:      11293 :       if (value_table->collect_format)
    1190                 :            :         {
    1191                 :      10275 :           strcat (p, value_table->collect_format);
    1192                 :      10275 :           p += strlen (value_table->collect_format);
    1193                 :            :         }
    1194                 :      11293 :       p++;
    1195                 :      11293 :       p[0] = 0;
    1196                 :      11293 :       vtable->lcopy_format = p;
    1197         [ +  + ]:      11293 :       if (value_table->lcopy_format)
    1198                 :      10275 :         strcat  (p, value_table->lcopy_format);
    1199                 :            :     }
    1200                 :      37302 :   node->data->common.value_table = vtable;
    1201         [ +  + ]:      70355 :   node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL &&
    1202                 :      33053 :                                  !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) &
    1203         [ +  + ]:      33053 :                                    GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))));
    1204                 :            :   
    1205                 :      37302 :   g_assert (node->data->common.value_table != NULL); /* paranoid */
    1206                 :            : 
    1207                 :      37302 :   g_atomic_int_set ((int *) &node->ref_count, 1);
    1208                 :      37302 : }
    1209                 :            : 
    1210                 :            : static inline void
    1211                 :      27150 : type_data_ref_Wm (TypeNode *node)
    1212                 :            : {
    1213         [ +  + ]:      27150 :   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                 :      27146 :       g_assert (NODE_REFCOUNT (node) > 0);
    1246                 :            :       
    1247                 :      27146 :       g_atomic_int_inc ((int *) &node->ref_count);
    1248                 :            :     }
    1249                 :      27150 : }
    1250                 :            : 
    1251                 :            : static inline gboolean
    1252                 :    5684458 : type_data_ref_U (TypeNode *node)
    1253                 :            : {
    1254                 :            :   guint current;
    1255                 :            : 
    1256                 :            :   do {
    1257                 :    5926233 :     current = NODE_REFCOUNT (node);
    1258                 :            : 
    1259         [ +  + ]:    5926233 :     if (current < 1)
    1260                 :          3 :       return FALSE;
    1261         [ +  + ]:    5926230 :   } while (!g_atomic_int_compare_and_exchange ((int *) &node->ref_count, current, current + 1));
    1262                 :            : 
    1263                 :    5684455 :   return TRUE;
    1264                 :            : }
    1265                 :            : 
    1266                 :            : static gboolean
    1267                 :       5544 : iface_node_has_available_offset_L (TypeNode *iface_node,
    1268                 :            :                                    gsize offset,
    1269                 :            :                                    int for_index)
    1270                 :            : {
    1271                 :            :   guint8 *offsets;
    1272                 :            : 
    1273                 :       5544 :   offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->_prot.offsets, guint8);
    1274         [ +  + ]:       5544 :   if (offsets == NULL)
    1275                 :       2429 :     return TRUE;
    1276                 :            : 
    1277         [ +  + ]:       3115 :   if (G_ATOMIC_ARRAY_DATA_SIZE (offsets) <= offset)
    1278                 :        517 :     return TRUE;
    1279                 :            : 
    1280         [ +  + ]:       2598 :   if (offsets[offset] == 0 ||
    1281         [ +  + ]:       2497 :       offsets[offset] == for_index+1)
    1282                 :       2067 :     return TRUE;
    1283                 :            : 
    1284                 :        531 :   return FALSE;
    1285                 :            : }
    1286                 :            : 
    1287                 :            : static gsize
    1288                 :        265 : 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                 :        265 :   n_entries = IFACE_ENTRIES_N_ENTRIES (entries);
    1297                 :        265 :   offset = 0;
    1298                 :            :   do
    1299                 :            :     {
    1300         [ +  + ]:       1074 :       for (i = 0; i < n_entries; i++)
    1301                 :            :         {
    1302                 :        809 :           entry = &entries->entry[i];
    1303                 :        809 :           iface_node = lookup_type_node_I (entry->iface_type);
    1304                 :            : 
    1305         [ +  + ]:        809 :           if (!iface_node_has_available_offset_L (iface_node, offset, i))
    1306                 :            :             {
    1307                 :        266 :               offset++;
    1308                 :        266 :               break;
    1309                 :            :             }
    1310                 :            :         }
    1311                 :            :     }
    1312         [ +  + ]:        531 :   while (i != n_entries);
    1313                 :            : 
    1314                 :        265 :   return offset;
    1315                 :            : }
    1316                 :            : 
    1317                 :            : static void
    1318                 :       4874 : 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                 :       4874 :   old_offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->_prot.offsets, guint8);
    1327         [ +  + ]:       4874 :   if (old_offsets == NULL)
    1328                 :       2429 :     old_size = 0;
    1329                 :            :   else
    1330                 :            :     {
    1331                 :       2445 :       old_size = G_ATOMIC_ARRAY_DATA_SIZE (old_offsets);
    1332         [ +  + ]:       2445 :       if (offset < old_size &&
    1333         [ +  + ]:       1928 :           old_offsets[offset] == index + 1)
    1334                 :       1827 :         return; /* Already set to this index, return */
    1335                 :            :     }
    1336                 :       3047 :   new_size = MAX (old_size, offset + 1);
    1337                 :            : 
    1338                 :       3047 :   offsets = _g_atomic_array_copy (&iface_node->_prot.offsets,
    1339                 :            :                                   0, new_size - old_size);
    1340                 :            : 
    1341                 :            :   /* Mark new area as unused */
    1342         [ +  + ]:       6140 :   for (i = old_size; i < new_size; i++)
    1343                 :       3093 :     offsets[i] = 0;
    1344                 :            : 
    1345                 :       3047 :   offsets[offset] = index + 1;
    1346                 :            : 
    1347                 :       3047 :   _g_atomic_array_update (&iface_node->_prot.offsets, offsets);
    1348                 :            : }
    1349                 :            : 
    1350                 :            : static void
    1351                 :       5761 : 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                 :       5761 :   g_assert (node->is_instantiatable);
    1362                 :            : 
    1363                 :       5761 :   entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node);
    1364         [ +  + ]:       5761 :   if (entries != NULL)
    1365                 :            :     {
    1366                 :       2736 :       num_entries = IFACE_ENTRIES_N_ENTRIES (entries);
    1367                 :            : 
    1368                 :       2736 :       g_assert (num_entries < MAX_N_INTERFACES);
    1369                 :            : 
    1370         [ +  + ]:       5049 :       for (i = 0; i < num_entries; i++)
    1371                 :            :         {
    1372                 :       3339 :           entry = &entries->entry[i];
    1373         [ +  + ]:       3339 :           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         [ +  - ]:       1026 :               if (!parent_entry)
    1384                 :       1026 :                 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                 :       1026 :               return;
    1392                 :            :             }
    1393                 :            :         }
    1394                 :            :     }
    1395                 :            : 
    1396                 :       4735 :   entries = _g_atomic_array_copy (CLASSED_NODE_IFACES_ENTRIES (node),
    1397                 :            :                                   IFACE_ENTRIES_HEADER_SIZE,
    1398                 :            :                                   sizeof (IFaceEntry));
    1399                 :       4735 :   num_entries = IFACE_ENTRIES_N_ENTRIES (entries);
    1400                 :       4735 :   i = num_entries - 1;
    1401         [ +  + ]:       4735 :   if (i == 0)
    1402                 :       3025 :     entries->offset_index = 0;
    1403                 :       4735 :   entries->entry[i].iface_type = iface_type;
    1404                 :       4735 :   entries->entry[i].vtable = NULL;
    1405                 :       4735 :   entries->entry[i].init_state = UNINITIALIZED;
    1406                 :            : 
    1407         [ -  + ]:       4735 :   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                 :       4735 :   iface_node = lookup_type_node_I (iface_type);
    1418                 :            : 
    1419         [ +  + ]:       4735 :   if (iface_node_has_available_offset_L (iface_node,
    1420                 :            :                                          entries->offset_index,
    1421                 :            :                                          i))
    1422                 :            :     {
    1423                 :       4470 :       iface_node_set_offset_L (iface_node,
    1424                 :            :                                entries->offset_index, i);
    1425                 :            :     }
    1426                 :            :   else
    1427                 :            :    {
    1428                 :        265 :       entries->offset_index =
    1429                 :        265 :         find_free_iface_offset_L (entries);
    1430         [ +  + ]:        669 :       for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (entries); j++)
    1431                 :            :         {
    1432                 :        404 :           entry = &entries->entry[j];
    1433                 :            :           iface_node =
    1434                 :        404 :             lookup_type_node_I (entry->iface_type);
    1435                 :        404 :           iface_node_set_offset_L (iface_node,
    1436                 :            :                                    entries->offset_index, j);
    1437                 :            :         }
    1438                 :            :     }
    1439                 :            : 
    1440                 :       4735 :   _g_atomic_array_update (CLASSED_NODE_IFACES_ENTRIES (node), entries);
    1441                 :            : 
    1442         [ -  + ]:       4735 :   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                 :       5761 : type_add_interface_Wm (TypeNode             *node,
    1451                 :            :                        TypeNode             *iface,
    1452                 :            :                        const GInterfaceInfo *info,
    1453                 :            :                        GTypePlugin          *plugin)
    1454                 :            : {
    1455                 :       5761 :   IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
    1456                 :            :   IFaceEntry *entry;
    1457                 :            :   guint i;
    1458                 :            : 
    1459                 :       5761 :   g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin)));
    1460                 :            :   
    1461                 :       5761 :   iholder->next = iface_node_get_holders_L (iface);
    1462                 :       5761 :   iface_node_set_holders_W (iface, iholder);
    1463                 :       5761 :   iholder->instance_type = NODE_TYPE (node);
    1464         [ +  + ]:       5761 :   iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL;
    1465                 :       5761 :   iholder->plugin = plugin;
    1466                 :            : 
    1467                 :            :   /* create an iface entry for this type */
    1468                 :       5761 :   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         [ +  + ]:       5761 :   if (node->data)
    1474                 :            :     {
    1475                 :       5759 :       InitState class_state = g_atomic_int_get (&node->data->class.init_state);
    1476                 :            :       
    1477         [ -  + ]:       5759 :       if (class_state >= BASE_IFACE_INIT)
    1478                 :          0 :         type_iface_vtable_base_init_Wm (iface, node);
    1479                 :            :       
    1480         [ -  + ]:       5759 :       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                 :       5761 :   entry = type_lookup_iface_entry_L (node, iface);
    1486         [ -  + ]:       5761 :   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                 :       5761 : }
    1489                 :            : 
    1490                 :            : static void
    1491                 :       3925 : type_iface_add_prerequisite_W (TypeNode *iface,
    1492                 :            :                                TypeNode *prerequisite_node)
    1493                 :            : {
    1494                 :       3925 :   GType prerequisite_type = NODE_TYPE (prerequisite_node);
    1495                 :            :   GType *prerequisites, *dependants;
    1496                 :            :   guint n_dependants, i;
    1497                 :            :   
    1498                 :       3925 :   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                 :       3925 :   prerequisites = IFACE_NODE_PREREQUISITES (iface);
    1503         [ +  + ]:       4416 :   for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
    1504         [ +  + ]:       1228 :     if (prerequisites[i] == prerequisite_type)
    1505                 :        461 :       return;                   /* we already have that prerequisiste */
    1506         [ +  + ]:        767 :     else if (prerequisites[i] > prerequisite_type)
    1507                 :        276 :       break;
    1508                 :       3464 :   IFACE_NODE_N_PREREQUISITES (iface) += 1;
    1509                 :       3464 :   IFACE_NODE_PREREQUISITES (iface) = g_renew (GType,
    1510                 :            :                                               IFACE_NODE_PREREQUISITES (iface),
    1511                 :            :                                               IFACE_NODE_N_PREREQUISITES (iface));
    1512                 :       3464 :   prerequisites = IFACE_NODE_PREREQUISITES (iface);
    1513                 :       3464 :   memmove (prerequisites + i + 1, prerequisites + i,
    1514                 :       3464 :            sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1));
    1515                 :       3464 :   prerequisites[i] = prerequisite_type;
    1516                 :            :   
    1517                 :            :   /* we want to get notified when prerequisites get added to prerequisite_node */
    1518         [ +  + ]:       3464 :   if (NODE_IS_IFACE (prerequisite_node))
    1519                 :            :     {
    1520                 :        485 :       dependants = iface_node_get_dependants_array_L (prerequisite_node);
    1521         [ +  + ]:        485 :       n_dependants = dependants ? dependants[0] : 0;
    1522                 :        485 :       n_dependants += 1;
    1523                 :        485 :       dependants = g_renew (GType, dependants, n_dependants + 1);
    1524                 :        485 :       dependants[n_dependants] = NODE_TYPE (iface);
    1525                 :        485 :       dependants[0] = n_dependants;
    1526                 :        485 :       iface_node_set_dependants_array_W (prerequisite_node, dependants);
    1527                 :            :     }
    1528                 :            :   
    1529                 :            :   /* we need to notify all dependants */
    1530                 :       3464 :   dependants = iface_node_get_dependants_array_L (iface);
    1531         [ -  + ]:       3464 :   n_dependants = dependants ? dependants[0] : 0;
    1532         [ -  + ]:       3464 :   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                 :       3166 : g_type_interface_add_prerequisite (GType interface_type,
    1549                 :            :                                    GType prerequisite_type)
    1550                 :            : {
    1551                 :            :   TypeNode *iface, *prerequisite_node;
    1552                 :            :   IFaceHolder *holders;
    1553                 :            :   
    1554                 :       3166 :   g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type));      /* G_TYPE_IS_INTERFACE() is an external call: _U */
    1555                 :       3166 :   g_return_if_fail (!g_type_is_a (interface_type, prerequisite_type));
    1556                 :       3166 :   g_return_if_fail (!g_type_is_a (prerequisite_type, interface_type));
    1557                 :            :   
    1558                 :       3166 :   iface = lookup_type_node_I (interface_type);
    1559                 :       3166 :   prerequisite_node = lookup_type_node_I (prerequisite_type);
    1560   [ +  -  +  -  :       3166 :   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                 :       3166 :   G_WRITE_LOCK (&type_rw_lock);
    1568                 :       3166 :   holders = iface_node_get_holders_L (iface);
    1569         [ -  + ]:       3166 :   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         [ +  + ]:       3166 :   if (prerequisite_node->is_instantiatable)
    1579                 :            :     {
    1580                 :            :       guint i;
    1581                 :            :       
    1582                 :            :       /* can have at most one publicly installable instantiatable prerequisite */
    1583         [ -  + ]:       2684 :       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         [ +  + ]:       5642 :       for (i = 0; i < prerequisite_node->n_supers + 1u; i++)
    1599                 :       2958 :         type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisite_node->supers[i]));
    1600                 :       2684 :       G_WRITE_UNLOCK (&type_rw_lock);
    1601                 :            :     }
    1602         [ +  - ]:        482 :   else if (NODE_IS_IFACE (prerequisite_node))
    1603                 :            :     {
    1604                 :            :       GType *prerequisites;
    1605                 :            :       guint i;
    1606                 :            :       
    1607                 :        482 :       prerequisites = IFACE_NODE_PREREQUISITES (prerequisite_node);
    1608         [ +  + ]:        967 :       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (prerequisite_node); i++)
    1609                 :        485 :         type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisites[i]));
    1610                 :        482 :       type_iface_add_prerequisite_W (iface, prerequisite_node);
    1611                 :        482 :       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                 :          1 : g_type_interface_prerequisites (GType  interface_type,
    1638                 :            :                                 guint *n_prerequisites)
    1639                 :            : {
    1640                 :            :   TypeNode *iface;
    1641                 :            :   
    1642                 :          1 :   g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
    1643                 :            : 
    1644                 :          1 :   iface = lookup_type_node_I (interface_type);
    1645         [ +  - ]:          1 :   if (iface)
    1646                 :            :     {
    1647                 :            :       GType *types;
    1648                 :          1 :       TypeNode *inode = NULL;
    1649                 :          1 :       guint i, n = 0;
    1650                 :            :       
    1651                 :          1 :       G_READ_LOCK (&type_rw_lock);
    1652                 :          1 :       types = g_new0 (GType, IFACE_NODE_N_PREREQUISITES (iface) + 1);
    1653         [ +  + ]:          3 :       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
    1654                 :            :         {
    1655                 :          2 :           GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
    1656                 :          2 :           TypeNode *node = lookup_type_node_I (prerequisite);
    1657         [ +  + ]:          2 :           if (node->is_instantiatable)
    1658                 :            :             {
    1659   [ -  +  -  - ]:          1 :               if (!inode || type_node_is_a_L (node, inode))
    1660                 :          1 :                 inode = node;
    1661                 :            :             }
    1662                 :            :           else
    1663                 :          1 :             types[n++] = NODE_TYPE (node);
    1664                 :            :         }
    1665         [ +  - ]:          1 :       if (inode)
    1666                 :          1 :         types[n++] = NODE_TYPE (inode);
    1667                 :            :       
    1668         [ +  - ]:          1 :       if (n_prerequisites)
    1669                 :          1 :         *n_prerequisites = n;
    1670                 :          1 :       G_READ_UNLOCK (&type_rw_lock);
    1671                 :            :       
    1672                 :          1 :       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                 :         53 : g_type_interface_instantiatable_prerequisite (GType interface_type)
    1700                 :            : {
    1701                 :         53 :   TypeNode *inode = NULL;
    1702                 :            :   TypeNode *iface;
    1703                 :            :   guint i;
    1704                 :            : 
    1705                 :         53 :   g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), G_TYPE_INVALID);
    1706                 :            : 
    1707                 :         53 :   iface = lookup_type_node_I (interface_type);
    1708         [ -  + ]:         53 :   if (iface == NULL)
    1709                 :          0 :     return G_TYPE_INVALID;
    1710                 :            : 
    1711                 :         53 :   G_READ_LOCK (&type_rw_lock);
    1712                 :            : 
    1713         [ +  + ]:        110 :   for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
    1714                 :            :     {
    1715                 :         57 :       GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
    1716                 :         57 :       TypeNode *node = lookup_type_node_I (prerequisite);
    1717         [ +  + ]:         57 :       if (node->is_instantiatable)
    1718                 :            :         {
    1719   [ +  +  +  - ]:         52 :           if (!inode || type_node_is_a_L (node, inode))
    1720                 :         52 :             inode = node;
    1721                 :            :         }
    1722                 :            :     }
    1723                 :            : 
    1724                 :         53 :   G_READ_UNLOCK (&type_rw_lock);
    1725                 :            : 
    1726         [ +  + ]:         53 :   if (inode)
    1727                 :         51 :     return NODE_TYPE (inode);
    1728                 :            :   else
    1729                 :          2 :     return G_TYPE_INVALID;
    1730                 :            : }
    1731                 :            : 
    1732                 :            : static IFaceHolder*
    1733                 :       6996 : type_iface_peek_holder_L (TypeNode *iface,
    1734                 :            :                           GType     instance_type)
    1735                 :            : {
    1736                 :            :   IFaceHolder *iholder;
    1737                 :            :   
    1738                 :       6996 :   g_assert (NODE_IS_IFACE (iface));
    1739                 :            :   
    1740                 :       6996 :   iholder = iface_node_get_holders_L (iface);
    1741   [ +  +  +  + ]:      11863 :   while (iholder && iholder->instance_type != instance_type)
    1742                 :       4867 :     iholder = iholder->next;
    1743                 :       6996 :   return iholder;
    1744                 :            : }
    1745                 :            : 
    1746                 :            : static IFaceHolder*
    1747                 :       3128 : type_iface_retrieve_holder_info_Wm (TypeNode *iface,
    1748                 :            :                                     GType     instance_type,
    1749                 :            :                                     gboolean  need_info)
    1750                 :            : {
    1751                 :       3128 :   IFaceHolder *iholder = type_iface_peek_holder_L (iface, instance_type);
    1752                 :            :   
    1753   [ +  +  +  +  :       3128 :   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                 :       3128 :   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                 :    4979267 : 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                 :    4979267 :   node = lookup_type_node_I (type);
    1879   [ +  #  #  + ]:    4979137 :   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   [ -  +  -  - ]:    4979209 :   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         [ +  + ]:    4979209 :   if (G_UNLIKELY (G_TYPE_IS_DEPRECATED (type)))
    1891                 :            :     {
    1892                 :          2 :       maybe_issue_deprecation_warning (type);
    1893                 :            :     }
    1894                 :            : 
    1895                 :    4979091 :   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                 :    4979732 :   private_size = node->data->instance.private_size;
    1915                 :    4979732 :   ivar_size = node->data->instance.instance_size;
    1916                 :            : 
    1917                 :            : #ifdef ENABLE_VALGRIND
    1918   [ +  +  -  + ]:    4979732 :   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                 :    4979732 :     allocated = g_malloc0 (private_size + ivar_size);
    1934                 :            : 
    1935                 :    4979738 :   instance = (GTypeInstance *) (allocated + private_size);
    1936                 :            : 
    1937         [ +  + ]:   11789503 :   for (i = node->n_supers; i > 0; i--)
    1938                 :            :     {
    1939                 :            :       TypeNode *pnode;
    1940                 :            :       
    1941                 :    6810331 :       pnode = lookup_type_node_I (node->supers[i]);
    1942         [ +  + ]:    6810164 :       if (pnode->data->instance.instance_init)
    1943                 :            :         {
    1944                 :    6810148 :           instance->g_class = pnode->data->instance.class;
    1945                 :    6810148 :           pnode->data->instance.instance_init (instance, class);
    1946                 :            :         }
    1947                 :            :     }
    1948                 :            : 
    1949                 :    4979172 :   instance->g_class = class;
    1950         [ +  + ]:    4979172 :   if (node->data->instance.instance_init)
    1951                 :    4976930 :     node->data->instance.instance_init (instance, class);
    1952                 :            : 
    1953                 :            : #ifdef  G_ENABLE_DEBUG
    1954         [ -  + ]:    4979112 :   IF_DEBUG (INSTANCE_COUNT)
    1955                 :            :     {
    1956                 :          0 :       g_atomic_int_inc ((int *) &node->instance_count);
    1957                 :            :     }
    1958                 :            : #endif
    1959                 :            : 
    1960                 :    4979112 :   TRACE(GOBJECT_OBJECT_NEW(instance, type));
    1961                 :            : 
    1962                 :    4979247 :   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                 :    4966140 : 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                 :    4966140 :   g_return_if_fail (instance != NULL && instance->g_class != NULL);
    1985                 :            :   
    1986                 :    4966166 :   class = instance->g_class;
    1987                 :    4966166 :   node = lookup_type_node_I (class->g_type);
    1988   [ +  #  +  +  :    4966134 :   if (G_UNLIKELY (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class))
             +  #  +  + ]
    1989                 :            :     {
    1990                 :          1 :       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   [ -  +  -  - ]:    4966133 :   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                 :    4966133 :   instance->g_class = NULL;
    2003                 :    4966133 :   private_size = node->data->instance.private_size;
    2004                 :    4966133 :   ivar_size = node->data->instance.instance_size;
    2005                 :    4966133 :   allocated = ((gchar *) instance) - private_size;
    2006                 :            : 
    2007                 :            : #ifdef G_ENABLE_DEBUG
    2008                 :    4966133 :   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   [ +  +  -  + ]:    4966133 :   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                 :    4966133 :     g_free_sized (allocated, private_size + ivar_size);
    2031                 :            : 
    2032                 :            : #ifdef  G_ENABLE_DEBUG
    2033         [ -  + ]:    4966137 :   IF_DEBUG (INSTANCE_COUNT)
    2034                 :            :     {
    2035                 :          0 :       g_atomic_int_add ((int *) &node->instance_count, -1);
    2036                 :            :     }
    2037                 :            : #endif
    2038                 :            : 
    2039                 :    4966137 :   g_type_class_unref (class);
    2040                 :            : }
    2041                 :            : 
    2042                 :            : static void
    2043                 :       2846 : type_iface_ensure_dflt_vtable_Wm (TypeNode *iface)
    2044                 :            : {
    2045                 :       2846 :   g_assert (iface->data);
    2046                 :            : 
    2047         [ +  + ]:       2846 :   if (!iface->data->iface.dflt_vtable)
    2048                 :            :     {
    2049                 :       1587 :       GTypeInterface *vtable = g_malloc0 (iface->data->iface.vtable_size);
    2050                 :       1587 :       iface->data->iface.dflt_vtable = vtable;
    2051                 :       1587 :       vtable->g_type = NODE_TYPE (iface);
    2052                 :       1587 :       vtable->g_instance_type = 0;
    2053         [ +  + ]:       1587 :       if (iface->data->iface.vtable_init_base ||
    2054         [ +  + ]:       1585 :           iface->data->iface.dflt_init)
    2055                 :            :         {
    2056                 :       1570 :           G_WRITE_UNLOCK (&type_rw_lock);
    2057         [ +  + ]:       1570 :           if (iface->data->iface.vtable_init_base)
    2058                 :          2 :             iface->data->iface.vtable_init_base (vtable);
    2059         [ +  + ]:       1570 :           if (iface->data->iface.dflt_init)
    2060                 :       1569 :             iface->data->iface.dflt_init (vtable, (gpointer) iface->data->iface.dflt_data);
    2061                 :       1570 :           G_WRITE_LOCK (&type_rw_lock);
    2062                 :            :         }
    2063                 :            :     }
    2064                 :       2846 : }
    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                 :       3128 : type_iface_vtable_base_init_Wm (TypeNode *iface,
    2077                 :            :                                 TypeNode *node)
    2078                 :            : {
    2079                 :            :   IFaceEntry *entry;
    2080                 :            :   IFaceHolder *iholder;
    2081                 :       3128 :   GTypeInterface *vtable = NULL;
    2082                 :            :   TypeNode *pnode;
    2083                 :            :   
    2084                 :            :   /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
    2085                 :       3128 :   iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), TRUE);
    2086         [ +  + ]:       3128 :   if (!iholder)
    2087                 :        286 :     return FALSE;       /* we don't modify write lock upon FALSE */
    2088                 :            : 
    2089                 :       2842 :   type_iface_ensure_dflt_vtable_Wm (iface);
    2090                 :            : 
    2091                 :       2842 :   entry = type_lookup_iface_entry_L (node, iface);
    2092                 :            : 
    2093                 :       2842 :   g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
    2094                 :            :   
    2095                 :       2842 :   entry->init_state = IFACE_INIT;
    2096                 :            : 
    2097                 :       2842 :   pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
    2098         [ +  - ]:       2842 :   if (pnode)    /* want to copy over parent iface contents */
    2099                 :            :     {
    2100                 :       2842 :       IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
    2101                 :            :       
    2102         [ +  + ]:       2842 :       if (pentry)
    2103                 :        263 :         vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size);
    2104                 :            :     }
    2105         [ +  + ]:       2842 :   if (!vtable)
    2106                 :       2579 :     vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
    2107                 :       2842 :   entry->vtable = vtable;
    2108                 :       2842 :   vtable->g_type = NODE_TYPE (iface);
    2109                 :       2842 :   vtable->g_instance_type = NODE_TYPE (node);
    2110                 :            :   
    2111         [ +  + ]:       2842 :   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                 :       2842 :   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                 :       2842 : type_iface_vtable_iface_init_Wm (TypeNode *iface,
    2128                 :            :                                  TypeNode *node)
    2129                 :            : {
    2130                 :       2842 :   IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
    2131                 :       2842 :   IFaceHolder *iholder = type_iface_peek_holder_L (iface, NODE_TYPE (node));
    2132                 :       2842 :   GTypeInterface *vtable = NULL;
    2133                 :            :   guint i;
    2134                 :            :   
    2135                 :            :   /* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */
    2136                 :       2842 :   g_assert (iface->data && entry && iholder && iholder->info);
    2137                 :       2842 :   g_assert (entry->init_state == IFACE_INIT); /* assert prior base_init() */
    2138                 :            :   
    2139                 :       2842 :   entry->init_state = INITIALIZED;
    2140                 :            :       
    2141                 :       2842 :   vtable = entry->vtable;
    2142                 :            : 
    2143         [ +  + ]:       2842 :   if (iholder->info->interface_init)
    2144                 :            :     {
    2145                 :       2828 :       G_WRITE_UNLOCK (&type_rw_lock);
    2146         [ +  - ]:       2828 :       if (iholder->info->interface_init)
    2147                 :       2828 :         iholder->info->interface_init (vtable, iholder->info->interface_data);
    2148                 :       2828 :       G_WRITE_LOCK (&type_rw_lock);
    2149                 :            :     }
    2150                 :            :   
    2151         [ +  + ]:       5685 :   for (i = 0; i < static_n_iface_check_funcs; i++)
    2152                 :            :     {
    2153                 :       2843 :       GTypeInterfaceCheckFunc check_func = static_iface_check_funcs[i].check_func;
    2154                 :       2843 :       gpointer check_data = static_iface_check_funcs[i].check_data;
    2155                 :            : 
    2156                 :       2843 :       G_WRITE_UNLOCK (&type_rw_lock);
    2157                 :       2843 :       check_func (check_data, (gpointer)vtable);
    2158                 :       2843 :       G_WRITE_LOCK (&type_rw_lock);      
    2159                 :            :     }
    2160                 :       2842 : }
    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                 :      17781 : type_class_init_Wm (TypeNode   *node,
    2199                 :            :                     GTypeClass *pclass)
    2200                 :            : {
    2201                 :      17781 :   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                 :      17781 :   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         [ +  + ]:      17781 :   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                 :      17780 :     class = g_malloc0 (node->data->class.class_size);
    2219                 :      17781 :   node->data->class.class = class;
    2220                 :      17781 :   g_atomic_int_set (&node->data->class.init_state, BASE_CLASS_INIT);
    2221                 :            :   
    2222         [ +  + ]:      17781 :   if (pclass)
    2223                 :            :     {
    2224                 :      16662 :       pnode = lookup_type_node_I (pclass->g_type);
    2225                 :            : 
    2226                 :      16662 :       memcpy (class, pclass, pnode->data->class.class_size);
    2227                 :      16662 :       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         [ +  + ]:      16662 :       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                 :      15215 :           node->data->instance.private_size = pnode->data->instance.private_size;
    2236                 :            :         }
    2237                 :            :     }
    2238                 :      17781 :   class->g_type = NODE_TYPE (node);
    2239                 :            :   
    2240                 :      17781 :   G_WRITE_UNLOCK (&type_rw_lock);
    2241                 :            :   
    2242                 :            :   /* stack all base class initialization functions, so we
    2243                 :            :    * call them in ascending order.
    2244                 :            :    */
    2245         [ +  + ]:      55089 :   for (bnode = node; bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
    2246         [ +  + ]:      37308 :     if (bnode->data->class.class_init_base)
    2247                 :      16027 :       init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
    2248         [ +  + ]:      33808 :   for (slist = init_slist; slist; slist = slist->next)
    2249                 :            :     {
    2250                 :      16027 :       GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
    2251                 :            :       
    2252                 :      16027 :       class_init_base (class);
    2253                 :            :     }
    2254                 :      17781 :   g_slist_free (init_slist);
    2255                 :            :   
    2256                 :      17781 :   G_WRITE_LOCK (&type_rw_lock);
    2257                 :            : 
    2258                 :      17781 :   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                 :      17781 :   pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
    2264                 :            : 
    2265                 :      17781 :   i = 0;
    2266         [ +  + ]:      20909 :   while ((entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node)) != NULL &&
    2267         [ +  + ]:       5107 :           i < IFACE_ENTRIES_N_ENTRIES (entries))
    2268                 :            :     {
    2269                 :       3128 :       entry = &entries->entry[i];
    2270         [ +  - ]:       3128 :       while (i < IFACE_ENTRIES_N_ENTRIES (entries) &&
    2271         [ -  + ]:       3128 :              entry->init_state == IFACE_INIT)
    2272                 :            :         {
    2273                 :          0 :           entry++;
    2274                 :          0 :           i++;
    2275                 :            :         }
    2276                 :            : 
    2277         [ -  + ]:       3128 :       if (i == IFACE_ENTRIES_N_ENTRIES (entries))
    2278                 :          0 :         break;
    2279                 :            : 
    2280         [ +  + ]:       3128 :       if (!type_iface_vtable_base_init_Wm (lookup_type_node_I (entry->iface_type), node))
    2281                 :            :         {
    2282                 :            :           guint j;
    2283                 :        286 :           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                 :        286 :           g_assert (pnode != NULL);
    2289                 :            : 
    2290         [ +  - ]:        286 :           if (pentries)
    2291         [ +  - ]:        369 :             for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (pentries); j++)
    2292                 :            :               {
    2293                 :        369 :                 IFaceEntry *pentry = &pentries->entry[j];
    2294                 :            : 
    2295         [ +  + ]:        369 :                 if (pentry->iface_type == entry->iface_type)
    2296                 :            :                   {
    2297                 :        286 :                     entry->vtable = pentry->vtable;
    2298                 :        286 :                     entry->init_state = INITIALIZED;
    2299                 :        286 :                     break;
    2300                 :            :                   }
    2301                 :            :               }
    2302                 :        286 :           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                 :       3128 :       i++;
    2312                 :            :     }
    2313                 :            :   
    2314                 :      17781 :   g_atomic_int_set (&node->data->class.init_state, CLASS_INIT);
    2315                 :            :   
    2316                 :      17781 :   G_WRITE_UNLOCK (&type_rw_lock);
    2317                 :            : 
    2318         [ +  + ]:      17781 :   if (node->data->class.class_init)
    2319                 :      17473 :     node->data->class.class_init (class, (gpointer) node->data->class.class_data);
    2320                 :            :   
    2321                 :      17781 :   G_WRITE_LOCK (&type_rw_lock);
    2322                 :            :   
    2323                 :      17781 :   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                 :      17781 :   i = 0;
    2332         [ +  + ]:      20623 :   while ((entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node)) != NULL)
    2333                 :            :     {
    2334                 :       4821 :       entry = &entries->entry[i];
    2335         [ +  + ]:       5107 :       while (i < IFACE_ENTRIES_N_ENTRIES (entries) &&
    2336         [ +  + ]:       3128 :              entry->init_state == INITIALIZED)
    2337                 :            :         {
    2338                 :        286 :           entry++;
    2339                 :        286 :           i++;
    2340                 :            :         }
    2341                 :            : 
    2342         [ +  + ]:       4821 :       if (i == IFACE_ENTRIES_N_ENTRIES (entries))
    2343                 :       1979 :         break;
    2344                 :            : 
    2345                 :       2842 :       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                 :       2842 :       i++;
    2352                 :            :     }
    2353                 :            :   
    2354                 :      17781 :   g_atomic_int_set (&node->data->class.init_state, INITIALIZED);
    2355                 :      17781 : }
    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                 :    5707442 : type_data_unref_U (TypeNode *node,
    2508                 :            :                    gboolean  uncached)
    2509                 :            : {
    2510                 :            :   guint current;
    2511                 :            : 
    2512                 :            :   do {
    2513                 :    5725012 :     current = NODE_REFCOUNT (node);
    2514                 :            : 
    2515         [ +  + ]:    5725012 :     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         [ +  + ]:    5725008 :   } 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                 :        305 : g_type_add_interface_check (gpointer                check_data,
    2632                 :            :                             GTypeInterfaceCheckFunc check_func)
    2633                 :            : {
    2634                 :            :   guint i;
    2635                 :            :   
    2636                 :        305 :   g_return_if_fail (check_func != NULL);
    2637                 :            :   
    2638                 :        305 :   G_WRITE_LOCK (&type_rw_lock);
    2639                 :        305 :   i = static_n_iface_check_funcs++;
    2640                 :        305 :   static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
    2641                 :        305 :   static_iface_check_funcs[i].check_data = check_data;
    2642                 :        305 :   static_iface_check_funcs[i].check_func = check_func;
    2643                 :        305 :   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                 :       9654 : 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                 :       9654 :   g_assert_type_system_initialized ();
    2714                 :       9654 :   g_return_val_if_fail (type_id > 0, 0);
    2715                 :       9654 :   g_return_val_if_fail (type_name != NULL, 0);
    2716                 :       9654 :   g_return_val_if_fail (info != NULL, 0);
    2717                 :       9654 :   g_return_val_if_fail (finfo != NULL, 0);
    2718                 :            :   
    2719         [ -  + ]:       9654 :   if (!check_type_name_I (type_name))
    2720                 :          0 :     return 0;
    2721   [ +  -  -  + ]:       9654 :   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         [ +  + ]:       9654 :   if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
    2730         [ -  + ]:       1016 :       !(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         [ -  + ]:       9654 :   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                 :       9654 :   G_WRITE_LOCK (&type_rw_lock);
    2745                 :       9654 :   node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
    2746                 :       9654 :   type_add_flags_W (node, flags);
    2747                 :            :   
    2748         [ +  - ]:       9654 :   if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info))
    2749         [ +  + ]:       9654 :     type_data_make_W (node, info,
    2750                 :       9654 :                       check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
    2751                 :       9654 :   G_WRITE_UNLOCK (&type_rw_lock);
    2752                 :            :   
    2753                 :       9654 :   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                 :      11540 : 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                 :      11540 :   g_return_val_if_fail (class_size <= G_MAXUINT16, G_TYPE_INVALID);
    2790                 :      11540 :   g_return_val_if_fail (instance_size <= G_MAXUINT16, G_TYPE_INVALID);
    2791                 :            : 
    2792                 :      11540 :   info.class_size = class_size;
    2793                 :      11540 :   info.base_init = NULL;
    2794                 :      11540 :   info.base_finalize = NULL;
    2795                 :      11540 :   info.class_init = class_init;
    2796                 :      11540 :   info.class_finalize = NULL;
    2797                 :      11540 :   info.class_data = NULL;
    2798                 :      11540 :   info.instance_size = instance_size;
    2799                 :      11540 :   info.n_preallocs = 0;
    2800                 :      11540 :   info.instance_init = instance_init;
    2801                 :      11540 :   info.value_table = NULL;
    2802                 :            : 
    2803                 :      11540 :   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                 :      27137 : 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                 :      27137 :   GType type = 0;
    2829                 :            :   
    2830                 :      27137 :   g_assert_type_system_initialized ();
    2831                 :      27137 :   g_return_val_if_fail (parent_type > 0, 0);
    2832                 :      27137 :   g_return_val_if_fail (type_name != NULL, 0);
    2833                 :      27137 :   g_return_val_if_fail (info != NULL, 0);
    2834                 :            :   
    2835   [ +  -  +  + ]:      54274 :   if (!check_type_name_I (type_name) ||
    2836                 :      27137 :       !check_derivation_I (parent_type, type_name))
    2837                 :          1 :     return 0;
    2838         [ -  + ]:      27136 :   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                 :      27136 :   pnode = lookup_type_node_I (parent_type);
    2846                 :      27136 :   G_WRITE_LOCK (&type_rw_lock);
    2847                 :      27136 :   type_data_ref_Wm (pnode);
    2848         [ +  - ]:      27136 :   if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info))
    2849                 :            :     {
    2850                 :      27136 :       node = type_node_new_W (pnode, type_name, NULL);
    2851                 :      27136 :       type_add_flags_W (node, flags);
    2852                 :      27136 :       type = NODE_TYPE (node);
    2853         [ +  + ]:      27136 :       type_data_make_W (node, info,
    2854                 :      27136 :                         check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
    2855                 :            :     }
    2856                 :      27136 :   G_WRITE_UNLOCK (&type_rw_lock);
    2857                 :            :   
    2858                 :      27136 :   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                 :       5759 : 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                 :       5759 :   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
    2923                 :       5759 :   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                 :       5759 :   g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
    2930                 :       5759 :   G_WRITE_LOCK (&type_rw_lock);
    2931         [ +  - ]:       5759 :   if (check_add_interface_L (instance_type, interface_type))
    2932                 :            :     {
    2933                 :       5759 :       TypeNode *node = lookup_type_node_I (instance_type);
    2934                 :       5759 :       TypeNode *iface = lookup_type_node_I (interface_type);
    2935         [ +  - ]:       5759 :       if (check_interface_info_I (iface, NODE_TYPE (node), info))
    2936                 :       5759 :         type_add_interface_Wm (node, iface, info, NULL);
    2937                 :            :     }
    2938                 :       5759 :   G_WRITE_UNLOCK (&type_rw_lock);
    2939                 :       5759 :   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                 :    5773190 : 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                 :    5773190 :   node = lookup_type_node_I (type);
    3001   [ +  #  #  + ]:    5910274 :   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         [ +  # ]:    5989478 :   if (G_LIKELY (type_data_ref_U (node)))
    3009                 :            :     {
    3010         [ +  + ]:    5977974 :       if (G_LIKELY (g_atomic_int_get (&node->data->class.init_state) == INITIALIZED))
    3011                 :    5957349 :         return node->data->class.class;
    3012                 :      20625 :       holds_ref = TRUE;
    3013                 :            :     }
    3014                 :            :   else
    3015                 :          0 :     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                 :          0 :   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                 :      20628 :   ptype = NODE_PARENT_TYPE (node);
    3026         [ +  + ]:      20628 :   pclass = ptype ? g_type_class_ref (ptype) : NULL;
    3027                 :            : 
    3028                 :      20628 :   G_WRITE_LOCK (&type_rw_lock);
    3029                 :            : 
    3030         [ +  + ]:      20628 :   if (!holds_ref)
    3031                 :          3 :     type_data_ref_Wm (node);
    3032                 :            : 
    3033         [ +  + ]:      20628 :   if (!node->data->class.class) /* class uninitialized */
    3034                 :      17781 :     type_class_init_Wm (node, pclass);
    3035                 :            : 
    3036                 :      20628 :   G_WRITE_UNLOCK (&type_rw_lock);
    3037                 :            : 
    3038         [ +  + ]:      20628 :   if (pclass)
    3039                 :      19509 :     g_type_class_unref (pclass);
    3040                 :            : 
    3041                 :      20628 :   g_rec_mutex_unlock (&class_init_rec_mutex);
    3042                 :            : 
    3043                 :      20628 :   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                 :    5722491 : g_type_class_unref (gpointer g_class)
    3057                 :            : {
    3058                 :            :   TypeNode *node;
    3059                 :    5722491 :   GTypeClass *class = g_class;
    3060                 :            :   
    3061                 :    5722491 :   g_return_if_fail (g_class != NULL);
    3062                 :            :   
    3063                 :    5722491 :   node = lookup_type_node_I (class->g_type);
    3064   [ +  #  +  #  :    5624292 :   if (node && node->is_classed && NODE_REFCOUNT (node))
                   +  + ]
    3065                 :    5765243 :     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                 :      19048 : g_type_class_peek (GType type)
    3112                 :            : {
    3113                 :            :   TypeNode *node;
    3114                 :            :   gpointer class;
    3115                 :            :   
    3116                 :      19048 :   node = lookup_type_node_I (type);
    3117   [ +  -  +  -  :      19048 :   if (node && node->is_classed && NODE_REFCOUNT (node) &&
                   +  + ]
    3118         [ +  + ]:      19046 :       g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
    3119                 :            :     /* ref_count _may_ be 0 */
    3120                 :      19044 :     class = node->data->class.class;
    3121                 :            :   else
    3122                 :          4 :     class = NULL;
    3123                 :            :   
    3124                 :      19048 :   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                 :    4968977 : g_type_class_peek_static (GType type)
    3142                 :            : {
    3143                 :            :   TypeNode *node;
    3144                 :            :   gpointer class;
    3145                 :            :   
    3146                 :    4968977 :   node = lookup_type_node_I (type);
    3147   [ +  #  +  #  :    4968834 :   if (node && node->is_classed && NODE_REFCOUNT (node) &&
                   +  # ]
    3148         [ +  # ]:    4968863 :       /* peek only static types: */ node->plugin == NULL &&
    3149         [ +  + ]:    4968873 :       g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
    3150                 :            :     /* ref_count _may_ be 0 */
    3151                 :    4966710 :     class = node->data->class.class;
    3152                 :            :   else
    3153                 :       2124 :     class = NULL;
    3154                 :            :   
    3155                 :    4968834 :   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                 :       9966 : g_type_class_peek_parent (gpointer g_class)
    3177                 :            : {
    3178                 :            :   TypeNode *node;
    3179                 :       9966 :   gpointer class = NULL;
    3180                 :            :   
    3181                 :       9966 :   g_return_val_if_fail (g_class != NULL, NULL);
    3182                 :            :   
    3183                 :       9966 :   node = lookup_type_node_I (G_TYPE_FROM_CLASS (g_class));
    3184                 :            : 
    3185                 :       9966 :   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   [ +  -  +  -  :       9966 :   if (node->is_classed && node->data && NODE_PARENT_TYPE (node))
                   +  + ]
    3192                 :            :     {
    3193                 :       9662 :       node = lookup_type_node_I (NODE_PARENT_TYPE (node));
    3194                 :       9662 :       class = node->data->class.class;
    3195                 :            :     }
    3196         [ -  + ]:        304 :   else if (NODE_PARENT_TYPE (node))
    3197                 :          0 :     g_critical (G_STRLOC ": invalid class pointer '%p'", g_class);
    3198                 :            :   
    3199                 :       9966 :   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                 :     773722 : g_type_interface_peek (gpointer instance_class,
    3216                 :            :                        GType    iface_type)
    3217                 :            : {
    3218                 :            :   TypeNode *node;
    3219                 :            :   TypeNode *iface;
    3220                 :     773722 :   gpointer vtable = NULL;
    3221                 :     773722 :   GTypeClass *class = instance_class;
    3222                 :            :   
    3223                 :     773722 :   g_return_val_if_fail (instance_class != NULL, NULL);
    3224                 :            :   
    3225                 :     773722 :   node = lookup_type_node_I (class->g_type);
    3226                 :     773654 :   iface = lookup_type_node_I (iface_type);
    3227   [ +  #  +  #  :     773479 :   if (node && node->is_instantiatable && iface)
                   +  # ]
    3228                 :     773516 :     type_lookup_iface_vtable_I (node, iface, &vtable);
    3229                 :            :   else
    3230                 :          0 :     g_critical (G_STRLOC ": invalid class pointer '%p'", class);
    3231                 :            :   
    3232                 :     773819 :   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                 :        195 : g_type_interface_peek_parent (gpointer g_iface)
    3251                 :            : {
    3252                 :            :   TypeNode *node;
    3253                 :            :   TypeNode *iface;
    3254                 :        195 :   gpointer vtable = NULL;
    3255                 :        195 :   GTypeInterface *iface_class = g_iface;
    3256                 :            :   
    3257                 :        195 :   g_return_val_if_fail (g_iface != NULL, NULL);
    3258                 :            :   
    3259                 :        195 :   iface = lookup_type_node_I (iface_class->g_type);
    3260                 :        195 :   node = lookup_type_node_I (iface_class->g_instance_type);
    3261         [ +  + ]:        195 :   if (node)
    3262                 :        194 :     node = lookup_type_node_I (NODE_PARENT_TYPE (node));
    3263   [ +  +  +  -  :        195 :   if (node && node->is_instantiatable && iface)
                   +  - ]
    3264                 :        194 :     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                 :        195 :   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                 :          5 : g_type_default_interface_ref (GType g_type)
    3294                 :            : {
    3295                 :            :   TypeNode *node;
    3296                 :            :   gpointer dflt_vtable;
    3297                 :            : 
    3298                 :          5 :   G_WRITE_LOCK (&type_rw_lock);
    3299                 :            : 
    3300                 :          5 :   node = lookup_type_node_I (g_type);
    3301   [ +  -  +  - ]:          5 :   if (!node || !NODE_IS_IFACE (node) ||
    3302   [ +  +  -  + ]:          5 :       (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   [ +  +  +  + ]:          5 :   if (!node->data || !node->data->iface.dflt_vtable)
    3311                 :            :     {
    3312                 :          4 :       G_WRITE_UNLOCK (&type_rw_lock);
    3313                 :          4 :       g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
    3314                 :          4 :       G_WRITE_LOCK (&type_rw_lock);
    3315                 :          4 :       node = lookup_type_node_I (g_type);
    3316                 :          4 :       type_data_ref_Wm (node);
    3317                 :          4 :       type_iface_ensure_dflt_vtable_Wm (node);
    3318                 :          4 :       g_rec_mutex_unlock (&class_init_rec_mutex);
    3319                 :            :     }
    3320                 :            :   else
    3321                 :          1 :     type_data_ref_Wm (node); /* ref_count >= 1 already */
    3322                 :            : 
    3323                 :          5 :   dflt_vtable = node->data->iface.dflt_vtable;
    3324                 :          5 :   G_WRITE_UNLOCK (&type_rw_lock);
    3325                 :            : 
    3326                 :          5 :   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                 :         44 : g_type_default_interface_peek (GType g_type)
    3344                 :            : {
    3345                 :            :   TypeNode *node;
    3346                 :            :   gpointer vtable;
    3347                 :            :   
    3348                 :         44 :   node = lookup_type_node_I (g_type);
    3349   [ +  -  +  -  :         44 :   if (node && NODE_IS_IFACE (node) && NODE_REFCOUNT (node))
                   +  + ]
    3350                 :         43 :     vtable = node->data->iface.dflt_vtable;
    3351                 :            :   else
    3352                 :          1 :     vtable = NULL;
    3353                 :            :   
    3354                 :         44 :   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                 :          5 : g_type_default_interface_unref (gpointer g_iface)
    3372                 :            : {
    3373                 :            :   TypeNode *node;
    3374                 :          5 :   GTypeInterface *vtable = g_iface;
    3375                 :            :   
    3376                 :          5 :   g_return_if_fail (g_iface != NULL);
    3377                 :            :   
    3378                 :          5 :   node = lookup_type_node_I (vtable->g_type);
    3379   [ +  -  +  - ]:          5 :   if (node && NODE_IS_IFACE (node))
    3380                 :          5 :     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                 :      14811 : g_type_name (GType type)
    3400                 :            : {
    3401                 :            :   TypeNode *node;
    3402                 :            :   
    3403                 :      14811 :   g_assert_type_system_initialized ();
    3404                 :            :   
    3405                 :      14811 :   node = lookup_type_node_I (type);
    3406                 :            :   
    3407         [ +  + ]:      14811 :   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                 :      50141 : g_type_from_name (const gchar *name)
    3441                 :            : {
    3442                 :      50141 :   GType type = 0;
    3443                 :            :   
    3444                 :      50141 :   g_return_val_if_fail (name != NULL, 0);
    3445                 :            :   
    3446                 :      50141 :   G_READ_LOCK (&type_rw_lock);
    3447                 :      50141 :   type = GPOINTER_TO_TYPE (g_hash_table_lookup (static_type_nodes_ht, name));
    3448                 :      50141 :   G_READ_UNLOCK (&type_rw_lock);
    3449                 :            :   
    3450                 :      50141 :   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                 :     869590 : g_type_parent (GType type)
    3464                 :            : {
    3465                 :            :   TypeNode *node;
    3466                 :            :   
    3467                 :     869590 :   node = lookup_type_node_I (type);
    3468                 :            :   
    3469         [ +  - ]:     869590 :   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                 :       2984 : g_type_depth (GType type)
    3483                 :            : {
    3484                 :            :   TypeNode *node;
    3485                 :            :   
    3486                 :       2984 :   node = lookup_type_node_I (type);
    3487                 :            :   
    3488         [ +  - ]:       2984 :   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                 :   95785139 : 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                 :   95785139 :   if (/* support_inheritance && */
    3541   [ +  #  +  + ]:   95785139 :       NODE_IS_ANCESTOR (iface_node, node))
    3542                 :   91313358 :     return TRUE;
    3543                 :            : 
    3544   [ +  #  +  +  :    4471781 :   support_interfaces = support_interfaces && node->is_instantiatable && NODE_IS_IFACE (iface_node);
                   +  + ]
    3545   [ +  +  +  + ]:    4471781 :   support_prerequisites = support_prerequisites && NODE_IS_IFACE (node);
    3546                 :    4471781 :   match = FALSE;
    3547         [ +  + ]:    4471781 :   if (support_interfaces)
    3548                 :            :     {
    3549         [ +  + ]:    4454255 :       if (have_lock)
    3550                 :            :         {
    3551         [ +  - ]:        693 :           if (type_lookup_iface_entry_L (node, iface_node))
    3552                 :        693 :             match = TRUE;
    3553                 :            :         }
    3554                 :            :       else
    3555                 :            :         {
    3556         [ +  + ]:    4453562 :           if (type_lookup_iface_vtable_I (node, iface_node, NULL))
    3557                 :    4449555 :             match = TRUE;
    3558                 :            :         }
    3559                 :            :     }
    3560   [ +  +  +  + ]:    4472099 :   if (!match &&
    3561                 :            :       support_prerequisites)
    3562                 :            :     {
    3563         [ +  - ]:       7533 :       if (!have_lock)
    3564                 :       7533 :         G_READ_LOCK (&type_rw_lock);
    3565   [ +  -  +  + ]:       7533 :       if (support_prerequisites && type_lookup_prerequisite_L (node, NODE_TYPE (iface_node)))
    3566                 :       3237 :         match = TRUE;
    3567         [ +  - ]:       7533 :       if (!have_lock)
    3568                 :       7533 :         G_READ_UNLOCK (&type_rw_lock);
    3569                 :            :     }
    3570                 :    4505029 :   return match;
    3571                 :            : }
    3572                 :            : 
    3573                 :            : static gboolean
    3574                 :       5787 : type_node_is_a_L (TypeNode *node,
    3575                 :            :                   TypeNode *iface_node)
    3576                 :            : {
    3577                 :       5787 :   return type_node_check_conformities_UorL (node, iface_node, TRUE, TRUE, TRUE);
    3578                 :            : }
    3579                 :            : 
    3580                 :            : static inline gboolean
    3581                 :   95644340 : type_node_conforms_to_U (TypeNode *node,
    3582                 :            :                          TypeNode *iface_node,
    3583                 :            :                          gboolean  support_interfaces,
    3584                 :            :                          gboolean  support_prerequisites)
    3585                 :            : {
    3586                 :   95644340 :   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                 :    9114526 : (g_type_is_a) (GType type,
    3603                 :            :                GType iface_type)
    3604                 :            : {
    3605                 :            :   TypeNode *node, *iface_node;
    3606                 :            :   gboolean is_a;
    3607                 :            : 
    3608         [ +  + ]:    9114526 :   if (type == iface_type)
    3609                 :          1 :     return TRUE;
    3610                 :            :   
    3611                 :    9114525 :   node = lookup_type_node_I (type);
    3612                 :    9112465 :   iface_node = lookup_type_node_I (iface_type);
    3613   [ +  +  +  #  :    9111028 :   is_a = node && iface_node && type_node_conforms_to_U (node, iface_node, TRUE, TRUE);
                   +  + ]
    3614                 :            :   
    3615                 :    9112125 :   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                 :         62 : g_type_children (GType  type,
    3632                 :            :                  guint *n_children)
    3633                 :            : {
    3634                 :            :   TypeNode *node;
    3635                 :            :   
    3636                 :         62 :   node = lookup_type_node_I (type);
    3637         [ +  - ]:         62 :   if (node)
    3638                 :            :     {
    3639                 :            :       GType *children;
    3640                 :            :       
    3641                 :         62 :       G_READ_LOCK (&type_rw_lock);  /* ->children is relocatable */
    3642                 :         62 :       children = g_new (GType, node->n_children + 1);
    3643         [ +  + ]:         62 :       if (node->n_children != 0)
    3644                 :         18 :         memcpy (children, node->children, sizeof (GType) * node->n_children);
    3645                 :         62 :       children[node->n_children] = 0;
    3646                 :            :       
    3647         [ +  + ]:         62 :       if (n_children)
    3648                 :         14 :         *n_children = node->n_children;
    3649                 :         62 :       G_READ_UNLOCK (&type_rw_lock);
    3650                 :            :       
    3651                 :         62 :       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                 :     402711 : g_type_interfaces (GType  type,
    3676                 :            :                    guint *n_interfaces)
    3677                 :            : {
    3678                 :            :   TypeNode *node;
    3679                 :            :   
    3680                 :     402711 :   node = lookup_type_node_I (type);
    3681   [ +  -  +  + ]:     402711 :   if (node && node->is_instantiatable)
    3682                 :            :     {
    3683                 :            :       IFaceEntries *entries;
    3684                 :            :       GType *ifaces;
    3685                 :            :       guint i;
    3686                 :            :       
    3687                 :     402524 :       G_READ_LOCK (&type_rw_lock);
    3688                 :     402524 :       entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node);
    3689         [ +  + ]:     402524 :       if (entries)
    3690                 :            :         {
    3691                 :     401513 :           ifaces = g_new (GType, IFACE_ENTRIES_N_ENTRIES (entries) + 1);
    3692         [ +  + ]:    1205390 :           for (i = 0; i < IFACE_ENTRIES_N_ENTRIES (entries); i++)
    3693                 :     803877 :             ifaces[i] = entries->entry[i].iface_type;
    3694                 :            :         }
    3695                 :            :       else
    3696                 :            :         {
    3697                 :       1011 :           ifaces = g_new (GType, 1);
    3698                 :       1011 :           i = 0;
    3699                 :            :         }
    3700                 :     402524 :       ifaces[i] = 0;
    3701                 :            :       
    3702         [ +  - ]:     402524 :       if (n_interfaces)
    3703                 :     402524 :         *n_interfaces = i;
    3704                 :     402524 :       G_READ_UNLOCK (&type_rw_lock);
    3705                 :            :       
    3706                 :     402524 :       return ifaces;
    3707                 :            :     }
    3708                 :            :   else
    3709                 :            :     {
    3710         [ +  - ]:        187 :       if (n_interfaces)
    3711                 :        187 :         *n_interfaces = 0;
    3712                 :            :       
    3713                 :        187 :       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                 :     111824 : type_get_qdata_L (TypeNode *node,
    3731                 :            :                   GQuark    quark)
    3732                 :            : {
    3733                 :     111824 :   GData *gdata = node->global_gdata;
    3734                 :            :   
    3735   [ +  -  +  +  :     111824 :   if (quark && gdata && gdata->n_qdatas)
                   +  - ]
    3736                 :            :     {
    3737                 :      75030 :       QData *qdatas = gdata->qdatas - 1;
    3738                 :      75030 :       guint n_qdatas = gdata->n_qdatas;
    3739                 :            :       
    3740                 :            :       do
    3741                 :            :         {
    3742                 :            :           guint i;
    3743                 :            :           QData *check;
    3744                 :            :           
    3745                 :      84011 :           i = (n_qdatas + 1) / 2;
    3746                 :      84011 :           check = qdatas + i;
    3747         [ +  + ]:      84011 :           if (quark == check->quark)
    3748                 :      65832 :             return check->data;
    3749         [ +  + ]:      18179 :           else if (quark > check->quark)
    3750                 :            :             {
    3751                 :      18077 :               n_qdatas -= i;
    3752                 :      18077 :               qdatas = check;
    3753                 :            :             }
    3754                 :            :           else /* if (quark < check->quark) */
    3755                 :        102 :             n_qdatas = i - 1;
    3756                 :            :         }
    3757         [ +  + ]:      18179 :       while (n_qdatas);
    3758                 :            :     }
    3759                 :      45992 :   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                 :      43041 : 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         [ +  + ]:      43041 :   if (!node->global_gdata)
    3809                 :      36794 :     node->global_gdata = g_new0 (GData, 1);
    3810                 :      43041 :   gdata = node->global_gdata;
    3811                 :            :   
    3812                 :            :   /* try resetting old data */
    3813                 :      43041 :   qdata = gdata->qdatas;
    3814         [ +  + ]:      49453 :   for (i = 0; i < gdata->n_qdatas; i++)
    3815         [ +  + ]:      10090 :     if (qdata[i].quark == quark)
    3816                 :            :       {
    3817                 :       3678 :         qdata[i].data = data;
    3818                 :       3678 :         return;
    3819                 :            :       }
    3820                 :            :   
    3821                 :            :   /* add new entry */
    3822                 :      39363 :   gdata->n_qdatas++;
    3823                 :      39363 :   gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
    3824                 :      39363 :   qdata = gdata->qdatas;
    3825         [ +  + ]:      41962 :   for (i = 0; i < gdata->n_qdatas - 1; i++)
    3826         [ +  + ]:       2701 :     if (qdata[i].quark > quark)
    3827                 :        102 :       break;
    3828                 :      39363 :   memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
    3829                 :      39363 :   qdata[i].quark = quark;
    3830                 :      39363 :   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                 :      36794 : type_add_flags_W (TypeNode  *node,
    3863                 :            :                   GTypeFlags flags)
    3864                 :            : {
    3865                 :            :   guint dflags;
    3866                 :            :   
    3867                 :      36794 :   g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
    3868                 :      36794 :   g_return_if_fail (node != NULL);
    3869                 :            :   
    3870   [ +  +  +  +  :      36794 :   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                 :      36794 :   dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
    3873                 :      36794 :   dflags |= flags;
    3874                 :      36794 :   type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
    3875                 :            : 
    3876                 :      36794 :   node->is_abstract = (flags & G_TYPE_FLAG_ABSTRACT) != 0;
    3877                 :      36794 :   node->is_deprecated |= (flags & G_TYPE_FLAG_DEPRECATED) != 0;
    3878                 :      36794 :   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                 :    4992350 : _g_type_test_flags (GType type,
    3956                 :            :                     guint flags)
    3957                 :            : {
    3958                 :            :   TypeNode *node;
    3959                 :    4992350 :   gboolean result = FALSE;
    3960                 :            :   
    3961                 :    4992350 :   node = lookup_type_node_I (type);
    3962         [ +  # ]:    4992164 :   if (node)
    3963                 :            :     {
    3964         [ +  + ]:    4992177 :       if ((flags & ~NODE_FLAG_MASK) == 0)
    3965                 :            :         {
    3966   [ +  +  +  + ]:    4992173 :           if ((flags & G_TYPE_FLAG_CLASSED) && !node->is_classed)
    3967                 :        274 :             return FALSE;
    3968                 :            : 
    3969   [ +  +  +  + ]:    4991899 :           if ((flags & G_TYPE_FLAG_INSTANTIATABLE) && !node->is_instantiatable)
    3970                 :        256 :             return FALSE;
    3971                 :            : 
    3972   [ +  +  +  + ]:    4991643 :           if ((flags & G_TYPE_FLAG_FINAL) && !node->is_final)
    3973                 :          2 :             return FALSE;
    3974                 :            : 
    3975   [ +  +  +  + ]:    4991641 :           if ((flags & G_TYPE_FLAG_ABSTRACT) && !node->is_abstract)
    3976                 :       1399 :             return FALSE;
    3977                 :            : 
    3978   [ +  +  +  # ]:    4990242 :           if ((flags & G_TYPE_FLAG_DEPRECATED) && !node->is_deprecated)
    3979                 :    4979087 :             return FALSE;
    3980                 :            : 
    3981                 :      11155 :           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                 :          0 :   return result;
    4009                 :            : }
    4010                 :            : 
    4011                 :            : gboolean
    4012                 :       7379 : (g_type_test_flags) (GType type,
    4013                 :            :                      guint flags)
    4014                 :            : {
    4015                 :       7379 :   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                 :          6 : g_type_fundamental_next (void)
    4099                 :            : {
    4100                 :            :   GType type;
    4101                 :            :   
    4102                 :          6 :   G_READ_LOCK (&type_rw_lock);
    4103                 :          6 :   type = static_fundamental_next;
    4104                 :          6 :   G_READ_UNLOCK (&type_rw_lock);
    4105                 :          6 :   type = G_TYPE_MAKE_FUNDAMENTAL (type);
    4106         [ +  - ]:          6 :   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                 :   14545237 : g_type_fundamental (GType type_id)
    4120                 :            : {
    4121                 :   14545237 :   TypeNode *node = lookup_type_node_I (type_id);
    4122                 :            :   
    4123         [ +  # ]:   14549027 :   return node ? NODE_FUNDAMENTAL_TYPE (node) : 0;
    4124                 :            : }
    4125                 :            : 
    4126                 :            : gboolean
    4127                 :   11001790 : g_type_check_instance_is_a (GTypeInstance *type_instance,
    4128                 :            :                             GType          iface_type)
    4129                 :            : {
    4130                 :            :   TypeNode *node, *iface;
    4131                 :            :   gboolean check;
    4132                 :            :   
    4133   [ +  #  #  + ]:   11001790 :   if (!type_instance || !type_instance->g_class)
    4134                 :          0 :     return FALSE;
    4135                 :            : 
    4136                 :   11001872 :   iface = lookup_type_node_I (iface_type);
    4137   [ +  #  +  + ]:   11001568 :   if (iface && iface->is_final)
    4138                 :          4 :     return type_instance->g_class->g_type == iface_type;
    4139                 :            : 
    4140                 :   11001564 :   node = lookup_type_node_I (type_instance->g_class->g_type);
    4141   [ +  #  +  +  :   11001324 :   check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
             +  #  +  + ]
    4142                 :            :   
    4143                 :   11001507 :   return check;
    4144                 :            : }
    4145                 :            : 
    4146                 :            : gboolean
    4147                 :  482879381 : g_type_check_instance_is_fundamentally_a (GTypeInstance *type_instance,
    4148                 :            :                                           GType          fundamental_type)
    4149                 :            : {
    4150                 :            :   TypeNode *node;
    4151   [ +  #  +  + ]:  482879381 :   if (!type_instance || !type_instance->g_class)
    4152                 :          0 :     return FALSE;
    4153                 :  485691406 :   node = lookup_type_node_I (type_instance->g_class->g_type);
    4154   [ +  #  +  + ]:  482587052 :   return node && (NODE_FUNDAMENTAL_TYPE(node) == fundamental_type);
    4155                 :            : }
    4156                 :            : 
    4157                 :            : gboolean
    4158                 :      31268 : g_type_check_class_is_a (GTypeClass *type_class,
    4159                 :            :                          GType       is_a_type)
    4160                 :            : {
    4161                 :            :   TypeNode *node, *iface;
    4162                 :            :   gboolean check;
    4163                 :            :   
    4164         [ -  + ]:      31268 :   if (!type_class)
    4165                 :          0 :     return FALSE;
    4166                 :            :   
    4167                 :      31268 :   node = lookup_type_node_I (type_class->g_type);
    4168                 :      31268 :   iface = lookup_type_node_I (is_a_type);
    4169   [ +  -  +  -  :      31268 :   check = node && node->is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
             +  -  +  - ]
    4170                 :            :   
    4171                 :      31268 :   return check;
    4172                 :            : }
    4173                 :            : 
    4174                 :            : GTypeInstance*
    4175                 :   69116011 : g_type_check_instance_cast (GTypeInstance *type_instance,
    4176                 :            :                             GType          iface_type)
    4177                 :            : {
    4178         [ +  # ]:   69116011 :   if (type_instance)
    4179                 :            :     {
    4180         [ +  + ]:   69155523 :       if (type_instance->g_class)
    4181                 :            :         {
    4182                 :            :           TypeNode *node, *iface;
    4183                 :            :           gboolean is_instantiatable, check;
    4184                 :            :           
    4185                 :   69154385 :           node = lookup_type_node_I (type_instance->g_class->g_type);
    4186   [ +  #  +  # ]:   69068696 :           is_instantiatable = node && node->is_instantiatable;
    4187                 :   69068696 :           iface = lookup_type_node_I (iface_type);
    4188   [ +  #  +  #  :   68952476 :           check = is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
                   +  # ]
    4189         [ +  # ]:   68954616 :           if (check)
    4190                 :   68984748 :             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                 :       1138 :         g_critical ("invalid unclassed pointer in cast to '%s'",
    4203                 :            :                     type_descriptive_name_I (iface_type));
    4204                 :            :     }
    4205                 :            :   
    4206                 :         49 :   return type_instance;
    4207                 :            : }
    4208                 :            : 
    4209                 :            : GTypeClass*
    4210                 :    6757318 : g_type_check_class_cast (GTypeClass *type_class,
    4211                 :            :                          GType       is_a_type)
    4212                 :            : {
    4213         [ +  # ]:    6757318 :   if (type_class)
    4214                 :            :     {
    4215                 :            :       TypeNode *node, *iface;
    4216                 :            :       gboolean is_classed, check;
    4217                 :            :       
    4218                 :    6757359 :       node = lookup_type_node_I (type_class->g_type);
    4219   [ +  #  +  # ]:    6757296 :       is_classed = node && node->is_classed;
    4220                 :    6757296 :       iface = lookup_type_node_I (is_a_type);
    4221   [ +  +  +  #  :    6757241 :       check = is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
                   +  # ]
    4222         [ +  # ]:    6757248 :       if (check)
    4223                 :    6757274 :         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                 :   36397535 : 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         [ +  # ]:   36397535 :   if (type_instance)
    4256                 :            :     {
    4257         [ +  # ]:   36397952 :       if (type_instance->g_class)
    4258                 :            :         {
    4259                 :   36397984 :           TypeNode *node = lookup_type_node_I (type_instance->g_class->g_type);
    4260                 :            :           
    4261   [ +  +  +  # ]:   36396487 :           if (node && node->is_instantiatable)
    4262                 :   36396528 :             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                 :      83743 : type_check_is_value_type_U (GType type)
    4278                 :            : {
    4279                 :      83743 :   GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT;
    4280                 :            :   TypeNode *node;
    4281                 :            :   
    4282                 :            :   /* common path speed up */
    4283                 :      83743 :   node = lookup_type_node_I (type);
    4284   [ +  +  +  + ]:      83740 :   if (node && node->mutatable_check_cache)
    4285                 :      61635 :     return TRUE;
    4286                 :            :   
    4287                 :      22105 :   G_READ_LOCK (&type_rw_lock);
    4288                 :      27582 :  restart_check:
    4289         [ +  + ]:      27582 :   if (node)
    4290                 :            :     {
    4291   [ +  -  +  - ]:      27576 :       if (node->data && NODE_REFCOUNT (node) > 0 &&
    4292         [ +  + ]:      27576 :           node->data->common.value_table->value_init)
    4293                 :      22102 :         tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
    4294         [ +  - ]:       5474 :       else if (NODE_IS_IFACE (node))
    4295                 :            :         {
    4296                 :            :           guint i;
    4297                 :            :           
    4298         [ +  - ]:       5474 :           for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
    4299                 :            :             {
    4300                 :       5474 :               GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
    4301                 :       5474 :               TypeNode *prnode = lookup_type_node_I (prtype);
    4302                 :            :               
    4303         [ +  - ]:       5474 :               if (prnode->is_instantiatable)
    4304                 :            :                 {
    4305                 :       5474 :                   type = prtype;
    4306                 :       5474 :                   node = lookup_type_node_I (type);
    4307                 :       5474 :                   goto restart_check;
    4308                 :            :                 }
    4309                 :            :             }
    4310                 :            :         }
    4311                 :            :     }
    4312                 :      22107 :   G_READ_UNLOCK (&type_rw_lock);
    4313                 :            :   
    4314                 :      22108 :   return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT);
    4315                 :            : }
    4316                 :            : 
    4317                 :            : gboolean
    4318                 :       6465 : g_type_check_is_value_type (GType type)
    4319                 :            : {
    4320                 :       6465 :   return type_check_is_value_type_U (type);
    4321                 :            : }
    4322                 :            : 
    4323                 :            : gboolean
    4324                 :      10608 : g_type_check_value (const GValue *value)
    4325                 :            : {
    4326   [ +  -  +  + ]:      10608 :   return value && type_check_is_value_type_U (value->g_type);
    4327                 :            : }
    4328                 :            : 
    4329                 :            : gboolean
    4330                 :      66670 : g_type_check_value_holds (const GValue *value,
    4331                 :            :                           GType         type)
    4332                 :            : {
    4333   [ +  -  +  +  :      66670 :   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                 :  135691589 : g_type_value_table_peek (GType type)
    4351                 :            : {
    4352                 :  135691589 :   GTypeValueTable *vtable = NULL;
    4353                 :  135691589 :   TypeNode *node = lookup_type_node_I (type);
    4354                 :            :   gboolean has_refed_data, has_table;
    4355                 :            : 
    4356   [ +  #  +  +  :  135748233 :   if (node && NODE_REFCOUNT (node) && node->mutatable_check_cache)
                   +  + ]
    4357                 :  123689812 :     return node->data->common.value_table;
    4358                 :            : 
    4359                 :   12058421 :   G_READ_LOCK (&type_rw_lock);
    4360                 :            :   
    4361                 :   12303361 :  restart_table_peek:
    4362   [ +  +  +  #  :   12303361 :   has_refed_data = node && node->data && NODE_REFCOUNT (node) > 0;
                   +  # ]
    4363   [ +  +  +  + ]:   12303361 :   has_table = has_refed_data && node->data->common.value_table->value_init;
    4364         [ +  + ]:   12303361 :   if (has_refed_data)
    4365                 :            :     {
    4366         [ +  + ]:   12303162 :       if (has_table)
    4367                 :   12293569 :         vtable = node->data->common.value_table;
    4368         [ +  # ]:       9593 :       else if (NODE_IS_IFACE (node))
    4369                 :            :         {
    4370                 :            :           guint i;
    4371                 :            :           
    4372         [ +  - ]:       9598 :           for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
    4373                 :            :             {
    4374                 :       9598 :               GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
    4375                 :       9598 :               TypeNode *prnode = lookup_type_node_I (prtype);
    4376                 :            :               
    4377         [ +  - ]:       9598 :               if (prnode->is_instantiatable)
    4378                 :            :                 {
    4379                 :       9598 :                   type = prtype;
    4380                 :       9598 :                   node = lookup_type_node_I (type);
    4381                 :       9598 :                   goto restart_table_peek;
    4382                 :            :                 }
    4383                 :            :             }
    4384                 :            :         }
    4385                 :            :     }
    4386                 :            :   
    4387                 :   12293763 :   G_READ_UNLOCK (&type_rw_lock);
    4388                 :            :   
    4389         [ +  # ]:   12293932 :   if (vtable)
    4390                 :   12294300 :     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                 :         10 : g_type_name_from_instance (GTypeInstance *instance)
    4403                 :            : {
    4404         [ -  + ]:         10 :   if (!instance)
    4405                 :          0 :     return "<NULL-instance>";
    4406                 :            :   else
    4407                 :         10 :     return g_type_name_from_class (instance->g_class);
    4408                 :            : }
    4409                 :            : 
    4410                 :            : const gchar *
    4411                 :         10 : g_type_name_from_class (GTypeClass *g_class)
    4412                 :            : {
    4413         [ -  + ]:         10 :   if (!g_class)
    4414                 :          0 :     return "<NULL-class>";
    4415                 :            :   else
    4416                 :         10 :     return g_type_name (g_class->g_type);
    4417                 :            : }
    4418                 :            : 
    4419                 :            : 
    4420                 :            : /* --- private api for gboxed.c --- */
    4421                 :            : gpointer
    4422                 :        871 : _g_type_boxed_copy (GType type, gpointer value)
    4423                 :            : {
    4424                 :        871 :   TypeNode *node = lookup_type_node_I (type);
    4425                 :            : 
    4426                 :        871 :   return node->data->boxed.copy_func (value);
    4427                 :            : }
    4428                 :            : 
    4429                 :            : void
    4430                 :        581 : _g_type_boxed_free (GType type, gpointer value)
    4431                 :            : {
    4432                 :        581 :   TypeNode *node = lookup_type_node_I (type);
    4433                 :            : 
    4434                 :        581 :   node->data->boxed.free_func (value);
    4435                 :        581 : }
    4436                 :            : 
    4437                 :            : void
    4438                 :       1131 : _g_type_boxed_init (GType          type,
    4439                 :            :                     GBoxedCopyFunc copy_func,
    4440                 :            :                     GBoxedFreeFunc free_func)
    4441                 :            : {
    4442                 :       1131 :   TypeNode *node = lookup_type_node_I (type);
    4443                 :            : 
    4444                 :       1131 :   node->data->boxed.copy_func = copy_func;
    4445                 :       1131 :   node->data->boxed.free_func = free_func;
    4446                 :       1131 : }
    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                 :        508 : 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                 :        508 :   GLIB_PRIVATE_CALL (glib_init) ();
    4501                 :            : 
    4502                 :        508 :   G_WRITE_LOCK (&type_rw_lock);
    4503                 :            : 
    4504                 :            :   /* setup GObject library wide debugging flags */
    4505                 :        508 :   env_string = g_getenv ("GOBJECT_DEBUG");
    4506         [ -  + ]:        508 :   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                 :        508 :   static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
    4519                 :        508 :   static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
    4520                 :        508 :   static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
    4521                 :            : 
    4522                 :            :   /* type qname hash table */
    4523                 :        508 :   static_type_nodes_ht = g_hash_table_new (g_str_hash, g_str_equal);
    4524                 :            : 
    4525                 :            :   /* invalid type G_TYPE_INVALID (0)
    4526                 :            :    */
    4527                 :        508 :   static_fundamental_type_nodes[0] = NULL;
    4528                 :            : 
    4529                 :            :   /* void type G_TYPE_NONE
    4530                 :            :    */
    4531                 :        508 :   node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0);
    4532                 :        508 :   type = NODE_TYPE (node);
    4533                 :        508 :   g_assert (type == G_TYPE_NONE);
    4534                 :            : 
    4535                 :            :   /* interface fundamental type G_TYPE_INTERFACE (!classed)
    4536                 :            :    */
    4537                 :        508 :   memset (&info, 0, sizeof (info));
    4538                 :        508 :   node = type_node_fundamental_new_W (G_TYPE_INTERFACE, g_intern_static_string ("GInterface"), G_TYPE_FLAG_DERIVABLE);
    4539                 :        508 :   type = NODE_TYPE (node);
    4540                 :        508 :   type_data_make_W (node, &info, NULL);
    4541                 :        508 :   g_assert (type == G_TYPE_INTERFACE);
    4542                 :            : 
    4543                 :        508 :   G_WRITE_UNLOCK (&type_rw_lock);
    4544                 :            : 
    4545                 :        508 :   _g_value_c_init ();
    4546                 :            : 
    4547                 :            :   /* G_TYPE_TYPE_PLUGIN
    4548                 :            :    */
    4549                 :        508 :   g_type_ensure (g_type_plugin_get_type ());
    4550                 :            : 
    4551                 :            :   /* G_TYPE_* value types
    4552                 :            :    */
    4553                 :        508 :   _g_value_types_init ();
    4554                 :            : 
    4555                 :            :   /* G_TYPE_ENUM & G_TYPE_FLAGS
    4556                 :            :    */
    4557                 :        508 :   _g_enum_types_init ();
    4558                 :            : 
    4559                 :            :   /* G_TYPE_BOXED
    4560                 :            :    */
    4561                 :        508 :   _g_boxed_type_init ();
    4562                 :            : 
    4563                 :            :   /* G_TYPE_PARAM
    4564                 :            :    */
    4565                 :        508 :   _g_param_type_init ();
    4566                 :            : 
    4567                 :            :   /* G_TYPE_OBJECT
    4568                 :            :    */
    4569                 :        508 :   _g_object_type_init ();
    4570                 :            : 
    4571                 :            :   /* G_TYPE_PARAM_* pspec types
    4572                 :            :    */
    4573                 :        508 :   _g_param_spec_types_init ();
    4574                 :            : 
    4575                 :            :   /* Value Transformations
    4576                 :            :    */
    4577                 :        508 :   _g_value_transforms_init ();
    4578                 :            : 
    4579                 :            :   /* Signal system
    4580                 :            :    */
    4581                 :        508 :   _g_signal_init ();
    4582                 :        508 : }
    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                 :        508 : gobject_init_ctor (void)
    4667                 :            : {
    4668                 :        508 :   gobject_init ();
    4669                 :        508 : }
    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                 :       4837 : g_type_add_instance_private (GType class_gtype,
    4787                 :            :                              gsize private_size)
    4788                 :            : {
    4789                 :       4837 :   TypeNode *node = lookup_type_node_I (class_gtype);
    4790                 :            : 
    4791                 :       4837 :   g_return_val_if_fail (private_size > 0, 0);
    4792                 :       4837 :   g_return_val_if_fail (private_size <= 0xffff, 0);
    4793                 :            : 
    4794   [ +  -  +  -  :       4837 :   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         [ -  + ]:       4837 :   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                 :       4837 :   return private_size;
    4839                 :            : }
    4840                 :            : 
    4841                 :            : /* semi-private function, should only be used by G_DEFINE_TYPE_EXTENDED */
    4842                 :            : void
    4843                 :       3621 : g_type_class_adjust_private_offset (gpointer  g_class,
    4844                 :            :                                     gint     *private_size_or_offset)
    4845                 :            : {
    4846                 :       3621 :   GType class_gtype = ((GTypeClass *) g_class)->g_type;
    4847                 :       3621 :   TypeNode *node = lookup_type_node_I (class_gtype);
    4848                 :            :   gssize private_size;
    4849                 :            : 
    4850                 :       3621 :   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         [ +  - ]:       3621 :   if (*private_size_or_offset > 0)
    4857                 :       3621 :     g_return_if_fail (*private_size_or_offset <= 0xffff);
    4858                 :            :   else
    4859                 :          0 :     return;
    4860                 :            : 
    4861   [ +  -  +  -  :       3621 :   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         [ +  + ]:       3621 :   if (NODE_PARENT_TYPE (node))
    4870                 :            :     {
    4871                 :       3113 :       TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
    4872         [ -  + ]:       3113 :       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                 :       3621 :   G_WRITE_LOCK (&type_rw_lock);
    4881                 :            : 
    4882                 :       3621 :   private_size = ALIGN_STRUCT (node->data->instance.private_size + *private_size_or_offset);
    4883                 :       3621 :   g_assert (private_size <= 0xffff);
    4884                 :       3621 :   node->data->instance.private_size = private_size;
    4885                 :            : 
    4886                 :       3621 :   *private_size_or_offset = -(gint) node->data->instance.private_size;
    4887                 :            : 
    4888                 :       3621 :   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                 :    1145442 : 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         [ -  + ]:    1145442 :   if (G_UNLIKELY (type == (GType)-1))
    5083                 :          0 :     g_error ("can't happen");
    5084                 :    1145442 : }

Generated by: LCOV version 1.14