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