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