87530595b4ca5232a4e5c68b52b3c95bf58a0198
[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)                         (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 < IFACE_NODE_N_PREREQUISITES (iface); i++)
1168         {
1169           TypeNode *prnode = lookup_type_node_L (IFACE_NODE_PREREQUISITES (iface)[i]);
1170
1171           if (prnode->is_instantiatable)
1172             {
1173               g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
1174                          type_descriptive_name_L (prerequisite_type),
1175                          type_descriptive_name_L (interface_type),
1176                          type_descriptive_name_L (NODE_TYPE (prnode)));
1177               G_WRITE_UNLOCK (&type_rw_lock);
1178               return;
1179             }
1180         }
1181
1182       for (i = 0; i < prerequisite_node->n_supers + 1; i++)
1183         type_iface_add_prerequisite_W (iface, lookup_type_node_L (prerequisite_node->supers[i]));
1184     }
1185   else if (NODE_IS_IFACE (prerequisite_node))
1186     {
1187       GType *dependants;
1188       guint n_dependants, i;
1189
1190       dependants = iface_node_get_dependants_array_L (prerequisite_node);
1191       n_dependants = dependants ? dependants[0] : 0;
1192       for (i = 1; i <= n_dependants; i++)
1193         type_iface_add_prerequisite_W (iface, lookup_type_node_L (dependants[i]));
1194       type_iface_add_prerequisite_W (iface, prerequisite_node);
1195     }
1196   else
1197     g_warning ("prerequisite `%s' for interface `%s' is not instantiatable or interface",
1198                type_descriptive_name_L (prerequisite_type),
1199                type_descriptive_name_L (interface_type));
1200   G_WRITE_UNLOCK (&type_rw_lock);
1201 }
1202
1203 static IFaceHolder*
1204 type_iface_retrive_holder_info_Wm (TypeNode *iface,
1205                                    GType     instance_type)
1206 {
1207   IFaceHolder *iholder = iface_node_get_holders_L (iface);
1208   
1209   g_assert (NODE_IS_IFACE (iface));
1210   
1211   while (iholder->instance_type != instance_type)
1212     iholder = iholder->next;
1213   
1214   if (!iholder->info)
1215     {
1216       GInterfaceInfo tmp_info;
1217       
1218       g_assert (iholder->plugin != NULL);
1219       
1220       type_data_ref_Wm (iface);
1221       if (iholder->info)
1222         INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface));
1223       
1224       memset (&tmp_info, 0, sizeof (tmp_info));
1225       
1226       G_WRITE_UNLOCK (&type_rw_lock);
1227       g_type_plugin_use (iholder->plugin);
1228       g_type_plugin_complete_interface_info (iholder->plugin, instance_type, NODE_TYPE (iface), &tmp_info);
1229       G_WRITE_LOCK (&type_rw_lock);
1230       if (iholder->info)
1231         INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
1232       
1233       check_interface_info_L (iface, instance_type, &tmp_info);
1234       iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
1235     }
1236   
1237   return iholder;
1238 }
1239
1240 static void
1241 type_iface_blow_holder_info_Wm (TypeNode *iface,
1242                                 GType     instance_type)
1243 {
1244   IFaceHolder *iholder = iface_node_get_holders_L (iface);
1245   
1246   g_assert (NODE_IS_IFACE (iface));
1247   
1248   while (iholder->instance_type != instance_type)
1249     iholder = iholder->next;
1250   
1251   if (iholder->info && iholder->plugin)
1252     {
1253       g_free (iholder->info);
1254       iholder->info = NULL;
1255       
1256       G_WRITE_UNLOCK (&type_rw_lock);
1257       g_type_plugin_unuse (iholder->plugin);
1258       G_WRITE_LOCK (&type_rw_lock);
1259       
1260       type_data_unref_Wm (iface, FALSE);
1261     }
1262 }
1263
1264
1265 /* --- type structure creation/destruction --- */
1266 GTypeInstance*
1267 g_type_create_instance (GType type)
1268 {
1269   TypeNode *node;
1270   GTypeInstance *instance;
1271   GTypeClass *class;
1272   guint i;
1273   
1274   G_READ_LOCK (&type_rw_lock);
1275   node = lookup_type_node_L (type);
1276   G_READ_UNLOCK (&type_rw_lock);
1277   if (!node || !node->is_instantiatable)
1278     {
1279       g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1280                  type_descriptive_name_U (type));
1281       return NULL;
1282     }
1283   /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1284   if (G_TYPE_IS_ABSTRACT (type))
1285     {
1286       g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1287                  type_descriptive_name_U (type));
1288       return NULL;
1289     }
1290   
1291   class = g_type_class_ref (type);
1292   
1293   if (node->data->instance.n_preallocs)
1294     {
1295       G_WRITE_LOCK (&type_rw_lock);
1296       if (!node->data->instance.mem_chunk)
1297         node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
1298                                                           node->data->instance.instance_size,
1299                                                           (node->data->instance.instance_size *
1300                                                            node->data->instance.n_preallocs),
1301                                                           G_ALLOC_AND_FREE);
1302       instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
1303       G_WRITE_UNLOCK (&type_rw_lock);
1304     }
1305   else
1306     instance = g_malloc0 (node->data->instance.instance_size);  /* fine without read lock */
1307   for (i = node->n_supers; i > 0; i--)
1308     {
1309       TypeNode *pnode;
1310       
1311       G_READ_LOCK (&type_rw_lock);
1312       pnode = lookup_type_node_L (node->supers[i]);
1313       G_READ_UNLOCK (&type_rw_lock);
1314       
1315       if (pnode->data->instance.instance_init)
1316         {
1317           instance->g_class = pnode->data->instance.class;
1318           pnode->data->instance.instance_init (instance, class);
1319         }
1320     }
1321   instance->g_class = class;
1322   
1323   if (node->data->instance.instance_init)
1324     node->data->instance.instance_init (instance, class);
1325   
1326   return instance;
1327 }
1328
1329 void
1330 g_type_free_instance (GTypeInstance *instance)
1331 {
1332   TypeNode *node;
1333   GTypeClass *class;
1334   
1335   g_return_if_fail (instance != NULL && instance->g_class != NULL);
1336   
1337   G_READ_LOCK (&type_rw_lock);
1338   class = instance->g_class;
1339   node = lookup_type_node_L (class->g_type);
1340   if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
1341     {
1342       g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1343                  type_descriptive_name_L (class->g_type));
1344       G_READ_UNLOCK (&type_rw_lock);
1345       return;
1346     }
1347   G_READ_UNLOCK (&type_rw_lock);
1348   /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1349   if (G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
1350     {
1351       g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1352                  NODE_NAME (node));
1353       return;
1354     }
1355   
1356   instance->g_class = NULL;
1357   memset (instance, 0xaa, node->data->instance.instance_size);  // FIXME: debugging hack
1358   if (node->data->instance.n_preallocs)
1359     {
1360       G_WRITE_LOCK (&type_rw_lock);
1361       g_chunk_free (instance, node->data->instance.mem_chunk);
1362       G_WRITE_UNLOCK (&type_rw_lock);
1363     }
1364   else
1365     g_free (instance);
1366   
1367   g_type_class_unref (class);
1368 }
1369
1370 static void
1371 type_propagate_iface_vtable_W (TypeNode       *pnode,
1372                                TypeNode       *iface,
1373                                GTypeInterface *vtable)
1374 {
1375   IFaceEntry *entry = type_lookup_iface_entry_L (pnode, iface);
1376   guint i;
1377   
1378   entry->vtable = vtable;
1379   for (i = 0; i < pnode->n_children; i++)
1380     {
1381       TypeNode *node = lookup_type_node_L (pnode->children[i]);
1382       
1383       type_propagate_iface_vtable_W (node, iface, vtable);
1384     }
1385 }
1386
1387 static void
1388 type_iface_vtable_init_Wm (TypeNode *iface,
1389                            TypeNode *node)
1390 {
1391   IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1392   IFaceHolder *iholder = type_iface_retrive_holder_info_Wm (iface, NODE_TYPE (node));
1393   GTypeInterface *vtable;
1394   
1395   g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
1396   
1397   vtable = g_malloc0 (iface->data->iface.vtable_size);
1398   type_propagate_iface_vtable_W (node, iface, vtable);
1399   vtable->g_type = NODE_TYPE (iface);
1400   vtable->g_instance_type = NODE_TYPE (node);
1401   
1402   if (iface->data->iface.vtable_init_base || iholder->info->interface_init)
1403     {
1404       G_WRITE_UNLOCK (&type_rw_lock);
1405       if (iface->data->iface.vtable_init_base)
1406         iface->data->iface.vtable_init_base (vtable);
1407       if (iholder->info->interface_init)
1408         iholder->info->interface_init (vtable, iholder->info->interface_data);
1409       G_WRITE_LOCK (&type_rw_lock);
1410     }
1411 }
1412
1413 static void
1414 type_iface_vtable_finalize_Wm (TypeNode       *iface,
1415                                TypeNode       *node,
1416                                GTypeInterface *vtable)
1417 {
1418   IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1419   IFaceHolder *iholder = iface_node_get_holders_L (iface);
1420   
1421   g_assert (entry && entry->vtable == vtable);
1422   
1423   while (iholder->instance_type != NODE_TYPE (node))
1424     iholder = iholder->next;
1425   g_assert (iholder && iholder->info);
1426   
1427   type_propagate_iface_vtable_W (node, iface, NULL);
1428   if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
1429     {
1430       G_WRITE_UNLOCK (&type_rw_lock);
1431       if (iholder->info->interface_finalize)
1432         iholder->info->interface_finalize (vtable, iholder->info->interface_data);
1433       if (iface->data->iface.vtable_finalize_base)
1434         iface->data->iface.vtable_finalize_base (vtable);
1435       G_WRITE_LOCK (&type_rw_lock);
1436     }
1437   vtable->g_type = 0;
1438   vtable->g_instance_type = 0;
1439   g_free (vtable);
1440   
1441   type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
1442 }
1443
1444 static void
1445 type_class_init_Wm (TypeNode   *node,
1446                     GTypeClass *pclass)
1447 {
1448   GSList *slist, *init_slist = NULL;
1449   GTypeClass *class;
1450   IFaceEntry *entry;
1451   TypeNode *bnode;
1452   guint i;
1453   
1454   g_assert (node->is_classed && node->data &&
1455             node->data->class.class_size &&
1456             !node->data->class.class);
1457   
1458   class = g_malloc0 (node->data->class.class_size);
1459   node->data->class.class = class;
1460   
1461   if (pclass)
1462     {
1463       TypeNode *pnode = lookup_type_node_L (pclass->g_type);
1464       
1465       memcpy (class, pclass, pnode->data->class.class_size);
1466     }
1467   class->g_type = NODE_TYPE (node);
1468   
1469   G_WRITE_UNLOCK (&type_rw_lock);
1470   
1471   /* stack all base class initialization functions, so we
1472    * call them in ascending order.
1473    */
1474   G_READ_LOCK (&type_rw_lock);
1475   for (bnode = node; bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
1476     if (bnode->data->class.class_init_base)
1477       init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
1478   G_READ_UNLOCK (&type_rw_lock);
1479   for (slist = init_slist; slist; slist = slist->next)
1480     {
1481       GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
1482       
1483       class_init_base (class);
1484     }
1485   g_slist_free (init_slist);
1486   
1487   if (node->data->class.class_init)
1488     node->data->class.class_init (class, (gpointer) node->data->class.class_data);
1489   
1490   G_WRITE_LOCK (&type_rw_lock);
1491   
1492   /* ok, we got the class done, now initialize all interfaces */
1493   for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1494     if (!CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable)
1495       entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1496   while (entry)
1497     {
1498       type_iface_vtable_init_Wm (lookup_type_node_L (entry->iface_type), node);
1499       
1500       for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1501         if (!CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable)
1502           entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1503     }
1504 }
1505
1506 static void
1507 type_data_finalize_class_ifaces_Wm (TypeNode *node)
1508 {
1509   IFaceEntry *entry;
1510   guint i;
1511   
1512   g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
1513   
1514   g_message ("finalizing interfaces for %sClass `%s'",
1515              type_descriptive_name_L (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1516              type_descriptive_name_L (NODE_TYPE (node)));
1517   
1518   for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1519     if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable &&
1520         CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node))
1521       entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1522   while (entry)
1523     {
1524       type_iface_vtable_finalize_Wm (lookup_type_node_L (entry->iface_type), node, entry->vtable);
1525       
1526       for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1527         if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable &&
1528             CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node))
1529           entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1530     }
1531 }
1532
1533 static void
1534 type_data_finalize_class_U (TypeNode  *node,
1535                             ClassData *cdata)
1536 {
1537   GTypeClass *class = cdata->class;
1538   TypeNode *bnode;
1539   
1540   g_assert (cdata->class && cdata->common.ref_count == 0);
1541   
1542   if (cdata->class_finalize)
1543     cdata->class_finalize (class, (gpointer) cdata->class_data);
1544   
1545   /* call all base class destruction functions in descending order
1546    */
1547   if (cdata->class_finalize_base)
1548     cdata->class_finalize_base (class);
1549   G_READ_LOCK (&type_rw_lock);
1550   for (bnode = lookup_type_node_L (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
1551     if (bnode->data->class.class_finalize_base)
1552       {
1553         G_READ_UNLOCK (&type_rw_lock);
1554         bnode->data->class.class_finalize_base (class);
1555         G_READ_LOCK (&type_rw_lock);
1556       }
1557   G_READ_UNLOCK (&type_rw_lock);
1558   
1559   class->g_type = 0;
1560   g_free (cdata->class);
1561 }
1562
1563 static void
1564 type_data_last_unref_Wm (GType    type,
1565                          gboolean uncached)
1566 {
1567   TypeNode *node = lookup_type_node_L (type);
1568   
1569   g_return_if_fail (node != NULL && node->plugin != NULL);
1570   
1571   if (!node->data || node->data->common.ref_count == 0)
1572     {
1573       g_warning ("cannot drop last reference to unreferenced type `%s'",
1574                  type_descriptive_name_U (type));
1575       return;
1576     }
1577   
1578   if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs)
1579     {
1580       guint i;
1581       
1582       G_WRITE_UNLOCK (&type_rw_lock);
1583       G_READ_LOCK (&type_rw_lock);
1584       for (i = 0; i < static_n_class_cache_funcs; i++)
1585         {
1586           GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func;
1587           gpointer cache_data = static_class_cache_funcs[i].cache_data;
1588           gboolean need_break;
1589           
1590           G_READ_UNLOCK (&type_rw_lock);
1591           need_break = cache_func (cache_data, node->data->class.class);
1592           G_READ_LOCK (&type_rw_lock);
1593           if (!node->data || node->data->common.ref_count == 0)
1594             INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
1595           if (need_break)
1596             break;
1597         }
1598       G_READ_UNLOCK (&type_rw_lock);
1599       G_WRITE_LOCK (&type_rw_lock);
1600     }
1601   
1602   if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */
1603     node->data->common.ref_count -= 1;
1604   else
1605     {
1606       GType ptype = NODE_PARENT_TYPE (node);
1607       TypeData *tdata;
1608       
1609       node->data->common.ref_count = 0;
1610       
1611       if (node->is_instantiatable && node->data->instance.mem_chunk)
1612         {
1613           g_mem_chunk_destroy (node->data->instance.mem_chunk);
1614           node->data->instance.mem_chunk = NULL;
1615         }
1616       
1617       tdata = node->data;
1618       if (node->is_classed && tdata->class.class)
1619         {
1620           if (CLASSED_NODE_N_IFACES (node))
1621             type_data_finalize_class_ifaces_Wm (node);
1622           node->data = NULL;
1623           G_WRITE_UNLOCK (&type_rw_lock);
1624           type_data_finalize_class_U (node, &tdata->class);
1625           G_WRITE_LOCK (&type_rw_lock);
1626         }
1627       else
1628         node->data = NULL;
1629
1630       /* freeing tdata->common.value_table and its contents is taking care of
1631        * by allocating it in one chunk with tdata
1632        */
1633       g_free (tdata);
1634       
1635       if (ptype)
1636         type_data_unref_Wm (lookup_type_node_L (ptype), FALSE);
1637       G_WRITE_UNLOCK (&type_rw_lock);
1638       g_type_plugin_unuse (node->plugin);
1639       G_WRITE_LOCK (&type_rw_lock);
1640     }
1641 }
1642
1643 void
1644 g_type_add_class_cache_func (gpointer            cache_data,
1645                              GTypeClassCacheFunc cache_func)
1646 {
1647   guint i;
1648   
1649   g_return_if_fail (cache_func != NULL);
1650   
1651   G_WRITE_LOCK (&type_rw_lock);
1652   i = static_n_class_cache_funcs++;
1653   static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
1654   static_class_cache_funcs[i].cache_data = cache_data;
1655   static_class_cache_funcs[i].cache_func = cache_func;
1656   G_WRITE_UNLOCK (&type_rw_lock);
1657 }
1658
1659 void
1660 g_type_remove_class_cache_func (gpointer            cache_data,
1661                                 GTypeClassCacheFunc cache_func)
1662 {
1663   gboolean found_it = FALSE;
1664   guint i;
1665   
1666   g_return_if_fail (cache_func != NULL);
1667   
1668   G_WRITE_LOCK (&type_rw_lock);
1669   for (i = 0; i < static_n_class_cache_funcs; i++)
1670     if (static_class_cache_funcs[i].cache_data == cache_data &&
1671         static_class_cache_funcs[i].cache_func == cache_func)
1672       {
1673         static_n_class_cache_funcs--;
1674         g_memmove (static_class_cache_funcs + i,
1675                    static_class_cache_funcs + i + 1,
1676                    sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
1677         static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
1678         found_it = TRUE;
1679         break;
1680       }
1681   G_WRITE_UNLOCK (&type_rw_lock);
1682   
1683   if (!found_it)
1684     g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
1685                cache_func, cache_data);
1686 }
1687
1688
1689 /* --- type registration --- */
1690 GType
1691 g_type_register_fundamental (GType                       type_id,
1692                              const gchar                *type_name,
1693                              const GTypeInfo            *info,
1694                              const GTypeFundamentalInfo *finfo,
1695                              GTypeFlags                  flags)
1696 {
1697   GTypeFundamentalInfo *node_finfo;
1698   TypeNode *node;
1699   
1700   g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, 0);
1701   g_return_val_if_fail (type_id > 0, 0);
1702   g_return_val_if_fail (type_name != NULL, 0);
1703   g_return_val_if_fail (info != NULL, 0);
1704   g_return_val_if_fail (finfo != NULL, 0);
1705   
1706   if (!check_type_name_U (type_name))
1707     return 0;
1708   if (G_TYPE_FUNDAMENTAL (type_id) != type_id)
1709     {
1710       g_warning ("cannot register fundamental type `%s' with non-fundamental id (%u)",
1711                  type_name,
1712                  type_id);
1713       return 0;
1714     }
1715   if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
1716       !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
1717     {
1718       g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1719                  type_name);
1720       return 0;
1721     }
1722   G_WRITE_LOCK (&type_rw_lock);
1723   if (lookup_type_node_L (type_id))
1724     {
1725       G_WRITE_UNLOCK (&type_rw_lock);
1726       g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1727                  type_descriptive_name_U (type_id),
1728                  type_name);
1729       return 0;
1730     }
1731   
1732   node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
1733   node_finfo = type_node_fundamental_info_L (node);
1734   type_add_flags_W (node, flags);
1735   
1736   if (check_type_info_L (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
1737     type_data_make_W (node, info,
1738                       check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
1739   G_WRITE_UNLOCK (&type_rw_lock);
1740   
1741   return NODE_TYPE (node);
1742 }
1743
1744 GType
1745 g_type_register_static (GType            parent_type,
1746                         const gchar     *type_name,
1747                         const GTypeInfo *info,
1748                         GTypeFlags       flags)
1749 {
1750   TypeNode *pnode, *node;
1751   GType type = 0;
1752   
1753   g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, 0);
1754   g_return_val_if_fail (parent_type > 0, 0);
1755   g_return_val_if_fail (type_name != NULL, 0);
1756   g_return_val_if_fail (info != NULL, 0);
1757   
1758   if (!check_type_name_U (type_name) ||
1759       !check_derivation_U (parent_type, type_name))
1760     return 0;
1761   if (info->class_finalize)
1762     {
1763       g_warning ("class finalizer specified for static type `%s'",
1764                  type_name);
1765       return 0;
1766     }
1767   
1768   G_WRITE_LOCK (&type_rw_lock);
1769   pnode = lookup_type_node_L (parent_type);
1770   type_data_ref_Wm (pnode);
1771   if (check_type_info_L (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
1772     {
1773       node = type_node_new_W (pnode, type_name, NULL);
1774       type_add_flags_W (node, flags);
1775       type = NODE_TYPE (node);
1776       type_data_make_W (node, info,
1777                         check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
1778     }
1779   G_WRITE_UNLOCK (&type_rw_lock);
1780   
1781   return type;
1782 }
1783
1784 GType
1785 g_type_register_dynamic (GType        parent_type,
1786                          const gchar *type_name,
1787                          GTypePlugin *plugin,
1788                          GTypeFlags   flags)
1789 {
1790   TypeNode *pnode, *node;
1791   GType type;
1792   
1793   g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, 0);
1794   g_return_val_if_fail (parent_type > 0, 0);
1795   g_return_val_if_fail (type_name != NULL, 0);
1796   g_return_val_if_fail (plugin != NULL, 0);
1797   
1798   if (!check_type_name_U (type_name) ||
1799       !check_derivation_U (parent_type, type_name) ||
1800       !check_plugin_U (plugin, TRUE, FALSE, type_name))
1801     return 0;
1802   
1803   G_WRITE_LOCK (&type_rw_lock);
1804   pnode = lookup_type_node_L (parent_type);
1805   node = type_node_new_W (pnode, type_name, plugin);
1806   type_add_flags_W (node, flags);
1807   type = NODE_TYPE (node);
1808   G_WRITE_UNLOCK (&type_rw_lock);
1809   
1810   return type;
1811 }
1812
1813 void
1814 g_type_add_interface_static (GType                 instance_type,
1815                              GType                 interface_type,
1816                              const GInterfaceInfo *info)
1817 {
1818   /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1819   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1820   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1821   
1822   G_WRITE_LOCK (&type_rw_lock);
1823   if (check_add_interface_L (instance_type, interface_type))
1824     {
1825       TypeNode *node = lookup_type_node_L (instance_type);
1826       TypeNode *iface = lookup_type_node_L (interface_type);
1827       
1828       if (check_interface_info_L (iface, NODE_TYPE (node), info))
1829         type_add_interface_W (node, iface, info, NULL);
1830     }
1831   G_WRITE_UNLOCK (&type_rw_lock);
1832 }
1833
1834 void
1835 g_type_add_interface_dynamic (GType        instance_type,
1836                               GType        interface_type,
1837                               GTypePlugin *plugin)
1838 {
1839   TypeNode *node;
1840   
1841   /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1842   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1843   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1844   
1845   G_READ_LOCK (&type_rw_lock);
1846   node = lookup_type_node_L (instance_type);
1847   G_READ_UNLOCK (&type_rw_lock);
1848   if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
1849     return;
1850   
1851   G_WRITE_LOCK (&type_rw_lock);
1852   if (check_add_interface_L (instance_type, interface_type))
1853     {
1854       TypeNode *iface = lookup_type_node_L (interface_type);
1855       
1856       type_add_interface_W (node, iface, NULL, plugin);
1857     }
1858   G_WRITE_UNLOCK (&type_rw_lock);
1859 }
1860
1861
1862 /* --- public API functions --- */
1863 gpointer
1864 g_type_class_ref (GType type)
1865 {
1866   TypeNode *node;
1867   
1868   /* optimize for common code path
1869    */
1870   G_WRITE_LOCK (&type_rw_lock);
1871   node = lookup_type_node_L (type);
1872   if (node && node->is_classed && node->data &&
1873       node->data->class.class && node->data->common.ref_count > 0)
1874     {
1875       type_data_ref_Wm (node);
1876       G_WRITE_UNLOCK (&type_rw_lock);
1877       
1878       return node->data->class.class;
1879     }
1880   
1881   if (!node || !node->is_classed ||
1882       (node->data && node->data->common.ref_count < 1))
1883     {
1884       G_WRITE_UNLOCK (&type_rw_lock);
1885       g_warning ("cannot retrive class for invalid (unclassed) type `%s'",
1886                  type_descriptive_name_U (type));
1887       return NULL;
1888     }
1889   
1890   type_data_ref_Wm (node);
1891   
1892   if (!node->data->class.class)
1893     {
1894       GType ptype = NODE_PARENT_TYPE (node);
1895       GTypeClass *pclass = NULL;
1896       
1897       if (ptype)
1898         {
1899           G_WRITE_UNLOCK (&type_rw_lock);
1900           pclass = g_type_class_ref (ptype);
1901           if (node->data->class.class)
1902             INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1903           G_WRITE_LOCK (&type_rw_lock);
1904         }
1905       
1906       type_class_init_Wm (node, pclass);
1907     }
1908   G_WRITE_UNLOCK (&type_rw_lock);
1909   
1910   return node->data->class.class;
1911 }
1912
1913 void
1914 g_type_class_unref (gpointer g_class)
1915 {
1916   TypeNode *node;
1917   GTypeClass *class = g_class;
1918   
1919   g_return_if_fail (g_class != NULL);
1920   
1921   G_WRITE_LOCK (&type_rw_lock);
1922   node = lookup_type_node_L (class->g_type);
1923   if (node && node->is_classed && node->data &&
1924       node->data->class.class == class && node->data->common.ref_count > 0)
1925     type_data_unref_Wm (node, FALSE);
1926   else
1927     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1928                type_descriptive_name_L (class->g_type));
1929   G_WRITE_UNLOCK (&type_rw_lock);
1930 }
1931
1932 void
1933 g_type_class_unref_uncached (gpointer g_class)
1934 {
1935   TypeNode *node;
1936   GTypeClass *class = g_class;
1937   
1938   g_return_if_fail (g_class != NULL);
1939   
1940   G_WRITE_LOCK (&type_rw_lock);
1941   node = lookup_type_node_L (class->g_type);
1942   if (node && node->is_classed && node->data &&
1943       node->data->class.class == class && node->data->common.ref_count > 0)
1944     type_data_unref_Wm (node, TRUE);
1945   else
1946     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1947                type_descriptive_name_L (class->g_type));
1948   G_WRITE_UNLOCK (&type_rw_lock);
1949 }
1950
1951 gpointer
1952 g_type_class_peek (GType type)
1953 {
1954   TypeNode *node;
1955   gpointer class;
1956   
1957   G_READ_LOCK (&type_rw_lock);
1958   node = lookup_type_node_L (type);
1959   if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
1960     class = node->data->class.class;
1961   else
1962     class = NULL;
1963   G_READ_UNLOCK (&type_rw_lock);
1964   
1965   return class;
1966 }
1967
1968 gpointer
1969 g_type_class_peek_parent (gpointer g_class)
1970 {
1971   TypeNode *node;
1972   gpointer class;
1973   
1974   g_return_val_if_fail (g_class != NULL, NULL);
1975   
1976   G_READ_LOCK (&type_rw_lock);
1977   node = lookup_type_node_L (G_TYPE_FROM_CLASS (g_class));
1978   if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
1979     {
1980       node = lookup_type_node_L (NODE_PARENT_TYPE (node));
1981       class = node->data->class.class;
1982     }
1983   else
1984     class = NULL;
1985   G_READ_UNLOCK (&type_rw_lock);
1986   
1987   return class;
1988 }
1989
1990 gpointer
1991 g_type_interface_peek (gpointer instance_class,
1992                        GType    iface_type)
1993 {
1994   TypeNode *node;
1995   TypeNode *iface;
1996   gpointer vtable = NULL;
1997   GTypeClass *class = instance_class;
1998   
1999   g_return_val_if_fail (instance_class != NULL, NULL);
2000   
2001   G_READ_LOCK (&type_rw_lock);
2002   node = lookup_type_node_L (class->g_type);
2003   iface = lookup_type_node_L (iface_type);
2004   if (node && node->is_instantiatable && iface)
2005     {
2006       IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
2007       
2008       if (entry && entry->vtable)
2009         vtable = entry->vtable;
2010     }
2011   G_READ_UNLOCK (&type_rw_lock);
2012   
2013   return vtable;
2014 }
2015
2016 G_CONST_RETURN gchar*
2017 g_type_name (GType type)
2018 {
2019   TypeNode *node;
2020   
2021   g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, NULL);
2022
2023   G_READ_LOCK (&type_rw_lock);
2024   node = lookup_type_node_L (type);
2025   G_READ_UNLOCK (&type_rw_lock);
2026   
2027   return node ? NODE_NAME (node) : NULL;
2028 }
2029
2030 GQuark
2031 g_type_qname (GType type)
2032 {
2033   TypeNode *node;
2034   
2035   G_READ_LOCK (&type_rw_lock);
2036   node = lookup_type_node_L (type);
2037   G_READ_UNLOCK (&type_rw_lock);
2038   
2039   return node ? node->qname : 0;
2040 }
2041
2042 GType
2043 g_type_from_name (const gchar *name)
2044 {
2045   GType type = 0;
2046   GQuark quark;
2047   
2048   g_return_val_if_fail (name != NULL, 0);
2049   
2050   quark = g_quark_try_string (name);
2051   if (quark)
2052     {
2053       G_READ_LOCK (&type_rw_lock);
2054       type = GPOINTER_TO_UINT (g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark)));
2055       G_READ_UNLOCK (&type_rw_lock);
2056     }
2057   
2058   return type;
2059 }
2060
2061 GType
2062 g_type_parent (GType type)
2063 {
2064   TypeNode *node;
2065   
2066   G_READ_LOCK (&type_rw_lock);
2067   node = lookup_type_node_L (type);
2068   G_READ_UNLOCK (&type_rw_lock);
2069   
2070   return node ? NODE_PARENT_TYPE (node) : 0;
2071 }
2072
2073 GType
2074 g_type_next_base (GType type,
2075                   GType base_type)
2076 {
2077   GType atype = 0;
2078   TypeNode *node;
2079   
2080   G_READ_LOCK (&type_rw_lock);
2081   node = lookup_type_node_L (type);
2082   if (node)
2083     {
2084       TypeNode *base_node = lookup_type_node_L (base_type);
2085       
2086       if (base_node && base_node->n_supers < node->n_supers)
2087         {
2088           guint n = node->n_supers - base_node->n_supers;
2089           
2090           if (node->supers[n] == base_type)
2091             atype = node->supers[n - 1];
2092         }
2093     }
2094   G_READ_UNLOCK (&type_rw_lock);
2095   
2096   return atype;
2097 }
2098
2099 static inline gboolean
2100 type_node_is_a_L (TypeNode *node,
2101                   TypeNode *iface_node,
2102                   /*        support_inheritance */
2103                   gboolean  support_interfaces,
2104                   gboolean  support_prerequisites)
2105 {
2106   if (support_interfaces &&
2107       node->is_instantiatable && NODE_IS_IFACE (iface_node) &&
2108       type_lookup_iface_entry_L (node, iface_node) != NULL)
2109     return TRUE;
2110   else if (/* support_inheritance && */
2111            iface_node->n_supers <= node->n_supers &&
2112            node->supers[node->n_supers - iface_node->n_supers] == NODE_TYPE (iface_node))
2113     return TRUE;
2114   else if (support_prerequisites &&
2115            NODE_IS_IFACE (node) &&
2116            type_lookup_prerequisite (node, NODE_TYPE (iface_node)))
2117     return TRUE;
2118   else
2119     return FALSE;
2120 }
2121
2122 gboolean
2123 g_type_is_a (GType type,
2124              GType iface_type)
2125 {
2126   TypeNode *node, *iface_node;
2127   gboolean is_a;
2128
2129   G_READ_LOCK (&type_rw_lock);
2130   node = lookup_type_node_L (type);
2131   iface_node = lookup_type_node_L (iface_type);
2132   is_a = node && iface_node && type_node_is_a_L (node, iface_node, TRUE, TRUE);
2133   G_READ_UNLOCK (&type_rw_lock);
2134
2135   return is_a;
2136 }
2137
2138 guint
2139 g_type_fundamental_branch_last (GType type)
2140 {
2141   GType ftype = G_TYPE_FUNDAMENTAL (type);
2142   guint last_type;
2143   
2144   G_READ_LOCK (&type_rw_lock);
2145   last_type = ftype < static_last_fundamental_id ? static_branch_seqnos[ftype] : 0;
2146   G_READ_UNLOCK (&type_rw_lock);
2147   
2148   return last_type;
2149 }
2150
2151 GType* /* free result */
2152 g_type_children (GType  type,
2153                  guint *n_children)
2154 {
2155   TypeNode *node;
2156   
2157   G_READ_LOCK (&type_rw_lock);
2158   node = lookup_type_node_L (type);
2159   if (node)
2160     {
2161       GType *children = g_new (GType, node->n_children + 1);
2162       
2163       memcpy (children, node->children, sizeof (GType) * node->n_children);
2164       children[node->n_children] = 0;
2165       
2166       if (n_children)
2167         *n_children = node->n_children;
2168       G_READ_UNLOCK (&type_rw_lock);
2169       
2170       return children;
2171     }
2172   else
2173     {
2174       G_READ_UNLOCK (&type_rw_lock);
2175       if (n_children)
2176         *n_children = 0;
2177       
2178       return NULL;
2179     }
2180 }
2181
2182 GType* /* free result */
2183 g_type_interfaces (GType  type,
2184                    guint *n_interfaces)
2185 {
2186   TypeNode *node;
2187   
2188   G_READ_LOCK (&type_rw_lock);
2189   node = lookup_type_node_L (type);
2190   if (node && node->is_instantiatable)
2191     {
2192       GType *ifaces = g_new (GType, CLASSED_NODE_N_IFACES (node) + 1);
2193       guint i;
2194       
2195       for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
2196         ifaces[i] = CLASSED_NODE_IFACES_ENTRIES (node)[i].iface_type;
2197       ifaces[i] = 0;
2198       
2199       if (n_interfaces)
2200         *n_interfaces = CLASSED_NODE_N_IFACES (node);
2201       G_READ_UNLOCK (&type_rw_lock);
2202       
2203       return ifaces;
2204     }
2205   else
2206     {
2207       G_READ_UNLOCK (&type_rw_lock);
2208       if (n_interfaces)
2209         *n_interfaces = 0;
2210       
2211       return NULL;
2212     }
2213 }
2214
2215 typedef struct _QData QData;
2216 struct _GData
2217 {
2218   guint  n_qdatas;
2219   QData *qdatas;
2220 };
2221 struct _QData
2222 {
2223   GQuark   quark;
2224   gpointer data;
2225 };
2226
2227 static inline gpointer
2228 type_get_qdata_L (TypeNode *node,
2229                   GQuark    quark)
2230 {
2231   GData *gdata = node->global_gdata;
2232   
2233   if (quark && gdata && gdata->n_qdatas)
2234     {
2235       QData *qdatas = gdata->qdatas - 1;
2236       guint n_qdatas = gdata->n_qdatas;
2237       
2238       do
2239         {
2240           guint i;
2241           QData *check;
2242           
2243           i = (n_qdatas + 1) / 2;
2244           check = qdatas + i;
2245           if (quark == check->quark)
2246             return check->data;
2247           else if (quark > check->quark)
2248             {
2249               n_qdatas -= i;
2250               qdatas = check;
2251             }
2252           else /* if (quark < check->quark) */
2253             n_qdatas = i - 1;
2254         }
2255       while (n_qdatas);
2256     }
2257   return NULL;
2258 }
2259
2260 gpointer
2261 g_type_get_qdata (GType  type,
2262                   GQuark quark)
2263 {
2264   TypeNode *node;
2265   gpointer data;
2266   
2267   G_READ_LOCK (&type_rw_lock);
2268   node = lookup_type_node_L (type);
2269   if (node)
2270     {
2271       data = type_get_qdata_L (node, quark);
2272       G_READ_UNLOCK (&type_rw_lock);
2273     }
2274   else
2275     {
2276       G_READ_UNLOCK (&type_rw_lock);
2277       g_return_val_if_fail (node != NULL, NULL);
2278       data = NULL;
2279     }
2280   return data;
2281 }
2282
2283 static inline void
2284 type_set_qdata_W (TypeNode *node,
2285                   GQuark    quark,
2286                   gpointer  data)
2287 {
2288   GData *gdata;
2289   QData *qdata;
2290   guint i;
2291   
2292   /* setup qdata list if necessary */
2293   if (!node->global_gdata)
2294     node->global_gdata = g_new0 (GData, 1);
2295   gdata = node->global_gdata;
2296   
2297   /* try resetting old data */
2298   qdata = gdata->qdatas;
2299   for (i = 0; i < gdata->n_qdatas; i++)
2300     if (qdata[i].quark == quark)
2301       {
2302         qdata[i].data = data;
2303         return;
2304       }
2305   
2306   /* add new entry */
2307   gdata->n_qdatas++;
2308   gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
2309   qdata = gdata->qdatas;
2310   for (i = 0; i < gdata->n_qdatas - 1; i++)
2311     if (qdata[i].quark > quark)
2312       break;
2313   g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
2314   qdata[i].quark = quark;
2315   qdata[i].data = data;
2316 }
2317
2318 void
2319 g_type_set_qdata (GType    type,
2320                   GQuark   quark,
2321                   gpointer data)
2322 {
2323   TypeNode *node;
2324   
2325   g_return_if_fail (quark != 0);
2326   
2327   G_WRITE_LOCK (&type_rw_lock);
2328   node = lookup_type_node_L (type);
2329   if (node)
2330     {
2331       type_set_qdata_W (node, quark, data);
2332       G_WRITE_UNLOCK (&type_rw_lock);
2333     }
2334   else
2335     {
2336       G_WRITE_UNLOCK (&type_rw_lock);
2337       g_return_if_fail (node != NULL);
2338     }
2339 }
2340
2341 static void
2342 type_add_flags_W (TypeNode  *node,
2343                   GTypeFlags flags)
2344 {
2345   guint dflags;
2346   
2347   g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
2348   g_return_if_fail (node != NULL);
2349   
2350   if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class)
2351     g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
2352   dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
2353   dflags |= flags;
2354   type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
2355 }
2356
2357 void
2358 g_type_query (GType       type,
2359               GTypeQuery *query)
2360 {
2361   TypeNode *node;
2362
2363   g_return_if_fail (query != NULL);
2364   
2365   G_READ_LOCK (&type_rw_lock);
2366   node = lookup_type_node_L (type);
2367   if (node && node->is_classed && !node->plugin && node->data)
2368     {
2369       /* type is classed and static, probably even instantiatable */
2370
2371       query->type = NODE_TYPE (node);
2372       query->type_name = NODE_NAME (node);
2373       query->class_size = node->data->class.class_size;
2374       query->instance_size = node->is_instantiatable ? node->data->instance.instance_size : 0;
2375     }
2376   else
2377     {
2378       /* node is not static and classed, won't allow query */
2379       query->type = 0;
2380     }
2381   G_READ_UNLOCK (&type_rw_lock);
2382 }
2383
2384
2385 /* --- implementation details --- */
2386 gboolean
2387 g_type_check_flags (GType type,
2388                     guint flags)
2389 {
2390   TypeNode *node;
2391   gboolean result = FALSE;
2392   
2393   G_READ_LOCK (&type_rw_lock);
2394   node = lookup_type_node_L (type);
2395   if (node)
2396     {
2397       guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
2398       guint tflags = flags & TYPE_FLAG_MASK;
2399       
2400       if (fflags)
2401         {
2402           GTypeFundamentalInfo *finfo = type_node_fundamental_info_L (node);
2403           
2404           fflags = (finfo->type_flags & fflags) == fflags;
2405         }
2406       else
2407         fflags = TRUE;
2408       
2409       if (tflags)
2410         tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
2411       else
2412         tflags = TRUE;
2413       
2414       result = tflags && fflags;
2415     }
2416   G_READ_UNLOCK (&type_rw_lock);
2417   
2418   return result;
2419 }
2420
2421 GTypePlugin*
2422 g_type_get_plugin (GType type)
2423 {
2424   TypeNode *node;
2425   
2426   G_READ_LOCK (&type_rw_lock);
2427   node = lookup_type_node_L (type);
2428   G_READ_UNLOCK (&type_rw_lock);
2429   
2430   return node ? node->plugin : NULL;
2431 }
2432
2433 GTypePlugin*
2434 g_type_interface_get_plugin (GType instance_type,
2435                              GType interface_type)
2436 {
2437   TypeNode *node;
2438   TypeNode *iface;
2439   
2440   g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
2441   
2442   G_READ_LOCK (&type_rw_lock);
2443   node = lookup_type_node_L (instance_type);  
2444   iface = lookup_type_node_L (interface_type);
2445   if (node && iface)
2446     {
2447       IFaceHolder *iholder = iface_node_get_holders_L (iface);
2448       
2449       while (iholder && iholder->instance_type != instance_type)
2450         iholder = iholder->next;
2451       G_READ_UNLOCK (&type_rw_lock);
2452       
2453       if (iholder)
2454         return iholder->plugin;
2455     }
2456   else
2457     G_READ_UNLOCK (&type_rw_lock);
2458   
2459   g_return_val_if_fail (node == NULL, NULL);
2460   g_return_val_if_fail (iface == NULL, NULL);
2461   
2462   g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
2463   
2464   return NULL;
2465 }
2466
2467 GType
2468 g_type_fundamental_last (void)
2469 {
2470   GType type;
2471   
2472   G_READ_LOCK (&type_rw_lock);
2473   type = static_last_fundamental_id;
2474   G_READ_UNLOCK (&type_rw_lock);
2475   
2476   return type;
2477 }
2478
2479 gboolean
2480 g_type_instance_is_a (GTypeInstance *type_instance,
2481                       GType          iface_type)
2482 {
2483   TypeNode *node, *iface;
2484   gboolean check;
2485
2486   if (!type_instance || !type_instance->g_class)
2487     return FALSE;
2488
2489   G_READ_LOCK (&type_rw_lock);
2490   node = lookup_type_node_L (type_instance->g_class->g_type);
2491   iface = lookup_type_node_L (iface_type);
2492   check = node && node->is_instantiatable && iface && type_node_is_a_L (node, iface, TRUE, FALSE);
2493   G_READ_UNLOCK (&type_rw_lock);
2494
2495   return check;
2496 }
2497
2498 gboolean
2499 g_type_class_is_a (GTypeClass *type_class,
2500                    GType       is_a_type)
2501 {
2502   TypeNode *node, *iface;
2503   gboolean check;
2504
2505   if (!type_class)
2506     return FALSE;
2507
2508   G_READ_LOCK (&type_rw_lock);
2509   node = lookup_type_node_L (type_class->g_type);
2510   iface = lookup_type_node_L (is_a_type);
2511   check = node && node->is_classed && iface && type_node_is_a_L (node, iface, FALSE, FALSE);
2512   G_READ_UNLOCK (&type_rw_lock);
2513
2514   return check;
2515 }
2516
2517 GTypeInstance*
2518 g_type_check_instance_cast (GTypeInstance *type_instance,
2519                             GType          iface_type)
2520 {
2521   if (type_instance)
2522     {
2523       if (type_instance->g_class)
2524         {
2525           TypeNode *node, *iface;
2526           gboolean is_instantiatable, check;
2527
2528           G_READ_LOCK (&type_rw_lock);
2529           node = lookup_type_node_L (type_instance->g_class->g_type);
2530           is_instantiatable = node && node->is_instantiatable;
2531           iface = lookup_type_node_L (iface_type);
2532           check = is_instantiatable && iface && type_node_is_a_L (node, iface, TRUE, FALSE);
2533           G_READ_UNLOCK (&type_rw_lock);
2534           if (check)
2535             return type_instance;
2536
2537           if (is_instantiatable)
2538             g_warning ("invalid cast from `%s' to `%s'",
2539                        type_descriptive_name_U (type_instance->g_class->g_type),
2540                        type_descriptive_name_U (iface_type));
2541           else
2542             g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
2543                        type_descriptive_name_U (type_instance->g_class->g_type),
2544                        type_descriptive_name_U (iface_type));
2545         }
2546       else
2547         g_warning ("invalid unclassed pointer in cast to `%s'",
2548                    type_descriptive_name_U (iface_type));
2549     }
2550   else
2551     g_warning ("invalid cast from (NULL) pointer to `%s'",
2552                type_descriptive_name_U (iface_type));
2553   
2554   return type_instance;
2555 }
2556
2557 GTypeClass*
2558 g_type_check_class_cast (GTypeClass *type_class,
2559                          GType       is_a_type)
2560 {
2561   if (type_class)
2562     {
2563       TypeNode *node, *iface;
2564       gboolean is_classed, check;
2565       
2566       G_READ_LOCK (&type_rw_lock);
2567       node = lookup_type_node_L (type_class->g_type);
2568       is_classed = node && node->is_classed;
2569       iface = lookup_type_node_L (is_a_type);
2570       check = is_classed && iface && type_node_is_a_L (node, iface, FALSE, FALSE);
2571       G_READ_UNLOCK (&type_rw_lock);
2572       if (check)
2573         return type_class;
2574
2575       if (is_classed)
2576         g_warning ("invalid class cast from `%s' to `%s'",
2577                    type_descriptive_name_U (type_class->g_type),
2578                    type_descriptive_name_U (is_a_type));
2579       else
2580         g_warning ("invalid unclassed type `%s' in class cast to `%s'",
2581                    type_descriptive_name_U (type_class->g_type),
2582                    type_descriptive_name_U (is_a_type));
2583     }
2584   else
2585     g_warning ("invalid class cast from (NULL) pointer to `%s'",
2586                type_descriptive_name_U (is_a_type));
2587   return type_class;
2588 }
2589
2590 gboolean
2591 g_type_check_instance (GTypeInstance *type_instance)
2592 {
2593   /* this function is just here to make the signal system
2594    * conveniently elaborated on instance checks
2595    */
2596   if (type_instance)
2597     {
2598       if (type_instance->g_class)
2599         {
2600           TypeNode *node;
2601           gboolean is_instantiatable;
2602           
2603           G_READ_LOCK (&type_rw_lock);
2604           node = lookup_type_node_L (type_instance->g_class->g_type);
2605           is_instantiatable = node && node->is_instantiatable;
2606           G_READ_UNLOCK (&type_rw_lock);
2607           if (is_instantiatable)
2608             return TRUE;
2609
2610           g_warning ("instance of invalid non-instantiatable type `%s'",
2611                      type_descriptive_name_U (type_instance->g_class->g_type));
2612         }
2613       else
2614         g_warning ("instance with invalid (NULL) class pointer");
2615     }
2616   else
2617     g_warning ("invalid (NULL) pointer instance");
2618
2619   return FALSE;
2620 }
2621
2622 static inline gboolean
2623 type_check_is_value_type_U (GType type)
2624 {
2625   GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT;
2626   TypeNode *node;
2627
2628   G_READ_LOCK (&type_rw_lock);
2629  restart_check:
2630   node = lookup_type_node_L (type);
2631   if (node)
2632     {
2633       if (node->data && node->data->common.ref_count > 0 &&
2634           node->data->common.value_table->value_init)
2635         tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
2636       else if (NODE_IS_IFACE (node))
2637         {
2638           guint i;
2639
2640           for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
2641             {
2642               GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
2643               TypeNode *prnode = lookup_type_node_L (prtype);
2644
2645               if (prnode->is_instantiatable)
2646                 {
2647                   type = prtype;
2648                   goto restart_check;
2649                 }
2650             }
2651         }
2652     }
2653   G_READ_UNLOCK (&type_rw_lock);
2654
2655   return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT);
2656 }
2657
2658 gboolean
2659 g_type_check_is_value_type (GType type)
2660 {
2661   return type_check_is_value_type_U (type);
2662 }
2663
2664 gboolean
2665 g_type_check_value (GValue *value)
2666 {
2667   return value && type_check_is_value_type_U (value->g_type);
2668 }
2669
2670 gboolean
2671 g_type_check_value_holds (GValue *value,
2672                           GType   type)
2673 {
2674   return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type);
2675 }
2676
2677 GTypeValueTable*
2678 g_type_value_table_peek (GType type)
2679 {
2680   TypeNode *node;
2681   GTypeValueTable *vtable;
2682   
2683   G_READ_LOCK (&type_rw_lock);
2684  restart_table_peek:
2685   node = lookup_type_node_L (type);
2686   if (!node)
2687     {
2688       g_warning ("type id `%u' is invalid", type);
2689       G_READ_UNLOCK (&type_rw_lock);
2690       return NULL;
2691     }
2692   if (!node->data || node->data->common.ref_count < 1)
2693     {
2694       g_warning ("can't peek value table for type `%s' which is not currently referenced",
2695                  type_descriptive_name_L (type));
2696       G_READ_UNLOCK (&type_rw_lock);
2697       return NULL;
2698     }
2699   if (node->data->common.value_table->value_init)
2700     vtable = node->data->common.value_table;
2701   else if (NODE_IS_IFACE (node))
2702     {
2703       guint i;
2704
2705       for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
2706         {
2707           GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
2708           TypeNode *prnode = lookup_type_node_L (prtype);
2709
2710           if (prnode->is_instantiatable)
2711             {
2712               type = prtype;
2713               goto restart_table_peek;
2714             }
2715         }
2716       vtable = NULL;
2717     }
2718   else
2719     vtable = NULL;
2720   G_READ_UNLOCK (&type_rw_lock);
2721   
2722   return vtable;
2723 }
2724
2725
2726 /* --- foreign prototypes --- */
2727 extern void     g_value_types_init      (void); /* sync with gvaluetypes.c */
2728 extern void     g_enum_types_init       (void); /* sync with genums.c */
2729 extern void     g_param_type_init       (void); /* sync with gparam.c */
2730 extern void     g_boxed_type_init       (void); /* sync with gboxed.c */
2731 extern void     g_object_type_init      (void); /* sync with gobject.c */
2732 extern void     g_param_spec_types_init (void); /* sync with gparamspecs.c */
2733 extern void     g_value_transforms_init (void); /* sync with gvaluetransform.c */
2734 extern void     g_signal_init           (void); /* sync with gsignal.c */
2735
2736
2737 /* --- initialization --- */
2738 void
2739 g_type_init (GTypeDebugFlags debug_flags)
2740 {
2741   G_LOCK_DEFINE_STATIC (type_init_lock);
2742   static TypeNode *type0_node = NULL;
2743   const gchar *env_string;
2744   GTypeInfo info;
2745   TypeNode *node;
2746   GType type;
2747   
2748   G_LOCK (type_init_lock);
2749   
2750   G_WRITE_LOCK (&type_rw_lock);
2751   
2752   if (static_last_fundamental_id)
2753     {
2754       G_WRITE_UNLOCK (&type_rw_lock);
2755       G_UNLOCK (type_init_lock);
2756       return;
2757     }
2758
2759   /* setup GRuntime wide debugging flags */
2760   _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
2761   env_string = g_getenv ("GRUNTIME_DEBUG");
2762   if (env_string != NULL)
2763     {
2764       static GDebugKey debug_keys[] = {
2765         { "objects", G_TYPE_DEBUG_OBJECTS },
2766         { "signals", G_TYPE_DEBUG_SIGNALS },
2767       };
2768
2769       _g_type_debug_flags |= g_parse_debug_string (env_string,
2770                                                    debug_keys,
2771                                                    sizeof (debug_keys) / sizeof (debug_keys[0]));
2772       env_string = NULL;
2773     }
2774   
2775   /* quarks */
2776   static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
2777   static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
2778   static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
2779   
2780   /* type qname hash table */
2781   static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
2782   
2783   /* invalid type G_TYPE_INVALID (0)
2784    */
2785   static_last_fundamental_id = 1;
2786   static_type_nodes = g_renew (TypeNode**, static_type_nodes, static_last_fundamental_id);
2787   static_type_nodes[0] = &type0_node;
2788   static_branch_seqnos = g_renew (GType, static_branch_seqnos, static_last_fundamental_id);
2789   static_branch_seqnos[0] = 1;
2790   
2791   /* void type G_TYPE_NONE
2792    */
2793   node = type_node_fundamental_new_W (G_TYPE_NONE, "void", 0);
2794   type = NODE_TYPE (node);
2795   g_assert (type == G_TYPE_NONE);
2796   
2797   /* interface fundamental type G_TYPE_INTERFACE (!classed)
2798    */
2799   memset (&info, 0, sizeof (info));
2800   node = type_node_fundamental_new_W (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
2801   type = NODE_TYPE (node);
2802   type_data_make_W (node, &info, NULL);
2803   g_assert (type == G_TYPE_INTERFACE);
2804   
2805   G_WRITE_UNLOCK (&type_rw_lock);
2806   
2807   /* G_TYPE_TYPE_PLUGIN
2808    */
2809   g_type_plugin_get_type ();
2810   
2811   /* G_TYPE_* value types
2812    */
2813   g_value_types_init ();
2814   
2815   /* G_TYPE_ENUM & G_TYPE_FLAGS
2816    */
2817   g_enum_types_init ();
2818   
2819   /* G_TYPE_BOXED
2820    */
2821   g_boxed_type_init ();
2822   
2823   /* G_TYPE_PARAM
2824    */
2825   g_param_type_init ();
2826   
2827   /* G_TYPE_OBJECT
2828    */
2829   g_object_type_init ();
2830   
2831   /* G_TYPE_PARAM_* pspec types
2832    */
2833   g_param_spec_types_init ();
2834   
2835   /* Value Transformations
2836    */
2837   g_value_transforms_init ();
2838
2839   /* Signal system
2840    */
2841   g_signal_init ();
2842   
2843   G_UNLOCK (type_init_lock);
2844 }