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