if __GNUC__ is defined, inline a test for an exact type match for
[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 #include        "gtype.h"
20
21 /*
22  * MT safe
23  */
24
25 #include        "gtypeplugin.h"
26 #include        "gvaluecollector.h"
27 #include        <string.h>
28
29
30 /* NOTE: some functions (some internal variants and exported ones)
31  * invalidate data portions of the TypeNodes. if external functions/callbacks
32  * are called, pointers to memory maintained by TypeNodes have to be looked up
33  * again. this affects most of the struct TypeNode fields, e.g. ->children or
34  * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
35  * not ->supers[]), as all those memory portions can get realloc()ed during
36  * callback invocation.
37  *
38  * TODO:
39  * - g_type_from_name() should do an ordered array lookup after fetching the
40  *   the quark, instead of a second hashtable lookup.
41  * - speedup checks for virtual types, steal a bit somewhere
42  *
43  * FIXME:
44  * - force interface initialization for already existing classes
45  *
46  * LOCKING:
47  * lock handling issues when calling static functions are indicated by
48  * uppercase letter postfixes, all static functions have to have
49  * one of the below postfixes:
50  * - _I:        [Indifferent about locking]
51  *   function doesn't care about locks at all
52  * - _U:        [Unlocked invocation]
53  *   no read or write lock has to be held across function invocation
54  *   (locks may be acquired and released during invocation though)
55  * - _L:        [Locked invocation]
56  *   a write lock or more than 0 read locks have to be held across
57  *   function invocation
58  * - _W:        [Write-locked invocation]
59  *   a write lock has to be held across function invokation
60  * - _Wm:       [Write-locked invocation, mutatable]
61  *   like _W, but the write lock might be released and reacquired
62  *   during invocation, watch your pointers
63  */
64
65 static GStaticRWLock            type_rw_lock = G_STATIC_RW_LOCK_INIT;
66 #define G_READ_LOCK(rw_lock)    g_static_rw_lock_reader_lock (rw_lock)
67 #define G_READ_UNLOCK(rw_lock)  g_static_rw_lock_reader_unlock (rw_lock)
68 #define G_WRITE_LOCK(rw_lock)   g_static_rw_lock_writer_lock (rw_lock)
69 #define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
70 #define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
71     static const gchar *_action = " invalidly modified type "; \
72     gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
73     if (_arg) \
74       g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
75     else \
76       g_error ("%s()%s`%s'", _fname, _action, _tname); \
77 }G_STMT_END
78 #define g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{     \
79   if (!(condition))                                                                             \
80     {                                                                                           \
81       g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,                                                \
82              "%s: initialization assertion failed, use %s() prior to this function",            \
83              G_STRLOC, G_STRINGIFY (init_function));                                            \
84       return (return_value);                                                                    \
85     }                                                                                           \
86 }G_STMT_END
87
88 #ifdef  G_ENABLE_DEBUG
89 #define DEBUG_CODE(debug_type, code_block)  G_STMT_START {    \
90     if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
91       { code_block; }                                     \
92 } G_STMT_END
93 #else /* !G_ENABLE_DEBUG */
94 #define DEBUG_CODE(debug_type, code_block)  /* code_block */
95 #endif  /* G_ENABLE_DEBUG */
96
97 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
98                                     G_TYPE_FLAG_INSTANTIATABLE | \
99                                     G_TYPE_FLAG_DERIVABLE | \
100                                     G_TYPE_FLAG_DEEP_DERIVABLE)
101 #define TYPE_FLAG_MASK             (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
102 #define SIZEOF_FUNDAMENTAL_INFO    ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
103                                                        sizeof (gpointer)), \
104                                                   sizeof (glong)))
105
106
107 /* --- typedefs --- */
108 typedef struct _TypeNode        TypeNode;
109 typedef struct _CommonData      CommonData;
110 typedef struct _IFaceData       IFaceData;
111 typedef struct _ClassData       ClassData;
112 typedef struct _InstanceData    InstanceData;
113 typedef union  _TypeData        TypeData;
114 typedef struct _IFaceEntry      IFaceEntry;
115 typedef struct _IFaceHolder     IFaceHolder;
116
117
118 /* --- prototypes --- */
119 static inline GTypeFundamentalInfo*     type_node_fundamental_info_L    (TypeNode               *node);
120 static        void                      type_add_flags_W                (TypeNode               *node,
121                                                                          GTypeFlags              flags);
122 static        void                      type_data_make_W                (TypeNode               *node,
123                                                                          const GTypeInfo        *info,
124                                                                          const GTypeValueTable  *value_table);
125 static inline void                      type_data_ref_Wm                (TypeNode               *node);
126 static inline void                      type_data_unref_Wm              (TypeNode               *node,
127                                                                          gboolean                uncached);
128 static        void                      type_data_last_unref_Wm         (GType                   type,
129                                                                          gboolean                uncached);
130 static inline gpointer                  type_get_qdata_L                (TypeNode               *node,
131                                                                          GQuark                  quark);
132 static inline void                      type_set_qdata_W                (TypeNode               *node,
133                                                                          GQuark                  quark,
134                                                                          gpointer                data);
135
136
137 /* --- structures --- */
138 struct _GValue  /* kludge, keep in sync with gvalue.h */
139 {
140   GType g_type;
141 };
142 struct _TypeNode
143 {
144   GTypePlugin *plugin;
145   guint        n_children : 12;
146   guint        n_supers : 8;
147   guint        _prot_n_ifaces_prerequisites : 9;
148   guint        is_classed : 1;
149   guint        is_instantiatable : 1;
150   guint        free_flag : 1;
151   GType       *children;
152   TypeData    *data;
153   GQuark       qname;
154   GData       *global_gdata;
155   union {
156     IFaceEntry  *iface_entries;         /* for !iface types */
157     GType       *prerequisistes;
158   } _prot;
159   GType        supers[1]; /* flexible array */
160 };
161 #define SIZEOF_BASE_TYPE_NODE()                 (G_STRUCT_OFFSET (TypeNode, supers))
162 #define MAX_N_SUPERS                            (255)
163 #define MAX_N_CHILDREN                          (4095)
164 #define MAX_N_IFACES                            (511)
165 #define MAX_N_PREREQUISITES                     (MAX_N_IFACES)
166 #define NODE_TYPE(node)                         (node->supers[0])
167 #define NODE_PARENT_TYPE(node)                  (node->supers[1])
168 #define NODE_NAME(node)                         (g_quark_to_string (node->qname))
169 #define NODE_IS_IFACE(node)                     (G_TYPE_IS_INTERFACE (NODE_TYPE (node)))
170 #define CLASSED_NODE_N_IFACES(node)             ((node)->_prot_n_ifaces_prerequisites)
171 #define CLASSED_NODE_IFACES_ENTRIES(node)       ((node)->_prot.iface_entries)
172 #define IFACE_NODE_N_PREREQUISITES(node)        ((node)->_prot_n_ifaces_prerequisites)
173 #define IFACE_NODE_PREREQUISITES(node)          ((node)->_prot.prerequisistes)
174 #define iface_node_get_holders_L(node)          ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
175 #define iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
176 #define iface_node_get_dependants_array_L(n)    ((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
177 #define iface_node_set_dependants_array_W(n,d)  (type_set_qdata_W ((n), static_quark_dependants_array, (d)))
178
179 struct _IFaceHolder
180 {
181   GType           instance_type;
182   GInterfaceInfo *info;
183   GTypePlugin    *plugin;
184   IFaceHolder    *next;
185 };
186 struct _IFaceEntry
187 {
188   GType           iface_type;
189   GTypeInterface *vtable;
190 };
191 struct _CommonData
192 {
193   guint             ref_count;
194   GTypeValueTable  *value_table;
195 };
196 struct _IFaceData
197 {
198   CommonData         common;
199   guint16            vtable_size;
200   GBaseInitFunc      vtable_init_base;
201   GBaseFinalizeFunc  vtable_finalize_base;
202 };
203 struct _ClassData
204 {
205   CommonData         common;
206   guint16            class_size;
207   GBaseInitFunc      class_init_base;
208   GBaseFinalizeFunc  class_finalize_base;
209   GClassInitFunc     class_init;
210   GClassFinalizeFunc class_finalize;
211   gconstpointer      class_data;
212   gpointer           class;
213 };
214 struct _InstanceData
215 {
216   CommonData         common;
217   guint16            class_size;
218   GBaseInitFunc      class_init_base;
219   GBaseFinalizeFunc  class_finalize_base;
220   GClassInitFunc     class_init;
221   GClassFinalizeFunc class_finalize;
222   gconstpointer      class_data;
223   gpointer           class;
224   guint16            instance_size;
225   guint16            n_preallocs;
226   GInstanceInitFunc  instance_init;
227   GMemChunk        *mem_chunk;
228 };
229 union _TypeData
230 {
231   CommonData         common;
232   IFaceData          iface;
233   ClassData          class;
234   InstanceData       instance;
235 };
236 typedef struct {
237   gpointer            cache_data;
238   GTypeClassCacheFunc cache_func;
239 } ClassCacheFunc;
240
241
242 /* --- variables --- */
243 static guint           static_n_class_cache_funcs = 0;
244 static ClassCacheFunc *static_class_cache_funcs = NULL;
245 static GType           static_last_fundamental_id = 0;
246 static GQuark          static_quark_type_flags = 0;
247 static GQuark          static_quark_iface_holder = 0;
248 static GQuark          static_quark_dependants_array = 0;
249 GTypeDebugFlags        _g_type_debug_flags = 0;
250
251
252 /* --- externs --- */
253 const char  *g_log_domain_gruntime = "GRuntime";
254
255
256 /* --- type nodes --- */
257 static GHashTable       *static_type_nodes_ht = NULL;
258 static GType            *static_branch_seqnos = NULL;
259 static TypeNode       ***static_type_nodes = NULL;
260
261 static inline TypeNode*
262 lookup_type_node_L (register GType utype)
263 {
264   register GType ftype = G_TYPE_FUNDAMENTAL (utype);
265   register GType b_seqno = G_TYPE_BRANCH_SEQNO (utype);
266   
267   if (ftype < static_last_fundamental_id && b_seqno < static_branch_seqnos[ftype])
268     return static_type_nodes[ftype][b_seqno];
269   else
270     return NULL;
271 }
272
273 static TypeNode*
274 type_node_any_new_W (TypeNode             *pnode,
275                      GType                 ftype,
276                      const gchar          *name,
277                      GTypePlugin          *plugin,
278                      GTypeFundamentalFlags type_flags)
279 {
280   guint branch_last, n_supers;
281   GType type;
282   TypeNode *node;
283   guint i, node_size = 0;
284   
285   n_supers = pnode ? pnode->n_supers + 1 : 0;
286   branch_last = static_branch_seqnos[ftype]++;
287   type = G_TYPE_DERIVE_ID (ftype, branch_last);
288   g_assert ((type & G_TYPE_FLAG_RESERVED_ID_BIT) == 0);
289   if (!branch_last || g_bit_storage (branch_last - 1) < g_bit_storage (static_branch_seqnos[ftype] - 1))
290     static_type_nodes[ftype] = g_renew (TypeNode*, static_type_nodes[ftype], 1 << g_bit_storage (static_branch_seqnos[ftype] - 1));
291   
292   if (!pnode)
293     node_size += SIZEOF_FUNDAMENTAL_INFO;             /* fundamental type info */
294   node_size += SIZEOF_BASE_TYPE_NODE ();              /* TypeNode structure */
295   node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + 0 for ->supers[] */
296   node = g_malloc0 (node_size);
297   if (!pnode)                                         /* offset fundamental types */
298     node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
299   static_type_nodes[ftype][branch_last] = node;
300   
301   node->n_supers = n_supers;
302   if (!pnode)
303     {
304       node->supers[0] = type;
305       node->supers[1] = 0;
306       
307       node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
308       node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
309       
310       if (NODE_IS_IFACE (node))
311         {
312           IFACE_NODE_N_PREREQUISITES (node) = 0;
313           IFACE_NODE_PREREQUISITES (node) = NULL;
314         }
315       else
316         {
317           CLASSED_NODE_N_IFACES (node) = 0;
318           CLASSED_NODE_IFACES_ENTRIES (node) = NULL;
319         }
320     }
321   else
322     {
323       node->supers[0] = type;
324       memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
325       
326       node->is_classed = pnode->is_classed;
327       node->is_instantiatable = pnode->is_instantiatable;
328       
329       if (NODE_IS_IFACE (node))
330         {
331           IFACE_NODE_N_PREREQUISITES (node) = 0;
332           IFACE_NODE_PREREQUISITES (node) = NULL;
333         }
334       else
335         {
336           CLASSED_NODE_N_IFACES (node) = CLASSED_NODE_N_IFACES (pnode);
337           CLASSED_NODE_IFACES_ENTRIES (node) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode),
338                                                          sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode)[0]) *
339                                                          CLASSED_NODE_N_IFACES (node));
340         }
341       
342       i = pnode->n_children++;
343       pnode->children = g_renew (GType, pnode->children, pnode->n_children);
344       pnode->children[i] = type;
345     }
346   
347   node->plugin = plugin;
348   node->n_children = 0;
349   node->children = NULL;
350   node->data = NULL;
351   node->qname = g_quark_from_string (name);
352   node->global_gdata = NULL;
353   
354   g_hash_table_insert (static_type_nodes_ht,
355                        GUINT_TO_POINTER (node->qname),
356                        GUINT_TO_POINTER (type));
357   return node;
358 }
359
360 static inline GTypeFundamentalInfo*
361 type_node_fundamental_info_L (TypeNode *node)
362 {
363   GType ftype = G_TYPE_FUNDAMENTAL (NODE_TYPE (node));
364   
365   if (ftype != NODE_TYPE (node))
366     node = lookup_type_node_L (ftype);
367   
368   return node ? G_STRUCT_MEMBER_P (node, - SIZEOF_FUNDAMENTAL_INFO) : NULL;
369 }
370
371 static TypeNode*
372 type_node_fundamental_new_W (GType                 ftype,
373                              const gchar          *name,
374                              GTypeFundamentalFlags type_flags)
375 {
376   GTypeFundamentalInfo *finfo;
377   TypeNode *node;
378   guint i, flast;
379   
380   flast = static_last_fundamental_id;
381   
382   g_assert (ftype == G_TYPE_FUNDAMENTAL (ftype));
383   
384   type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
385   
386   static_last_fundamental_id = MAX (static_last_fundamental_id, ftype + 1);
387   if (static_last_fundamental_id > flast)
388     {
389       static_type_nodes = g_renew (TypeNode**, static_type_nodes, static_last_fundamental_id);
390       static_branch_seqnos = g_renew (GType, static_branch_seqnos, static_last_fundamental_id);
391       for (i = flast; i < static_last_fundamental_id; i++)
392         {
393           static_type_nodes[i] = NULL;
394           static_branch_seqnos[i] = 0;
395         }
396     }
397   g_assert (static_branch_seqnos[ftype] == 0);
398   
399   node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
400   
401   finfo = type_node_fundamental_info_L (node);
402   finfo->type_flags = type_flags;
403   
404   return node;
405 }
406
407 static TypeNode*
408 type_node_new_W (TypeNode    *pnode,
409                  const gchar *name,
410                  GTypePlugin *plugin)
411      
412 {
413   g_assert (pnode);
414   g_assert (pnode->n_supers < MAX_N_SUPERS);
415   g_assert (pnode->n_children < MAX_N_CHILDREN);
416   
417   return type_node_any_new_W (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (pnode)), name, plugin, 0);
418 }
419
420 static inline IFaceEntry*
421 type_lookup_iface_entry_L (TypeNode *node,
422                            TypeNode *iface_node)
423 {
424   if (NODE_IS_IFACE (iface_node) && CLASSED_NODE_N_IFACES (node))
425     {
426       IFaceEntry *ifaces = CLASSED_NODE_IFACES_ENTRIES (node) - 1;
427       guint n_ifaces = CLASSED_NODE_N_IFACES (node);
428       GType iface_type = NODE_TYPE (iface_node);
429       
430       do
431         {
432           guint i;
433           IFaceEntry *check;
434           
435           i = (n_ifaces + 1) >> 1;
436           check = ifaces + i;
437           if (iface_type == check->iface_type)
438             return check;
439           else if (iface_type > check->iface_type)
440             {
441               n_ifaces -= i;
442               ifaces = check;
443             }
444           else /* if (iface_type < check->iface_type) */
445             n_ifaces = i - 1;
446         }
447       while (n_ifaces);
448     }
449   
450   return NULL;
451 }
452
453 static inline gboolean
454 type_lookup_prerequisite_L (TypeNode *iface,
455                             GType     prerequisite_type)
456 {
457   if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface))
458     {
459       GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1;
460       guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface);
461
462       do
463         {
464           guint i;
465           GType *check;
466           
467           i = (n_prerequisites + 1) >> 1;
468           check = prerequisites + i;
469           if (prerequisite_type == *check)
470             return TRUE;
471           else if (prerequisite_type > *check)
472             {
473               n_prerequisites -= i;
474               prerequisites = check;
475             }
476           else /* if (prerequisite_type < *check) */
477             n_prerequisites = i - 1;
478         }
479       while (n_prerequisites);
480     }
481   return FALSE;
482 }
483
484 static inline gchar*
485 type_descriptive_name_L (GType type)
486 {
487   if (type)
488     {
489       TypeNode *node = lookup_type_node_L (type);
490       
491       return node ? NODE_NAME (node) : "<unknown>";
492     }
493   else
494     return "<invalid>";
495 }
496
497 static inline gchar*
498 type_descriptive_name_U (GType type)
499 {
500   const gchar *name;
501   
502   G_READ_LOCK (&type_rw_lock);
503   name = type_descriptive_name_L (type);
504   G_READ_UNLOCK (&type_rw_lock);
505   
506   return (gchar *)name;
507 }
508
509
510 /* --- type consistency checks --- */
511 static gboolean
512 check_plugin_U (GTypePlugin *plugin,
513                 gboolean     need_complete_type_info,
514                 gboolean     need_complete_interface_info,
515                 const gchar *type_name)
516 {
517   /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U 
518    */
519   if (!plugin)
520     {
521       g_warning ("plugin handle for type `%s' is NULL",
522                  type_name);
523       return FALSE;
524     }
525   if (!G_IS_TYPE_PLUGIN (plugin))
526     {
527       g_warning ("plugin pointer (%p) for type `%s' is invalid",
528                  plugin, type_name);
529       return FALSE;
530     }
531   if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
532     {
533       g_warning ("plugin for type `%s' has no complete_type_info() implementation",
534                  type_name);
535       return FALSE;
536     }
537   if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
538     {
539       g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
540                  type_name);
541       return FALSE;
542     }
543   return TRUE;
544 }
545
546 static gboolean
547 check_type_name_U (const gchar *type_name)
548 {
549   static const gchar *extra_chars = "-_+";
550   const gchar *p = type_name;
551   gboolean name_valid;
552   
553   if (!type_name[0] || !type_name[1] || !type_name[2])
554     {
555       g_warning ("type name `%s' is too short", type_name);
556       return FALSE;
557     }
558   /* check the first letter */
559   name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
560   for (p = type_name + 1; *p; p++)
561     name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
562                    (p[0] >= 'a' && p[0] <= 'z') ||
563                    (p[0] >= '0' && p[0] <= '9') ||
564                    strchr (extra_chars, p[0]));
565   if (!name_valid)
566     {
567       g_warning ("type name `%s' contains invalid characters", type_name);
568       return FALSE;
569     }
570   if (g_type_from_name (type_name))
571     {
572       g_warning ("cannot register existing type `%s'", type_name);
573       return FALSE;
574     }
575   
576   return TRUE;
577 }
578
579 static gboolean
580 check_derivation_U (GType        parent_type,
581                     const gchar *type_name)
582 {
583   TypeNode *pnode;
584   GTypeFundamentalInfo* finfo;
585   
586   G_READ_LOCK (&type_rw_lock);
587   pnode = lookup_type_node_L (parent_type);
588   if (!pnode)
589     {
590       G_READ_UNLOCK (&type_rw_lock);
591       g_warning ("cannot derive type `%s' from invalid parent type `%s'",
592                  type_name,
593                  type_descriptive_name_U (parent_type));
594       return FALSE;
595     }
596   finfo = type_node_fundamental_info_L (pnode);
597   /* ensure flat derivability */
598   if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
599     {
600       G_READ_UNLOCK (&type_rw_lock);
601       g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
602                  type_name,
603                  NODE_NAME (pnode));
604       return FALSE;
605     }
606   /* ensure deep derivability */
607   if (parent_type != G_TYPE_FUNDAMENTAL (parent_type) &&
608       !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
609     {
610       G_READ_UNLOCK (&type_rw_lock);
611       g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
612                  type_name,
613                  NODE_NAME (pnode));
614       return FALSE;
615     }
616   G_READ_UNLOCK (&type_rw_lock);
617   
618   return TRUE;
619 }
620
621 static gboolean
622 check_collect_format_I (const gchar *collect_format)
623 {
624   const gchar *p = collect_format;
625   gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
626                            G_VALUE_COLLECT_DOUBLE, G_VALUE_COLLECT_POINTER,
627                            0 };
628
629   while (*p)
630     if (!strchr (valid_format, *p++))
631       return FALSE;
632   return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
633 }
634
635 static gboolean
636 check_value_table_I (const gchar           *type_name,
637                      const GTypeValueTable *value_table)
638 {
639   if (!value_table)
640     return FALSE;
641   else if (value_table->value_init == NULL)
642     {
643       if (value_table->value_free || value_table->value_copy ||
644           value_table->value_peek_pointer ||
645           value_table->collect_format || value_table->collect_value ||
646           value_table->lcopy_format || value_table->lcopy_value)
647         g_warning ("cannot handle uninitializable values of type `%s'",
648                    type_name);
649       return FALSE;
650     }
651   else /* value_table->value_init != NULL */
652     {
653       if (!value_table->value_free)
654         {
655           /* +++ optional +++
656            * g_warning ("missing `value_free()' for type `%s'", type_name);
657            * return FALSE;
658            */
659         }
660       if (!value_table->value_copy)
661         {
662           g_warning ("missing `value_copy()' for type `%s'", type_name);
663           return FALSE;
664         }
665       if ((value_table->collect_format || value_table->collect_value) &&
666           (!value_table->collect_format || !value_table->collect_value))
667         {
668           g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
669                      type_name);
670           return FALSE;
671         }
672       if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
673         {
674           g_warning ("the `%s' specification for type `%s' is too long or invalid",
675                      "collect_format",
676                      type_name);
677           return FALSE;
678         }
679       if ((value_table->lcopy_format || value_table->lcopy_value) &&
680           (!value_table->lcopy_format || !value_table->lcopy_value))
681         {
682           g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
683                      type_name);
684           return FALSE;
685         }
686       if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
687         {
688           g_warning ("the `%s' specification for type `%s' is too long or invalid",
689                      "lcopy_format",
690                      type_name);
691           return FALSE;
692         }
693     }
694   return TRUE;
695 }
696
697 static gboolean
698 check_type_info_L (TypeNode        *pnode,
699                    GType            ftype,
700                    const gchar     *type_name,
701                    const GTypeInfo *info)
702 {
703   GTypeFundamentalInfo *finfo = type_node_fundamental_info_L (lookup_type_node_L (ftype));
704   gboolean is_interface = G_TYPE_IS_INTERFACE (ftype);
705   
706   /* check instance members */
707   if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
708       (info->instance_size || info->n_preallocs || info->instance_init))
709     {
710       if (pnode)
711         g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
712                    type_name,
713                    NODE_NAME (pnode));
714       else
715         g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
716                    type_name);
717       return FALSE;
718     }
719   /* check class & interface members */
720   if (!(finfo->type_flags & G_TYPE_FLAG_CLASSED) &&
721       (info->class_init || info->class_finalize || info->class_data ||
722        (!is_interface && (info->class_size || info->base_init || info->base_finalize))))
723     {
724       if (pnode)
725         g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
726                    type_name,
727                    NODE_NAME (pnode));
728       else
729         g_warning ("cannot create class for `%s' as non-classed fundamental",
730                    type_name);
731       return FALSE;
732     }
733   /* check interface size */
734   if (is_interface && info->class_size < sizeof (GTypeInterface))
735     {
736       g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
737                  type_name);
738       return FALSE;
739     }
740   /* check class size */
741   if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
742     {
743       if (info->class_size < sizeof (GTypeClass))
744         {
745           g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
746                      type_name);
747           return FALSE;
748         }
749       if (pnode && info->class_size < pnode->data->class.class_size)
750         {
751           g_warning ("specified class size for type `%s' is smaller "
752                      "than the parent type's `%s' class size",
753                      type_name,
754                      NODE_NAME (pnode));
755           return FALSE;
756         }
757     }
758   /* check instance size */
759   if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
760     {
761       if (info->instance_size < sizeof (GTypeInstance))
762         {
763           g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
764                      type_name);
765           return FALSE;
766         }
767       if (pnode && info->instance_size < pnode->data->instance.instance_size)
768         {
769           g_warning ("specified instance size for type `%s' is smaller "
770                      "than the parent type's `%s' instance size",
771                      type_name,
772                      NODE_NAME (pnode));
773           return FALSE;
774         }
775     }
776   
777   return TRUE;
778 }
779
780 static TypeNode*
781 find_conforming_type_L (TypeNode *pnode,
782                         TypeNode *iface)
783 {
784   TypeNode *node = NULL;
785   guint i;
786   
787   if (type_lookup_iface_entry_L (pnode, iface))
788     return pnode;
789   
790   for (i = 0; i < pnode->n_children && !node; i++)
791     node = find_conforming_type_L (lookup_type_node_L (pnode->children[i]), iface);
792   
793   return node;
794 }
795
796 static gboolean
797 check_add_interface_L (GType instance_type,
798                        GType iface_type)
799 {
800   TypeNode *node = lookup_type_node_L (instance_type);
801   TypeNode *iface = lookup_type_node_L (iface_type);
802   TypeNode *tnode;
803   
804   if (!node || !node->is_instantiatable)
805     {
806       g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
807                  type_descriptive_name_L (instance_type));
808       return FALSE;
809     }
810   if (!iface || !NODE_IS_IFACE (iface))
811     {
812       g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
813                  type_descriptive_name_L (iface_type),
814                  NODE_NAME (node));
815       return FALSE;
816     }
817   tnode = lookup_type_node_L (NODE_PARENT_TYPE (iface));
818   if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
819     {
820       /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
821       g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
822                  NODE_NAME (iface),
823                  NODE_NAME (node),
824                  NODE_NAME (tnode));
825       return FALSE;
826     }
827   tnode = find_conforming_type_L (node, iface);  // FIXME: iface overriding
828   if (tnode)
829     {
830       g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
831                  NODE_NAME (iface),
832                  NODE_NAME (node),
833                  NODE_NAME (tnode));
834       return FALSE;
835     }
836   return TRUE;
837 }
838
839 static gboolean
840 check_interface_info_L (TypeNode             *iface,
841                         GType                 instance_type,
842                         const GInterfaceInfo *info)
843 {
844   if ((info->interface_finalize || info->interface_data) && !info->interface_init)
845     {
846       g_warning ("interface type `%s' for type `%s' comes without initializer",
847                  NODE_NAME (iface),
848                  type_descriptive_name_L (instance_type));
849       return FALSE;
850     }
851   
852   return TRUE;
853 }
854
855 /* --- type info (type node data) --- */
856 static void
857 type_data_make_W (TypeNode              *node,
858                   const GTypeInfo       *info,
859                   const GTypeValueTable *value_table)
860 {
861   TypeData *data;
862   GTypeValueTable *vtable = NULL;
863   guint vtable_size = 0;
864   
865   g_assert (node->data == NULL && info != NULL);
866   
867   if (!value_table)
868     {
869       TypeNode *pnode = lookup_type_node_L (NODE_PARENT_TYPE (node));
870       
871       if (pnode)
872         vtable = pnode->data->common.value_table;
873       else
874         {
875           static const GTypeValueTable zero_vtable = { NULL, };
876           
877           value_table = &zero_vtable;
878         }
879     }
880   if (value_table)
881     {
882       /* need to setup vtable_size since we have to allocate it with data in one chunk */
883       vtable_size = sizeof (GTypeValueTable);
884       if (value_table->collect_format)
885         vtable_size += strlen (value_table->collect_format);
886       if (value_table->lcopy_format)
887         vtable_size += strlen (value_table->lcopy_format);
888       vtable_size += 2;
889     }
890   
891   if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
892     {
893       data = g_malloc0 (sizeof (InstanceData) + vtable_size);
894       if (vtable_size)
895         vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
896       data->instance.class_size = info->class_size;
897       data->instance.class_init_base = info->base_init;
898       data->instance.class_finalize_base = info->base_finalize;
899       data->instance.class_init = info->class_init;
900       data->instance.class_finalize = info->class_finalize;
901       data->instance.class_data = info->class_data;
902       data->instance.class = NULL;
903       data->instance.instance_size = info->instance_size;
904 #ifdef  DISABLE_MEM_POOLS
905       data->instance.n_preallocs = 0;
906 #else   /* !DISABLE_MEM_POOLS */
907       data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
908 #endif  /* !DISABLE_MEM_POOLS */
909       data->instance.instance_init = info->instance_init;
910       data->instance.mem_chunk = NULL;
911     }
912   else if (node->is_classed) /* only classed */
913     {
914       data = g_malloc0 (sizeof (ClassData) + vtable_size);
915       if (vtable_size)
916         vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
917       data->class.class_size = info->class_size;
918       data->class.class_init_base = info->base_init;
919       data->class.class_finalize_base = info->base_finalize;
920       data->class.class_init = info->class_init;
921       data->class.class_finalize = info->class_finalize;
922       data->class.class_data = info->class_data;
923       data->class.class = NULL;
924     }
925   else if (NODE_IS_IFACE (node))
926     {
927       data = g_malloc0 (sizeof (IFaceData) + vtable_size);
928       if (vtable_size)
929         vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
930       data->iface.vtable_size = info->class_size;
931       data->iface.vtable_init_base = info->base_init;
932       data->iface.vtable_finalize_base = info->base_finalize;
933     }
934   else
935     {
936       data = g_malloc0 (sizeof (CommonData) + vtable_size);
937       if (vtable_size)
938         vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
939     }
940   
941   node->data = data;
942   node->data->common.ref_count = 1;
943   
944   if (vtable_size)
945     {
946       gchar *p;
947
948       /* we allocate the vtable and its strings together with the type data, so
949        * children can take over their parent's vtable pointer, and we don't
950        * need to worry freeing it or not when the child data is destroyed
951        */
952       *vtable = *value_table;
953       p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable));
954       p[0] = 0;
955       vtable->collect_format = p;
956       if (value_table->collect_format)
957         {
958           strcat (p, value_table->collect_format);
959           p += strlen (value_table->collect_format);
960         }
961       p++;
962       p[0] = 0;
963       vtable->lcopy_format = p;
964       if (value_table->lcopy_format)
965         strcat  (p, value_table->lcopy_format);
966     }
967   node->data->common.value_table = vtable;
968   
969   g_assert (node->data->common.value_table != NULL); /* paranoid */
970 }
971
972 static inline void
973 type_data_ref_Wm (TypeNode *node)
974 {
975   if (!node->data)
976     {
977       TypeNode *pnode = lookup_type_node_L (NODE_PARENT_TYPE (node));
978       GTypeInfo tmp_info;
979       GTypeValueTable tmp_value_table;
980       
981       g_assert (node->plugin != NULL);
982       
983       if (pnode)
984         {
985           type_data_ref_Wm (pnode);
986           if (node->data)
987             INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
988         }
989       
990       memset (&tmp_info, 0, sizeof (tmp_info));
991       memset (&tmp_value_table, 0, sizeof (tmp_value_table));
992       
993       G_WRITE_UNLOCK (&type_rw_lock);
994       g_type_plugin_use (node->plugin);
995       g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
996       G_WRITE_LOCK (&type_rw_lock);
997       if (node->data)
998         INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
999       
1000       check_type_info_L (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmp_info);
1001       type_data_make_W (node, &tmp_info,
1002                         check_value_table_I (NODE_NAME (node),
1003                                              &tmp_value_table) ? &tmp_value_table : NULL);
1004     }
1005   else
1006     {
1007       g_assert (node->data->common.ref_count > 0);
1008       
1009       node->data->common.ref_count += 1;
1010     }
1011 }
1012
1013 static inline void
1014 type_data_unref_Wm (TypeNode *node,
1015                     gboolean  uncached)
1016 {
1017   g_assert (node->data && node->data->common.ref_count);
1018   
1019   if (node->data->common.ref_count > 1)
1020     node->data->common.ref_count -= 1;
1021   else
1022     {
1023       if (!node->plugin)
1024         {
1025           g_warning ("static type `%s' unreferenced too often",
1026                      NODE_NAME (node));
1027           return;
1028         }
1029       
1030       type_data_last_unref_Wm (NODE_TYPE (node), uncached);
1031     }
1032 }
1033
1034 static void
1035 type_node_add_iface_entry_W (TypeNode *node,
1036                              GType     iface_type)
1037 {
1038   IFaceEntry *entries;
1039   guint i;
1040   
1041   g_assert (node->is_instantiatable && CLASSED_NODE_N_IFACES (node) < MAX_N_IFACES);
1042   
1043   entries = CLASSED_NODE_IFACES_ENTRIES (node);
1044   for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1045     if (entries[i].iface_type == iface_type)
1046       {
1047         g_warning ("failed to add interface, type `%s' already conforms to interface type `%s'",
1048                    type_descriptive_name_L (NODE_TYPE (node)),
1049                    type_descriptive_name_L (iface_type));
1050         return;
1051       }
1052     else if (entries[i].iface_type > iface_type)
1053       break;
1054   CLASSED_NODE_N_IFACES (node) += 1;
1055   CLASSED_NODE_IFACES_ENTRIES (node) = g_renew (IFaceEntry,
1056                                                 CLASSED_NODE_IFACES_ENTRIES (node),
1057                                                 CLASSED_NODE_N_IFACES (node));
1058   entries = CLASSED_NODE_IFACES_ENTRIES (node);
1059   g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (CLASSED_NODE_N_IFACES (node) - i - 1));
1060   entries[i].iface_type = iface_type;
1061   entries[i].vtable = NULL;
1062   
1063   for (i = 0; i < node->n_children; i++)
1064     type_node_add_iface_entry_W (lookup_type_node_L (node->children[i]), iface_type);
1065 }
1066
1067 static void
1068 type_add_interface_W (TypeNode             *node,
1069                       TypeNode             *iface,
1070                       const GInterfaceInfo *info,
1071                       GTypePlugin          *plugin)
1072 {
1073   IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
1074   
1075   /* we must not call any functions of GInterfaceInfo from within here, since
1076    * we got most probably called from _within_ a type registration function
1077    */
1078   g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin)));
1079   
1080   iholder->next = iface_node_get_holders_L (iface);
1081   iface_node_set_holders_W (iface, iholder);
1082   iholder->instance_type = NODE_TYPE (node);
1083   iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
1084   iholder->plugin = plugin;
1085   
1086   type_node_add_iface_entry_W (node, NODE_TYPE (iface));
1087 }
1088
1089 static void
1090 type_iface_add_prerequisite_W (TypeNode *iface,
1091                                TypeNode *prerequisite_node)
1092 {
1093   GType prerequisite_type = NODE_TYPE (prerequisite_node);
1094   GType *prerequisites, *dependants;
1095   guint n_dependants, i;
1096
1097   g_assert (NODE_IS_IFACE (iface) &&
1098             IFACE_NODE_N_PREREQUISITES (iface) < MAX_N_PREREQUISITES &&
1099             (prerequisite_node->is_instantiatable || NODE_IS_IFACE (prerequisite_node)));
1100
1101   prerequisites = IFACE_NODE_PREREQUISITES (iface);
1102   for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1103     if (prerequisites[i] == prerequisite_type)
1104       return;                   /* we already have that prerequisiste */
1105     else if (prerequisites[i] > prerequisite_type)
1106       break;
1107   IFACE_NODE_N_PREREQUISITES (iface) += 1;
1108   IFACE_NODE_PREREQUISITES (iface) = g_renew (GType,
1109                                               IFACE_NODE_PREREQUISITES (iface),
1110                                               IFACE_NODE_N_PREREQUISITES (iface));
1111   prerequisites = IFACE_NODE_PREREQUISITES (iface);
1112   g_memmove (prerequisites + i + 1, prerequisites + i,
1113              sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1));
1114   prerequisites[i] = prerequisite_type;
1115
1116   /* we want to get notified when prerequisites get added to prerequisite_node */
1117   if (NODE_IS_IFACE (prerequisite_node))
1118     {
1119       dependants = iface_node_get_dependants_array_L (prerequisite_node);
1120       n_dependants = dependants ? dependants[0] : 0;
1121       n_dependants += 1;
1122       dependants = g_renew (GType, dependants, n_dependants + 1);
1123       dependants[n_dependants] = NODE_TYPE (iface);
1124       dependants[0] = n_dependants;
1125       iface_node_set_dependants_array_W (prerequisite_node, dependants);
1126     }
1127
1128   /* we need to notify all dependants */
1129   dependants = iface_node_get_dependants_array_L (iface);
1130   n_dependants = dependants ? dependants[0] : 0;
1131   for (i = 1; i <= n_dependants; i++)
1132     type_iface_add_prerequisite_W (lookup_type_node_L (dependants[i]), prerequisite_node);
1133 }
1134
1135 void
1136 g_type_interface_add_prerequisite (GType interface_type,
1137                                    GType prerequisite_type)
1138 {
1139   TypeNode *iface, *prerequisite_node;
1140   IFaceHolder *holders;
1141
1142   g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type));
1143   g_return_if_fail (!g_type_is_a (interface_type, prerequisite_type));
1144   g_return_if_fail (!g_type_is_a (prerequisite_type, interface_type));
1145
1146   G_WRITE_LOCK (&type_rw_lock);
1147   iface = lookup_type_node_L (interface_type);
1148   prerequisite_node = lookup_type_node_L (prerequisite_type);
1149   if (!iface || !prerequisite_node || !NODE_IS_IFACE (iface))
1150     {
1151       g_warning ("interface type `%s' or prerequisite type `%s' invalid",
1152                  type_descriptive_name_L (interface_type),
1153                  type_descriptive_name_L (prerequisite_type));
1154       G_WRITE_UNLOCK (&type_rw_lock);
1155       return;
1156     }
1157   holders = iface_node_get_holders_L (iface);
1158   if (holders)
1159     {
1160       g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'",
1161                  type_descriptive_name_L (prerequisite_type),
1162                  type_descriptive_name_L (interface_type),
1163                  type_descriptive_name_L (holders->instance_type));
1164       G_WRITE_UNLOCK (&type_rw_lock);
1165       return;
1166     }
1167   if (prerequisite_node->is_instantiatable)
1168     {
1169       guint i;
1170
1171       /* can have at most one publically installable instantiatable prerequisite */
1172       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1173         {
1174           TypeNode *prnode = lookup_type_node_L (IFACE_NODE_PREREQUISITES (iface)[i]);
1175
1176           if (prnode->is_instantiatable)
1177             {
1178               g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
1179                          type_descriptive_name_L (prerequisite_type),
1180                          type_descriptive_name_L (interface_type),
1181                          type_descriptive_name_L (NODE_TYPE (prnode)));
1182               G_WRITE_UNLOCK (&type_rw_lock);
1183               return;
1184             }
1185         }
1186
1187       for (i = 0; i < prerequisite_node->n_supers + 1; i++)
1188         type_iface_add_prerequisite_W (iface, lookup_type_node_L (prerequisite_node->supers[i]));
1189     }
1190   else if (NODE_IS_IFACE (prerequisite_node))
1191     {
1192       GType *dependants;
1193       guint n_dependants, i;
1194
1195       dependants = iface_node_get_dependants_array_L (prerequisite_node);
1196       n_dependants = dependants ? dependants[0] : 0;
1197       for (i = 1; i <= n_dependants; i++)
1198         type_iface_add_prerequisite_W (iface, lookup_type_node_L (dependants[i]));
1199       type_iface_add_prerequisite_W (iface, prerequisite_node);
1200     }
1201   else
1202     g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface",
1203                type_descriptive_name_L (prerequisite_type),
1204                type_descriptive_name_L (interface_type));
1205   G_WRITE_UNLOCK (&type_rw_lock);
1206 }
1207
1208 static IFaceHolder*
1209 type_iface_retrive_holder_info_Wm (TypeNode *iface,
1210                                    GType     instance_type)
1211 {
1212   IFaceHolder *iholder = iface_node_get_holders_L (iface);
1213   
1214   g_assert (NODE_IS_IFACE (iface));
1215   
1216   while (iholder->instance_type != instance_type)
1217     iholder = iholder->next;
1218   
1219   if (!iholder->info)
1220     {
1221       GInterfaceInfo tmp_info;
1222       
1223       g_assert (iholder->plugin != NULL);
1224       
1225       type_data_ref_Wm (iface);
1226       if (iholder->info)
1227         INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface));
1228       
1229       memset (&tmp_info, 0, sizeof (tmp_info));
1230       
1231       G_WRITE_UNLOCK (&type_rw_lock);
1232       g_type_plugin_use (iholder->plugin);
1233       g_type_plugin_complete_interface_info (iholder->plugin, instance_type, NODE_TYPE (iface), &tmp_info);
1234       G_WRITE_LOCK (&type_rw_lock);
1235       if (iholder->info)
1236         INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
1237       
1238       check_interface_info_L (iface, instance_type, &tmp_info);
1239       iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
1240     }
1241   
1242   return iholder;
1243 }
1244
1245 static void
1246 type_iface_blow_holder_info_Wm (TypeNode *iface,
1247                                 GType     instance_type)
1248 {
1249   IFaceHolder *iholder = iface_node_get_holders_L (iface);
1250   
1251   g_assert (NODE_IS_IFACE (iface));
1252   
1253   while (iholder->instance_type != instance_type)
1254     iholder = iholder->next;
1255   
1256   if (iholder->info && iholder->plugin)
1257     {
1258       g_free (iholder->info);
1259       iholder->info = NULL;
1260       
1261       G_WRITE_UNLOCK (&type_rw_lock);
1262       g_type_plugin_unuse (iholder->plugin);
1263       G_WRITE_LOCK (&type_rw_lock);
1264       
1265       type_data_unref_Wm (iface, FALSE);
1266     }
1267 }
1268
1269
1270 /* --- type structure creation/destruction --- */
1271 GTypeInstance*
1272 g_type_create_instance (GType type)
1273 {
1274   TypeNode *node;
1275   GTypeInstance *instance;
1276   GTypeClass *class;
1277   guint i;
1278   
1279   G_READ_LOCK (&type_rw_lock);
1280   node = lookup_type_node_L (type);
1281   G_READ_UNLOCK (&type_rw_lock);
1282   if (!node || !node->is_instantiatable)
1283     {
1284       g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1285                  type_descriptive_name_U (type));
1286       return NULL;
1287     }
1288   /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1289   if (G_TYPE_IS_ABSTRACT (type))
1290     {
1291       g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1292                  type_descriptive_name_U (type));
1293       return NULL;
1294     }
1295   
1296   class = g_type_class_ref (type);
1297   
1298   if (node->data->instance.n_preallocs)
1299     {
1300       G_WRITE_LOCK (&type_rw_lock);
1301       if (!node->data->instance.mem_chunk)
1302         node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
1303                                                           node->data->instance.instance_size,
1304                                                           (node->data->instance.instance_size *
1305                                                            node->data->instance.n_preallocs),
1306                                                           G_ALLOC_AND_FREE);
1307       instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
1308       G_WRITE_UNLOCK (&type_rw_lock);
1309     }
1310   else
1311     instance = g_malloc0 (node->data->instance.instance_size);  /* fine without read lock */
1312   for (i = node->n_supers; i > 0; i--)
1313     {
1314       TypeNode *pnode;
1315       
1316       G_READ_LOCK (&type_rw_lock);
1317       pnode = lookup_type_node_L (node->supers[i]);
1318       G_READ_UNLOCK (&type_rw_lock);
1319       
1320       if (pnode->data->instance.instance_init)
1321         {
1322           instance->g_class = pnode->data->instance.class;
1323           pnode->data->instance.instance_init (instance, class);
1324         }
1325     }
1326   instance->g_class = class;
1327   
1328   if (node->data->instance.instance_init)
1329     node->data->instance.instance_init (instance, class);
1330   
1331   return instance;
1332 }
1333
1334 void
1335 g_type_free_instance (GTypeInstance *instance)
1336 {
1337   TypeNode *node;
1338   GTypeClass *class;
1339   
1340   g_return_if_fail (instance != NULL && instance->g_class != NULL);
1341   
1342   G_READ_LOCK (&type_rw_lock);
1343   class = instance->g_class;
1344   node = lookup_type_node_L (class->g_type);
1345   if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
1346     {
1347       g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1348                  type_descriptive_name_L (class->g_type));
1349       G_READ_UNLOCK (&type_rw_lock);
1350       return;
1351     }
1352   G_READ_UNLOCK (&type_rw_lock);
1353   /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1354   if (G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
1355     {
1356       g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1357                  NODE_NAME (node));
1358       return;
1359     }
1360   
1361   instance->g_class = NULL;
1362   memset (instance, 0xaa, node->data->instance.instance_size);  /* FIXME: debugging hack */
1363   if (node->data->instance.n_preallocs)
1364     {
1365       G_WRITE_LOCK (&type_rw_lock);
1366       g_chunk_free (instance, node->data->instance.mem_chunk);
1367       G_WRITE_UNLOCK (&type_rw_lock);
1368     }
1369   else
1370     g_free (instance);
1371   
1372   g_type_class_unref (class);
1373 }
1374
1375 static void
1376 type_propagate_iface_vtable_W (TypeNode       *pnode,
1377                                TypeNode       *iface,
1378                                GTypeInterface *vtable)
1379 {
1380   IFaceEntry *entry = type_lookup_iface_entry_L (pnode, iface);
1381   guint i;
1382   
1383   entry->vtable = vtable;
1384   for (i = 0; i < pnode->n_children; i++)
1385     {
1386       TypeNode *node = lookup_type_node_L (pnode->children[i]);
1387       
1388       type_propagate_iface_vtable_W (node, iface, vtable);
1389     }
1390 }
1391
1392 static void
1393 type_iface_vtable_init_Wm (TypeNode *iface,
1394                            TypeNode *node)
1395 {
1396 #ifndef G_DISABLE_ASSERT
1397   IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1398 #endif
1399   IFaceHolder *iholder = type_iface_retrive_holder_info_Wm (iface, NODE_TYPE (node));
1400   GTypeInterface *vtable;
1401   
1402   g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
1403   
1404   vtable = g_malloc0 (iface->data->iface.vtable_size);
1405   type_propagate_iface_vtable_W (node, iface, vtable);
1406   vtable->g_type = NODE_TYPE (iface);
1407   vtable->g_instance_type = NODE_TYPE (node);
1408   
1409   if (iface->data->iface.vtable_init_base || iholder->info->interface_init)
1410     {
1411       G_WRITE_UNLOCK (&type_rw_lock);
1412       if (iface->data->iface.vtable_init_base)
1413         iface->data->iface.vtable_init_base (vtable);
1414       if (iholder->info->interface_init)
1415         iholder->info->interface_init (vtable, iholder->info->interface_data);
1416       G_WRITE_LOCK (&type_rw_lock);
1417     }
1418 }
1419
1420 static void
1421 type_iface_vtable_finalize_Wm (TypeNode       *iface,
1422                                TypeNode       *node,
1423                                GTypeInterface *vtable)
1424 {
1425 #ifndef G_DISABLE_ASSERT
1426   IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1427 #endif
1428   IFaceHolder *iholder = iface_node_get_holders_L (iface);
1429   
1430   g_assert (entry && entry->vtable == vtable);
1431   
1432   while (iholder->instance_type != NODE_TYPE (node))
1433     iholder = iholder->next;
1434   g_assert (iholder && iholder->info);
1435   
1436   type_propagate_iface_vtable_W (node, iface, NULL);
1437   if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
1438     {
1439       G_WRITE_UNLOCK (&type_rw_lock);
1440       if (iholder->info->interface_finalize)
1441         iholder->info->interface_finalize (vtable, iholder->info->interface_data);
1442       if (iface->data->iface.vtable_finalize_base)
1443         iface->data->iface.vtable_finalize_base (vtable);
1444       G_WRITE_LOCK (&type_rw_lock);
1445     }
1446   vtable->g_type = 0;
1447   vtable->g_instance_type = 0;
1448   g_free (vtable);
1449   
1450   type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
1451 }
1452
1453 static void
1454 type_class_init_Wm (TypeNode   *node,
1455                     GTypeClass *pclass)
1456 {
1457   GSList *slist, *init_slist = NULL;
1458   GTypeClass *class;
1459   IFaceEntry *entry;
1460   TypeNode *bnode;
1461   guint i;
1462   
1463   g_assert (node->is_classed && node->data &&
1464             node->data->class.class_size &&
1465             !node->data->class.class);
1466   
1467   class = g_malloc0 (node->data->class.class_size);
1468   node->data->class.class = class;
1469   
1470   if (pclass)
1471     {
1472       TypeNode *pnode = lookup_type_node_L (pclass->g_type);
1473       
1474       memcpy (class, pclass, pnode->data->class.class_size);
1475     }
1476   class->g_type = NODE_TYPE (node);
1477   
1478   G_WRITE_UNLOCK (&type_rw_lock);
1479   
1480   /* stack all base class initialization functions, so we
1481    * call them in ascending order.
1482    */
1483   G_READ_LOCK (&type_rw_lock);
1484   for (bnode = node; bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
1485     if (bnode->data->class.class_init_base)
1486       init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
1487   G_READ_UNLOCK (&type_rw_lock);
1488   for (slist = init_slist; slist; slist = slist->next)
1489     {
1490       GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
1491       
1492       class_init_base (class);
1493     }
1494   g_slist_free (init_slist);
1495   
1496   if (node->data->class.class_init)
1497     node->data->class.class_init (class, (gpointer) node->data->class.class_data);
1498   
1499   G_WRITE_LOCK (&type_rw_lock);
1500   
1501   /* ok, we got the class done, now initialize all interfaces */
1502   for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1503     if (!CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable)
1504       entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1505   while (entry)
1506     {
1507       type_iface_vtable_init_Wm (lookup_type_node_L (entry->iface_type), node);
1508       
1509       for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1510         if (!CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable)
1511           entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1512     }
1513 }
1514
1515 static void
1516 type_data_finalize_class_ifaces_Wm (TypeNode *node)
1517 {
1518   IFaceEntry *entry;
1519   guint i;
1520   
1521   g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
1522   
1523   g_message ("finalizing interfaces for %sClass `%s'",
1524              type_descriptive_name_L (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1525              type_descriptive_name_L (NODE_TYPE (node)));
1526   
1527   for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1528     if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable &&
1529         CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node))
1530       entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1531   while (entry)
1532     {
1533       type_iface_vtable_finalize_Wm (lookup_type_node_L (entry->iface_type), node, entry->vtable);
1534       
1535       for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1536         if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable &&
1537             CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node))
1538           entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1539     }
1540 }
1541
1542 static void
1543 type_data_finalize_class_U (TypeNode  *node,
1544                             ClassData *cdata)
1545 {
1546   GTypeClass *class = cdata->class;
1547   TypeNode *bnode;
1548   
1549   g_assert (cdata->class && cdata->common.ref_count == 0);
1550   
1551   if (cdata->class_finalize)
1552     cdata->class_finalize (class, (gpointer) cdata->class_data);
1553   
1554   /* call all base class destruction functions in descending order
1555    */
1556   if (cdata->class_finalize_base)
1557     cdata->class_finalize_base (class);
1558   G_READ_LOCK (&type_rw_lock);
1559   for (bnode = lookup_type_node_L (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
1560     if (bnode->data->class.class_finalize_base)
1561       {
1562         G_READ_UNLOCK (&type_rw_lock);
1563         bnode->data->class.class_finalize_base (class);
1564         G_READ_LOCK (&type_rw_lock);
1565       }
1566   G_READ_UNLOCK (&type_rw_lock);
1567   
1568   class->g_type = 0;
1569   g_free (cdata->class);
1570 }
1571
1572 static void
1573 type_data_last_unref_Wm (GType    type,
1574                          gboolean uncached)
1575 {
1576   TypeNode *node = lookup_type_node_L (type);
1577   
1578   g_return_if_fail (node != NULL && node->plugin != NULL);
1579   
1580   if (!node->data || node->data->common.ref_count == 0)
1581     {
1582       g_warning ("cannot drop last reference to unreferenced type `%s'",
1583                  type_descriptive_name_U (type));
1584       return;
1585     }
1586   
1587   if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs)
1588     {
1589       guint i;
1590       
1591       G_WRITE_UNLOCK (&type_rw_lock);
1592       G_READ_LOCK (&type_rw_lock);
1593       for (i = 0; i < static_n_class_cache_funcs; i++)
1594         {
1595           GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func;
1596           gpointer cache_data = static_class_cache_funcs[i].cache_data;
1597           gboolean need_break;
1598           
1599           G_READ_UNLOCK (&type_rw_lock);
1600           need_break = cache_func (cache_data, node->data->class.class);
1601           G_READ_LOCK (&type_rw_lock);
1602           if (!node->data || node->data->common.ref_count == 0)
1603             INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
1604           if (need_break)
1605             break;
1606         }
1607       G_READ_UNLOCK (&type_rw_lock);
1608       G_WRITE_LOCK (&type_rw_lock);
1609     }
1610   
1611   if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */
1612     node->data->common.ref_count -= 1;
1613   else
1614     {
1615       GType ptype = NODE_PARENT_TYPE (node);
1616       TypeData *tdata;
1617       
1618       node->data->common.ref_count = 0;
1619       
1620       if (node->is_instantiatable && node->data->instance.mem_chunk)
1621         {
1622           g_mem_chunk_destroy (node->data->instance.mem_chunk);
1623           node->data->instance.mem_chunk = NULL;
1624         }
1625       
1626       tdata = node->data;
1627       if (node->is_classed && tdata->class.class)
1628         {
1629           if (CLASSED_NODE_N_IFACES (node))
1630             type_data_finalize_class_ifaces_Wm (node);
1631           node->data = NULL;
1632           G_WRITE_UNLOCK (&type_rw_lock);
1633           type_data_finalize_class_U (node, &tdata->class);
1634           G_WRITE_LOCK (&type_rw_lock);
1635         }
1636       else
1637         node->data = NULL;
1638
1639       /* freeing tdata->common.value_table and its contents is taking care of
1640        * by allocating it in one chunk with tdata
1641        */
1642       g_free (tdata);
1643       
1644       if (ptype)
1645         type_data_unref_Wm (lookup_type_node_L (ptype), FALSE);
1646       G_WRITE_UNLOCK (&type_rw_lock);
1647       g_type_plugin_unuse (node->plugin);
1648       G_WRITE_LOCK (&type_rw_lock);
1649     }
1650 }
1651
1652 void
1653 g_type_add_class_cache_func (gpointer            cache_data,
1654                              GTypeClassCacheFunc cache_func)
1655 {
1656   guint i;
1657   
1658   g_return_if_fail (cache_func != NULL);
1659   
1660   G_WRITE_LOCK (&type_rw_lock);
1661   i = static_n_class_cache_funcs++;
1662   static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
1663   static_class_cache_funcs[i].cache_data = cache_data;
1664   static_class_cache_funcs[i].cache_func = cache_func;
1665   G_WRITE_UNLOCK (&type_rw_lock);
1666 }
1667
1668 void
1669 g_type_remove_class_cache_func (gpointer            cache_data,
1670                                 GTypeClassCacheFunc cache_func)
1671 {
1672   gboolean found_it = FALSE;
1673   guint i;
1674   
1675   g_return_if_fail (cache_func != NULL);
1676   
1677   G_WRITE_LOCK (&type_rw_lock);
1678   for (i = 0; i < static_n_class_cache_funcs; i++)
1679     if (static_class_cache_funcs[i].cache_data == cache_data &&
1680         static_class_cache_funcs[i].cache_func == cache_func)
1681       {
1682         static_n_class_cache_funcs--;
1683         g_memmove (static_class_cache_funcs + i,
1684                    static_class_cache_funcs + i + 1,
1685                    sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
1686         static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
1687         found_it = TRUE;
1688         break;
1689       }
1690   G_WRITE_UNLOCK (&type_rw_lock);
1691   
1692   if (!found_it)
1693     g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
1694                cache_func, cache_data);
1695 }
1696
1697
1698 /* --- type registration --- */
1699 GType
1700 g_type_register_fundamental (GType                       type_id,
1701                              const gchar                *type_name,
1702                              const GTypeInfo            *info,
1703                              const GTypeFundamentalInfo *finfo,
1704                              GTypeFlags                  flags)
1705 {
1706   GTypeFundamentalInfo *node_finfo;
1707   TypeNode *node;
1708   
1709   g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, 0);
1710   g_return_val_if_fail (type_id > 0, 0);
1711   g_return_val_if_fail (type_name != NULL, 0);
1712   g_return_val_if_fail (info != NULL, 0);
1713   g_return_val_if_fail (finfo != NULL, 0);
1714   
1715   if (!check_type_name_U (type_name))
1716     return 0;
1717   if (G_TYPE_FUNDAMENTAL (type_id) != type_id)
1718     {
1719       g_warning ("cannot register fundamental type `%s' with non-fundamental id (%u)",
1720                  type_name,
1721                  type_id);
1722       return 0;
1723     }
1724   if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
1725       !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
1726     {
1727       g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1728                  type_name);
1729       return 0;
1730     }
1731   G_WRITE_LOCK (&type_rw_lock);
1732   if (lookup_type_node_L (type_id))
1733     {
1734       G_WRITE_UNLOCK (&type_rw_lock);
1735       g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1736                  type_descriptive_name_U (type_id),
1737                  type_name);
1738       return 0;
1739     }
1740   
1741   node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
1742   node_finfo = type_node_fundamental_info_L (node);
1743   type_add_flags_W (node, flags);
1744   
1745   if (check_type_info_L (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
1746     type_data_make_W (node, info,
1747                       check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
1748   G_WRITE_UNLOCK (&type_rw_lock);
1749   
1750   return NODE_TYPE (node);
1751 }
1752
1753 GType
1754 g_type_register_static (GType            parent_type,
1755                         const gchar     *type_name,
1756                         const GTypeInfo *info,
1757                         GTypeFlags       flags)
1758 {
1759   TypeNode *pnode, *node;
1760   GType type = 0;
1761   
1762   g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, 0);
1763   g_return_val_if_fail (parent_type > 0, 0);
1764   g_return_val_if_fail (type_name != NULL, 0);
1765   g_return_val_if_fail (info != NULL, 0);
1766   
1767   if (!check_type_name_U (type_name) ||
1768       !check_derivation_U (parent_type, type_name))
1769     return 0;
1770   if (info->class_finalize)
1771     {
1772       g_warning ("class finalizer specified for static type `%s'",
1773                  type_name);
1774       return 0;
1775     }
1776   
1777   G_WRITE_LOCK (&type_rw_lock);
1778   pnode = lookup_type_node_L (parent_type);
1779   type_data_ref_Wm (pnode);
1780   if (check_type_info_L (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
1781     {
1782       node = type_node_new_W (pnode, type_name, NULL);
1783       type_add_flags_W (node, flags);
1784       type = NODE_TYPE (node);
1785       type_data_make_W (node, info,
1786                         check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
1787     }
1788   G_WRITE_UNLOCK (&type_rw_lock);
1789   
1790   return type;
1791 }
1792
1793 GType
1794 g_type_register_dynamic (GType        parent_type,
1795                          const gchar *type_name,
1796                          GTypePlugin *plugin,
1797                          GTypeFlags   flags)
1798 {
1799   TypeNode *pnode, *node;
1800   GType type;
1801   
1802   g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, 0);
1803   g_return_val_if_fail (parent_type > 0, 0);
1804   g_return_val_if_fail (type_name != NULL, 0);
1805   g_return_val_if_fail (plugin != NULL, 0);
1806   
1807   if (!check_type_name_U (type_name) ||
1808       !check_derivation_U (parent_type, type_name) ||
1809       !check_plugin_U (plugin, TRUE, FALSE, type_name))
1810     return 0;
1811   
1812   G_WRITE_LOCK (&type_rw_lock);
1813   pnode = lookup_type_node_L (parent_type);
1814   node = type_node_new_W (pnode, type_name, plugin);
1815   type_add_flags_W (node, flags);
1816   type = NODE_TYPE (node);
1817   G_WRITE_UNLOCK (&type_rw_lock);
1818   
1819   return type;
1820 }
1821
1822 void
1823 g_type_add_interface_static (GType                 instance_type,
1824                              GType                 interface_type,
1825                              const GInterfaceInfo *info)
1826 {
1827   /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1828   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1829   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1830   
1831   G_WRITE_LOCK (&type_rw_lock);
1832   if (check_add_interface_L (instance_type, interface_type))
1833     {
1834       TypeNode *node = lookup_type_node_L (instance_type);
1835       TypeNode *iface = lookup_type_node_L (interface_type);
1836       
1837       if (check_interface_info_L (iface, NODE_TYPE (node), info))
1838         type_add_interface_W (node, iface, info, NULL);
1839     }
1840   G_WRITE_UNLOCK (&type_rw_lock);
1841 }
1842
1843 void
1844 g_type_add_interface_dynamic (GType        instance_type,
1845                               GType        interface_type,
1846                               GTypePlugin *plugin)
1847 {
1848   TypeNode *node;
1849   
1850   /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1851   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1852   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1853   
1854   G_READ_LOCK (&type_rw_lock);
1855   node = lookup_type_node_L (instance_type);
1856   G_READ_UNLOCK (&type_rw_lock);
1857   if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
1858     return;
1859   
1860   G_WRITE_LOCK (&type_rw_lock);
1861   if (check_add_interface_L (instance_type, interface_type))
1862     {
1863       TypeNode *iface = lookup_type_node_L (interface_type);
1864       
1865       type_add_interface_W (node, iface, NULL, plugin);
1866     }
1867   G_WRITE_UNLOCK (&type_rw_lock);
1868 }
1869
1870
1871 /* --- public API functions --- */
1872 gpointer
1873 g_type_class_ref (GType type)
1874 {
1875   TypeNode *node;
1876   
1877   /* optimize for common code path
1878    */
1879   G_WRITE_LOCK (&type_rw_lock);
1880   node = lookup_type_node_L (type);
1881   if (node && node->is_classed && node->data &&
1882       node->data->class.class && node->data->common.ref_count > 0)
1883     {
1884       type_data_ref_Wm (node);
1885       G_WRITE_UNLOCK (&type_rw_lock);
1886       
1887       return node->data->class.class;
1888     }
1889   
1890   if (!node || !node->is_classed ||
1891       (node->data && node->data->common.ref_count < 1))
1892     {
1893       G_WRITE_UNLOCK (&type_rw_lock);
1894       g_warning ("cannot retrive class for invalid (unclassed) type `%s'",
1895                  type_descriptive_name_U (type));
1896       return NULL;
1897     }
1898   
1899   type_data_ref_Wm (node);
1900   
1901   if (!node->data->class.class)
1902     {
1903       GType ptype = NODE_PARENT_TYPE (node);
1904       GTypeClass *pclass = NULL;
1905       
1906       if (ptype)
1907         {
1908           G_WRITE_UNLOCK (&type_rw_lock);
1909           pclass = g_type_class_ref (ptype);
1910           if (node->data->class.class)
1911             INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1912           G_WRITE_LOCK (&type_rw_lock);
1913         }
1914       
1915       type_class_init_Wm (node, pclass);
1916     }
1917   G_WRITE_UNLOCK (&type_rw_lock);
1918   
1919   return node->data->class.class;
1920 }
1921
1922 void
1923 g_type_class_unref (gpointer g_class)
1924 {
1925   TypeNode *node;
1926   GTypeClass *class = g_class;
1927   
1928   g_return_if_fail (g_class != NULL);
1929   
1930   G_WRITE_LOCK (&type_rw_lock);
1931   node = lookup_type_node_L (class->g_type);
1932   if (node && node->is_classed && node->data &&
1933       node->data->class.class == class && node->data->common.ref_count > 0)
1934     type_data_unref_Wm (node, FALSE);
1935   else
1936     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1937                type_descriptive_name_L (class->g_type));
1938   G_WRITE_UNLOCK (&type_rw_lock);
1939 }
1940
1941 void
1942 g_type_class_unref_uncached (gpointer g_class)
1943 {
1944   TypeNode *node;
1945   GTypeClass *class = g_class;
1946   
1947   g_return_if_fail (g_class != NULL);
1948   
1949   G_WRITE_LOCK (&type_rw_lock);
1950   node = lookup_type_node_L (class->g_type);
1951   if (node && node->is_classed && node->data &&
1952       node->data->class.class == class && node->data->common.ref_count > 0)
1953     type_data_unref_Wm (node, TRUE);
1954   else
1955     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1956                type_descriptive_name_L (class->g_type));
1957   G_WRITE_UNLOCK (&type_rw_lock);
1958 }
1959
1960 gpointer
1961 g_type_class_peek (GType type)
1962 {
1963   TypeNode *node;
1964   gpointer class;
1965   
1966   G_READ_LOCK (&type_rw_lock);
1967   node = lookup_type_node_L (type);
1968   if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
1969     class = node->data->class.class;
1970   else
1971     class = NULL;
1972   G_READ_UNLOCK (&type_rw_lock);
1973   
1974   return class;
1975 }
1976
1977 gpointer
1978 g_type_class_peek_parent (gpointer g_class)
1979 {
1980   TypeNode *node;
1981   gpointer class;
1982   
1983   g_return_val_if_fail (g_class != NULL, NULL);
1984   
1985   G_READ_LOCK (&type_rw_lock);
1986   node = lookup_type_node_L (G_TYPE_FROM_CLASS (g_class));
1987   if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
1988     {
1989       node = lookup_type_node_L (NODE_PARENT_TYPE (node));
1990       class = node->data->class.class;
1991     }
1992   else
1993     class = NULL;
1994   G_READ_UNLOCK (&type_rw_lock);
1995   
1996   return class;
1997 }
1998
1999 gpointer
2000 g_type_interface_peek (gpointer instance_class,
2001                        GType    iface_type)
2002 {
2003   TypeNode *node;
2004   TypeNode *iface;
2005   gpointer vtable = NULL;
2006   GTypeClass *class = instance_class;
2007   
2008   g_return_val_if_fail (instance_class != NULL, NULL);
2009   
2010   G_READ_LOCK (&type_rw_lock);
2011   node = lookup_type_node_L (class->g_type);
2012   iface = lookup_type_node_L (iface_type);
2013   if (node && node->is_instantiatable && iface)
2014     {
2015       IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
2016       
2017       if (entry && entry->vtable)
2018         vtable = entry->vtable;
2019     }
2020   G_READ_UNLOCK (&type_rw_lock);
2021   
2022   return vtable;
2023 }
2024
2025 G_CONST_RETURN gchar*
2026 g_type_name (GType type)
2027 {
2028   TypeNode *node;
2029   
2030   g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, NULL);
2031
2032   G_READ_LOCK (&type_rw_lock);
2033   node = lookup_type_node_L (type);
2034   G_READ_UNLOCK (&type_rw_lock);
2035   
2036   return node ? NODE_NAME (node) : NULL;
2037 }
2038
2039 GQuark
2040 g_type_qname (GType type)
2041 {
2042   TypeNode *node;
2043   
2044   G_READ_LOCK (&type_rw_lock);
2045   node = lookup_type_node_L (type);
2046   G_READ_UNLOCK (&type_rw_lock);
2047   
2048   return node ? node->qname : 0;
2049 }
2050
2051 GType
2052 g_type_from_name (const gchar *name)
2053 {
2054   GType type = 0;
2055   GQuark quark;
2056   
2057   g_return_val_if_fail (name != NULL, 0);
2058   
2059   quark = g_quark_try_string (name);
2060   if (quark)
2061     {
2062       G_READ_LOCK (&type_rw_lock);
2063       type = GPOINTER_TO_UINT (g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark)));
2064       G_READ_UNLOCK (&type_rw_lock);
2065     }
2066   
2067   return type;
2068 }
2069
2070 GType
2071 g_type_parent (GType type)
2072 {
2073   TypeNode *node;
2074   
2075   G_READ_LOCK (&type_rw_lock);
2076   node = lookup_type_node_L (type);
2077   G_READ_UNLOCK (&type_rw_lock);
2078   
2079   return node ? NODE_PARENT_TYPE (node) : 0;
2080 }
2081
2082 guint
2083 g_type_depth (GType type)
2084 {
2085   TypeNode *node;
2086   
2087   G_READ_LOCK (&type_rw_lock);
2088   node = lookup_type_node_L (type);
2089   G_READ_UNLOCK (&type_rw_lock);
2090   
2091   return node ? node->n_supers + 1 : 0;
2092 }
2093
2094 GType
2095 g_type_next_base (GType type,
2096                   GType base_type)
2097 {
2098   GType atype = 0;
2099   TypeNode *node;
2100   
2101   G_READ_LOCK (&type_rw_lock);
2102   node = lookup_type_node_L (type);
2103   if (node)
2104     {
2105       TypeNode *base_node = lookup_type_node_L (base_type);
2106       
2107       if (base_node && base_node->n_supers < node->n_supers)
2108         {
2109           guint n = node->n_supers - base_node->n_supers;
2110           
2111           if (node->supers[n] == base_type)
2112             atype = node->supers[n - 1];
2113         }
2114     }
2115   G_READ_UNLOCK (&type_rw_lock);
2116   
2117   return atype;
2118 }
2119
2120 static inline gboolean
2121 type_node_is_a_L (TypeNode *node,
2122                   TypeNode *iface_node,
2123                   /*        support_inheritance */
2124                   gboolean  support_interfaces,
2125                   gboolean  support_prerequisites)
2126 {
2127   if (support_interfaces &&
2128       node->is_instantiatable && NODE_IS_IFACE (iface_node) &&
2129       type_lookup_iface_entry_L (node, iface_node) != NULL)
2130     return TRUE;
2131   else if (/* support_inheritance && */
2132            iface_node->n_supers <= node->n_supers &&
2133            node->supers[node->n_supers - iface_node->n_supers] == NODE_TYPE (iface_node))
2134     return TRUE;
2135   else if (support_prerequisites &&
2136            NODE_IS_IFACE (node) &&
2137            type_lookup_prerequisite_L (node, NODE_TYPE (iface_node)))
2138     return TRUE;
2139   else
2140     return FALSE;
2141 }
2142
2143 gboolean
2144 g_type_is_a (GType type,
2145              GType iface_type)
2146 {
2147   TypeNode *node, *iface_node;
2148   gboolean is_a;
2149
2150   G_READ_LOCK (&type_rw_lock);
2151   node = lookup_type_node_L (type);
2152   iface_node = lookup_type_node_L (iface_type);
2153   is_a = node && iface_node && type_node_is_a_L (node, iface_node, TRUE, TRUE);
2154   G_READ_UNLOCK (&type_rw_lock);
2155
2156   return is_a;
2157 }
2158
2159 guint
2160 g_type_fundamental_branch_last (GType type)
2161 {
2162   GType ftype = G_TYPE_FUNDAMENTAL (type);
2163   guint last_type;
2164   
2165   G_READ_LOCK (&type_rw_lock);
2166   last_type = ftype < static_last_fundamental_id ? static_branch_seqnos[ftype] : 0;
2167   G_READ_UNLOCK (&type_rw_lock);
2168   
2169   return last_type;
2170 }
2171
2172 GType* /* free result */
2173 g_type_children (GType  type,
2174                  guint *n_children)
2175 {
2176   TypeNode *node;
2177   
2178   G_READ_LOCK (&type_rw_lock);
2179   node = lookup_type_node_L (type);
2180   if (node)
2181     {
2182       GType *children = g_new (GType, node->n_children + 1);
2183       
2184       memcpy (children, node->children, sizeof (GType) * node->n_children);
2185       children[node->n_children] = 0;
2186       
2187       if (n_children)
2188         *n_children = node->n_children;
2189       G_READ_UNLOCK (&type_rw_lock);
2190       
2191       return children;
2192     }
2193   else
2194     {
2195       G_READ_UNLOCK (&type_rw_lock);
2196       if (n_children)
2197         *n_children = 0;
2198       
2199       return NULL;
2200     }
2201 }
2202
2203 GType* /* free result */
2204 g_type_interfaces (GType  type,
2205                    guint *n_interfaces)
2206 {
2207   TypeNode *node;
2208   
2209   G_READ_LOCK (&type_rw_lock);
2210   node = lookup_type_node_L (type);
2211   if (node && node->is_instantiatable)
2212     {
2213       GType *ifaces = g_new (GType, CLASSED_NODE_N_IFACES (node) + 1);
2214       guint i;
2215       
2216       for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
2217         ifaces[i] = CLASSED_NODE_IFACES_ENTRIES (node)[i].iface_type;
2218       ifaces[i] = 0;
2219       
2220       if (n_interfaces)
2221         *n_interfaces = CLASSED_NODE_N_IFACES (node);
2222       G_READ_UNLOCK (&type_rw_lock);
2223       
2224       return ifaces;
2225     }
2226   else
2227     {
2228       G_READ_UNLOCK (&type_rw_lock);
2229       if (n_interfaces)
2230         *n_interfaces = 0;
2231       
2232       return NULL;
2233     }
2234 }
2235
2236 typedef struct _QData QData;
2237 struct _GData
2238 {
2239   guint  n_qdatas;
2240   QData *qdatas;
2241 };
2242 struct _QData
2243 {
2244   GQuark   quark;
2245   gpointer data;
2246 };
2247
2248 static inline gpointer
2249 type_get_qdata_L (TypeNode *node,
2250                   GQuark    quark)
2251 {
2252   GData *gdata = node->global_gdata;
2253   
2254   if (quark && gdata && gdata->n_qdatas)
2255     {
2256       QData *qdatas = gdata->qdatas - 1;
2257       guint n_qdatas = gdata->n_qdatas;
2258       
2259       do
2260         {
2261           guint i;
2262           QData *check;
2263           
2264           i = (n_qdatas + 1) / 2;
2265           check = qdatas + i;
2266           if (quark == check->quark)
2267             return check->data;
2268           else if (quark > check->quark)
2269             {
2270               n_qdatas -= i;
2271               qdatas = check;
2272             }
2273           else /* if (quark < check->quark) */
2274             n_qdatas = i - 1;
2275         }
2276       while (n_qdatas);
2277     }
2278   return NULL;
2279 }
2280
2281 gpointer
2282 g_type_get_qdata (GType  type,
2283                   GQuark quark)
2284 {
2285   TypeNode *node;
2286   gpointer data;
2287   
2288   G_READ_LOCK (&type_rw_lock);
2289   node = lookup_type_node_L (type);
2290   if (node)
2291     {
2292       data = type_get_qdata_L (node, quark);
2293       G_READ_UNLOCK (&type_rw_lock);
2294     }
2295   else
2296     {
2297       G_READ_UNLOCK (&type_rw_lock);
2298       g_return_val_if_fail (node != NULL, NULL);
2299       data = NULL;
2300     }
2301   return data;
2302 }
2303
2304 static inline void
2305 type_set_qdata_W (TypeNode *node,
2306                   GQuark    quark,
2307                   gpointer  data)
2308 {
2309   GData *gdata;
2310   QData *qdata;
2311   guint i;
2312   
2313   /* setup qdata list if necessary */
2314   if (!node->global_gdata)
2315     node->global_gdata = g_new0 (GData, 1);
2316   gdata = node->global_gdata;
2317   
2318   /* try resetting old data */
2319   qdata = gdata->qdatas;
2320   for (i = 0; i < gdata->n_qdatas; i++)
2321     if (qdata[i].quark == quark)
2322       {
2323         qdata[i].data = data;
2324         return;
2325       }
2326   
2327   /* add new entry */
2328   gdata->n_qdatas++;
2329   gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
2330   qdata = gdata->qdatas;
2331   for (i = 0; i < gdata->n_qdatas - 1; i++)
2332     if (qdata[i].quark > quark)
2333       break;
2334   g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
2335   qdata[i].quark = quark;
2336   qdata[i].data = data;
2337 }
2338
2339 void
2340 g_type_set_qdata (GType    type,
2341                   GQuark   quark,
2342                   gpointer data)
2343 {
2344   TypeNode *node;
2345   
2346   g_return_if_fail (quark != 0);
2347   
2348   G_WRITE_LOCK (&type_rw_lock);
2349   node = lookup_type_node_L (type);
2350   if (node)
2351     {
2352       type_set_qdata_W (node, quark, data);
2353       G_WRITE_UNLOCK (&type_rw_lock);
2354     }
2355   else
2356     {
2357       G_WRITE_UNLOCK (&type_rw_lock);
2358       g_return_if_fail (node != NULL);
2359     }
2360 }
2361
2362 static void
2363 type_add_flags_W (TypeNode  *node,
2364                   GTypeFlags flags)
2365 {
2366   guint dflags;
2367   
2368   g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
2369   g_return_if_fail (node != NULL);
2370   
2371   if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class)
2372     g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
2373   dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
2374   dflags |= flags;
2375   type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
2376 }
2377
2378 void
2379 g_type_query (GType       type,
2380               GTypeQuery *query)
2381 {
2382   TypeNode *node;
2383
2384   g_return_if_fail (query != NULL);
2385   
2386   G_READ_LOCK (&type_rw_lock);
2387   node = lookup_type_node_L (type);
2388   if (node && node->is_classed && !node->plugin && node->data)
2389     {
2390       /* type is classed and static, probably even instantiatable */
2391
2392       query->type = NODE_TYPE (node);
2393       query->type_name = NODE_NAME (node);
2394       query->class_size = node->data->class.class_size;
2395       query->instance_size = node->is_instantiatable ? node->data->instance.instance_size : 0;
2396     }
2397   else
2398     {
2399       /* node is not static and classed, won't allow query */
2400       query->type = 0;
2401     }
2402   G_READ_UNLOCK (&type_rw_lock);
2403 }
2404
2405
2406 /* --- implementation details --- */
2407 gboolean
2408 g_type_check_flags (GType type,
2409                     guint flags)
2410 {
2411   TypeNode *node;
2412   gboolean result = FALSE;
2413   
2414   G_READ_LOCK (&type_rw_lock);
2415   node = lookup_type_node_L (type);
2416   if (node)
2417     {
2418       guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
2419       guint tflags = flags & TYPE_FLAG_MASK;
2420       
2421       if (fflags)
2422         {
2423           GTypeFundamentalInfo *finfo = type_node_fundamental_info_L (node);
2424           
2425           fflags = (finfo->type_flags & fflags) == fflags;
2426         }
2427       else
2428         fflags = TRUE;
2429       
2430       if (tflags)
2431         tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
2432       else
2433         tflags = TRUE;
2434       
2435       result = tflags && fflags;
2436     }
2437   G_READ_UNLOCK (&type_rw_lock);
2438   
2439   return result;
2440 }
2441
2442 GTypePlugin*
2443 g_type_get_plugin (GType type)
2444 {
2445   TypeNode *node;
2446   
2447   G_READ_LOCK (&type_rw_lock);
2448   node = lookup_type_node_L (type);
2449   G_READ_UNLOCK (&type_rw_lock);
2450   
2451   return node ? node->plugin : NULL;
2452 }
2453
2454 GTypePlugin*
2455 g_type_interface_get_plugin (GType instance_type,
2456                              GType interface_type)
2457 {
2458   TypeNode *node;
2459   TypeNode *iface;
2460   
2461   g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
2462   
2463   G_READ_LOCK (&type_rw_lock);
2464   node = lookup_type_node_L (instance_type);  
2465   iface = lookup_type_node_L (interface_type);
2466   if (node && iface)
2467     {
2468       IFaceHolder *iholder = iface_node_get_holders_L (iface);
2469       
2470       while (iholder && iholder->instance_type != instance_type)
2471         iholder = iholder->next;
2472       G_READ_UNLOCK (&type_rw_lock);
2473       
2474       if (iholder)
2475         return iholder->plugin;
2476     }
2477   else
2478     G_READ_UNLOCK (&type_rw_lock);
2479   
2480   g_return_val_if_fail (node == NULL, NULL);
2481   g_return_val_if_fail (iface == NULL, NULL);
2482   
2483   g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
2484   
2485   return NULL;
2486 }
2487
2488 GType
2489 g_type_fundamental_last (void)
2490 {
2491   GType type;
2492   
2493   G_READ_LOCK (&type_rw_lock);
2494   type = static_last_fundamental_id;
2495   G_READ_UNLOCK (&type_rw_lock);
2496   
2497   return type;
2498 }
2499
2500 gboolean
2501 g_type_instance_is_a (GTypeInstance *type_instance,
2502                       GType          iface_type)
2503 {
2504   TypeNode *node, *iface;
2505   gboolean check;
2506
2507   if (!type_instance || !type_instance->g_class)
2508     return FALSE;
2509
2510   G_READ_LOCK (&type_rw_lock);
2511   node = lookup_type_node_L (type_instance->g_class->g_type);
2512   iface = lookup_type_node_L (iface_type);
2513   check = node && node->is_instantiatable && iface && type_node_is_a_L (node, iface, TRUE, FALSE);
2514   G_READ_UNLOCK (&type_rw_lock);
2515
2516   return check;
2517 }
2518
2519 gboolean
2520 g_type_class_is_a (GTypeClass *type_class,
2521                    GType       is_a_type)
2522 {
2523   TypeNode *node, *iface;
2524   gboolean check;
2525
2526   if (!type_class)
2527     return FALSE;
2528
2529   G_READ_LOCK (&type_rw_lock);
2530   node = lookup_type_node_L (type_class->g_type);
2531   iface = lookup_type_node_L (is_a_type);
2532   check = node && node->is_classed && iface && type_node_is_a_L (node, iface, FALSE, FALSE);
2533   G_READ_UNLOCK (&type_rw_lock);
2534
2535   return check;
2536 }
2537
2538 GTypeInstance*
2539 g_type_check_instance_cast (GTypeInstance *type_instance,
2540                             GType          iface_type)
2541 {
2542   if (type_instance)
2543     {
2544       if (type_instance->g_class)
2545         {
2546           TypeNode *node, *iface;
2547           gboolean is_instantiatable, check;
2548
2549           G_READ_LOCK (&type_rw_lock);
2550           node = lookup_type_node_L (type_instance->g_class->g_type);
2551           is_instantiatable = node && node->is_instantiatable;
2552           iface = lookup_type_node_L (iface_type);
2553           check = is_instantiatable && iface && type_node_is_a_L (node, iface, TRUE, FALSE);
2554           G_READ_UNLOCK (&type_rw_lock);
2555           if (check)
2556             return type_instance;
2557
2558           if (is_instantiatable)
2559             g_warning ("invalid cast from `%s' to `%s'",
2560                        type_descriptive_name_U (type_instance->g_class->g_type),
2561                        type_descriptive_name_U (iface_type));
2562           else
2563             g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
2564                        type_descriptive_name_U (type_instance->g_class->g_type),
2565                        type_descriptive_name_U (iface_type));
2566         }
2567       else
2568         g_warning ("invalid unclassed pointer in cast to `%s'",
2569                    type_descriptive_name_U (iface_type));
2570     }
2571   else
2572     g_warning ("invalid cast from (NULL) pointer to `%s'",
2573                type_descriptive_name_U (iface_type));
2574   
2575   return type_instance;
2576 }
2577
2578 GTypeClass*
2579 g_type_check_class_cast (GTypeClass *type_class,
2580                          GType       is_a_type)
2581 {
2582   if (type_class)
2583     {
2584       TypeNode *node, *iface;
2585       gboolean is_classed, check;
2586       
2587       G_READ_LOCK (&type_rw_lock);
2588       node = lookup_type_node_L (type_class->g_type);
2589       is_classed = node && node->is_classed;
2590       iface = lookup_type_node_L (is_a_type);
2591       check = is_classed && iface && type_node_is_a_L (node, iface, FALSE, FALSE);
2592       G_READ_UNLOCK (&type_rw_lock);
2593       if (check)
2594         return type_class;
2595
2596       if (is_classed)
2597         g_warning ("invalid class cast from `%s' to `%s'",
2598                    type_descriptive_name_U (type_class->g_type),
2599                    type_descriptive_name_U (is_a_type));
2600       else
2601         g_warning ("invalid unclassed type `%s' in class cast to `%s'",
2602                    type_descriptive_name_U (type_class->g_type),
2603                    type_descriptive_name_U (is_a_type));
2604     }
2605   else
2606     g_warning ("invalid class cast from (NULL) pointer to `%s'",
2607                type_descriptive_name_U (is_a_type));
2608   return type_class;
2609 }
2610
2611 gboolean
2612 g_type_check_instance (GTypeInstance *type_instance)
2613 {
2614   /* this function is just here to make the signal system
2615    * conveniently elaborated on instance checks
2616    */
2617   if (type_instance)
2618     {
2619       if (type_instance->g_class)
2620         {
2621           TypeNode *node;
2622           gboolean is_instantiatable;
2623           
2624           G_READ_LOCK (&type_rw_lock);
2625           node = lookup_type_node_L (type_instance->g_class->g_type);
2626           is_instantiatable = node && node->is_instantiatable;
2627           G_READ_UNLOCK (&type_rw_lock);
2628           if (is_instantiatable)
2629             return TRUE;
2630
2631           g_warning ("instance of invalid non-instantiatable type `%s'",
2632                      type_descriptive_name_U (type_instance->g_class->g_type));
2633         }
2634       else
2635         g_warning ("instance with invalid (NULL) class pointer");
2636     }
2637   else
2638     g_warning ("invalid (NULL) pointer instance");
2639
2640   return FALSE;
2641 }
2642
2643 static inline gboolean
2644 type_check_is_value_type_U (GType type)
2645 {
2646   GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT;
2647   TypeNode *node;
2648
2649   G_READ_LOCK (&type_rw_lock);
2650  restart_check:
2651   node = lookup_type_node_L (type);
2652   if (node)
2653     {
2654       if (node->data && node->data->common.ref_count > 0 &&
2655           node->data->common.value_table->value_init)
2656         tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
2657       else if (NODE_IS_IFACE (node))
2658         {
2659           guint i;
2660
2661           for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
2662             {
2663               GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
2664               TypeNode *prnode = lookup_type_node_L (prtype);
2665
2666               if (prnode->is_instantiatable)
2667                 {
2668                   type = prtype;
2669                   goto restart_check;
2670                 }
2671             }
2672         }
2673     }
2674   G_READ_UNLOCK (&type_rw_lock);
2675
2676   return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT);
2677 }
2678
2679 gboolean
2680 g_type_check_is_value_type (GType type)
2681 {
2682   return type_check_is_value_type_U (type);
2683 }
2684
2685 gboolean
2686 g_type_check_value (GValue *value)
2687 {
2688   return value && type_check_is_value_type_U (value->g_type);
2689 }
2690
2691 gboolean
2692 g_type_check_value_holds (GValue *value,
2693                           GType   type)
2694 {
2695   return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type);
2696 }
2697
2698 GTypeValueTable*
2699 g_type_value_table_peek (GType type)
2700 {
2701   TypeNode *node;
2702   GTypeValueTable *vtable;
2703   
2704   G_READ_LOCK (&type_rw_lock);
2705  restart_table_peek:
2706   node = lookup_type_node_L (type);
2707   if (!node)
2708     {
2709       g_warning (G_STRLOC ": type id `%u' is invalid", type);
2710       G_READ_UNLOCK (&type_rw_lock);
2711       return NULL;
2712     }
2713   if (!node->data || node->data->common.ref_count < 1)
2714     {
2715       g_warning ("can't peek value table for type `%s' which is not currently referenced",
2716                  type_descriptive_name_L (type));
2717       G_READ_UNLOCK (&type_rw_lock);
2718       return NULL;
2719     }
2720   if (node->data->common.value_table->value_init)
2721     vtable = node->data->common.value_table;
2722   else if (NODE_IS_IFACE (node))
2723     {
2724       guint i;
2725
2726       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
2727         {
2728           GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
2729           TypeNode *prnode = lookup_type_node_L (prtype);
2730
2731           if (prnode->is_instantiatable)
2732             {
2733               type = prtype;
2734               goto restart_table_peek;
2735             }
2736         }
2737       vtable = NULL;
2738     }
2739   else
2740     vtable = NULL;
2741   G_READ_UNLOCK (&type_rw_lock);
2742   
2743   return vtable;
2744 }
2745
2746 G_CONST_RETURN gchar*
2747 g_type_name_from_instance (GTypeInstance *instance)
2748 {
2749   if (!instance)
2750     return "<NULL-instance>";
2751   else
2752     return g_type_name_from_class (instance->g_class);
2753 }
2754
2755 G_CONST_RETURN gchar*
2756 g_type_name_from_class (GTypeClass *g_class)
2757 {
2758   if (!g_class)
2759     return "<NULL-class>";
2760   else
2761     return g_type_name (g_class->g_type);
2762 }
2763
2764
2765 /* --- foreign prototypes --- */
2766 extern void     g_value_types_init      (void); /* sync with gvaluetypes.c */
2767 extern void     g_enum_types_init       (void); /* sync with genums.c */
2768 extern void     g_param_type_init       (void); /* sync with gparam.c */
2769 extern void     g_boxed_type_init       (void); /* sync with gboxed.c */
2770 extern void     g_object_type_init      (void); /* sync with gobject.c */
2771 extern void     g_param_spec_types_init (void); /* sync with gparamspecs.c */
2772 extern void     g_value_transforms_init (void); /* sync with gvaluetransform.c */
2773 extern void     g_signal_init           (void); /* sync with gsignal.c */
2774
2775
2776 /* --- initialization --- */
2777 void
2778 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
2779 {
2780   G_LOCK_DEFINE_STATIC (type_init_lock);
2781   static TypeNode *type0_node = NULL;
2782   const gchar *env_string;
2783   GTypeInfo info;
2784   TypeNode *node;
2785   GType type;
2786   
2787   G_LOCK (type_init_lock);
2788   
2789   G_WRITE_LOCK (&type_rw_lock);
2790   
2791   if (static_last_fundamental_id)
2792     {
2793       G_WRITE_UNLOCK (&type_rw_lock);
2794       G_UNLOCK (type_init_lock);
2795       return;
2796     }
2797
2798   /* setup GRuntime wide debugging flags */
2799   _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
2800   env_string = g_getenv ("GRUNTIME_DEBUG");
2801   if (env_string != NULL)
2802     {
2803       static GDebugKey debug_keys[] = {
2804         { "objects", G_TYPE_DEBUG_OBJECTS },
2805         { "signals", G_TYPE_DEBUG_SIGNALS },
2806       };
2807
2808       _g_type_debug_flags |= g_parse_debug_string (env_string,
2809                                                    debug_keys,
2810                                                    sizeof (debug_keys) / sizeof (debug_keys[0]));
2811       env_string = NULL;
2812     }
2813   
2814   /* quarks */
2815   static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
2816   static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
2817   static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
2818   
2819   /* type qname hash table */
2820   static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
2821   
2822   /* invalid type G_TYPE_INVALID (0)
2823    */
2824   static_last_fundamental_id = 1;
2825   static_type_nodes = g_renew (TypeNode**, static_type_nodes, static_last_fundamental_id);
2826   static_type_nodes[0] = &type0_node;
2827   static_branch_seqnos = g_renew (GType, static_branch_seqnos, static_last_fundamental_id);
2828   static_branch_seqnos[0] = 1;
2829   
2830   /* void type G_TYPE_NONE
2831    */
2832   node = type_node_fundamental_new_W (G_TYPE_NONE, "void", 0);
2833   type = NODE_TYPE (node);
2834   g_assert (type == G_TYPE_NONE);
2835   
2836   /* interface fundamental type G_TYPE_INTERFACE (!classed)
2837    */
2838   memset (&info, 0, sizeof (info));
2839   node = type_node_fundamental_new_W (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
2840   type = NODE_TYPE (node);
2841   type_data_make_W (node, &info, NULL);
2842   g_assert (type == G_TYPE_INTERFACE);
2843   
2844   G_WRITE_UNLOCK (&type_rw_lock);
2845   
2846   /* G_TYPE_TYPE_PLUGIN
2847    */
2848   g_type_plugin_get_type ();
2849   
2850   /* G_TYPE_* value types
2851    */
2852   g_value_types_init ();
2853   
2854   /* G_TYPE_ENUM & G_TYPE_FLAGS
2855    */
2856   g_enum_types_init ();
2857   
2858   /* G_TYPE_BOXED
2859    */
2860   g_boxed_type_init ();
2861   
2862   /* G_TYPE_PARAM
2863    */
2864   g_param_type_init ();
2865   
2866   /* G_TYPE_OBJECT
2867    */
2868   g_object_type_init ();
2869   
2870   /* G_TYPE_PARAM_* pspec types
2871    */
2872   g_param_spec_types_init ();
2873   
2874   /* Value Transformations
2875    */
2876   g_value_transforms_init ();
2877
2878   /* Signal system
2879    */
2880   g_signal_init ();
2881   
2882   G_UNLOCK (type_init_lock);
2883 }
2884
2885 void 
2886 g_type_init (void)
2887 {
2888   g_type_init_with_debug_flags (0);
2889 }