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