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