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