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