1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc.
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.
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.
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.
26 #include "gtypeplugin.h"
27 #include "gvaluecollector.h"
28 #include "gbsearcharray.h"
32 /* NOTE: some functions (some internal variants and exported ones)
33 * invalidate data portions of the TypeNodes. if external functions/callbacks
34 * are called, pointers to memory maintained by TypeNodes have to be looked up
35 * again. this affects most of the struct TypeNode fields, e.g. ->children or
36 * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
37 * not ->supers[]), as all those memory portions can get realloc()ed during
38 * callback invocation.
41 * - g_type_from_name() should do an ordered array lookup after fetching the
42 * the quark, instead of a second hashtable lookup.
45 * lock handling issues when calling static functions are indicated by
46 * uppercase letter postfixes, all static functions have to have
47 * one of the below postfixes:
48 * - _I: [Indifferent about locking]
49 * function doesn't care about locks at all
50 * - _U: [Unlocked invocation]
51 * no read or write lock has to be held across function invocation
52 * (locks may be acquired and released during invocation though)
53 * - _L: [Locked invocation]
54 * a write lock or more than 0 read locks have to be held across
56 * - _W: [Write-locked invocation]
57 * a write lock has to be held across function invokation
58 * - _Wm: [Write-locked invocation, mutatable]
59 * like _W, but the write lock might be released and reacquired
60 * during invocation, watch your pointers
63 static GStaticRWLock type_rw_lock = G_STATIC_RW_LOCK_INIT;
65 #define G_READ_LOCK(rw_lock) do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0)
66 #define G_READ_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0)
67 #define G_WRITE_LOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL++\n"); g_static_rw_lock_writer_lock (rw_lock); } while (0)
68 #define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_static_rw_lock_writer_unlock (rw_lock); } while (0)
70 #define G_READ_LOCK(rw_lock) g_static_rw_lock_reader_lock (rw_lock)
71 #define G_READ_UNLOCK(rw_lock) g_static_rw_lock_reader_unlock (rw_lock)
72 #define G_WRITE_LOCK(rw_lock) g_static_rw_lock_writer_lock (rw_lock)
73 #define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
75 #define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
76 static const gchar *_action = " invalidly modified type "; \
77 gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
79 g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
81 g_error ("%s()%s`%s'", _fname, _action, _tname); \
83 #define g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{ \
86 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
87 "%s: initialization assertion failed, use %s() prior to this function", \
88 G_STRLOC, G_STRINGIFY (init_function)); \
89 return (return_value); \
94 #define DEBUG_CODE(debug_type, code_block) G_STMT_START { \
95 if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
98 #else /* !G_ENABLE_DEBUG */
99 #define DEBUG_CODE(debug_type, code_block) /* code_block */
100 #endif /* G_ENABLE_DEBUG */
102 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
103 G_TYPE_FLAG_INSTANTIATABLE | \
104 G_TYPE_FLAG_DERIVABLE | \
105 G_TYPE_FLAG_DEEP_DERIVABLE)
106 #define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
107 #define SIZEOF_FUNDAMENTAL_INFO ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
108 sizeof (gpointer)), \
111 /* The 2*sizeof(size_t) alignment here is borrowed from
112 * GNU libc, so it should be good most everywhere.
113 * It is more conservative than is needed on some 64-bit
114 * platforms, but ia64 does require a 16-byte alignment.
115 * The SIMD extensions for x86 and ppc32 would want a
116 * larger alignment than this, but we don't need to
117 * do better than malloc.
119 #define STRUCT_ALIGNMENT (2 * sizeof (gsize))
120 #define ALIGN_STRUCT(offset) \
121 ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
124 /* --- typedefs --- */
125 typedef struct _TypeNode TypeNode;
126 typedef struct _CommonData CommonData;
127 typedef struct _IFaceData IFaceData;
128 typedef struct _ClassData ClassData;
129 typedef struct _InstanceData InstanceData;
130 typedef union _TypeData TypeData;
131 typedef struct _IFaceEntry IFaceEntry;
132 typedef struct _IFaceHolder IFaceHolder;
135 /* --- prototypes --- */
136 static inline GTypeFundamentalInfo* type_node_fundamental_info_I (TypeNode *node);
137 static void type_add_flags_W (TypeNode *node,
139 static void type_data_make_W (TypeNode *node,
140 const GTypeInfo *info,
141 const GTypeValueTable *value_table);
142 static inline void type_data_ref_Wm (TypeNode *node);
143 static inline void type_data_unref_Wm (TypeNode *node,
145 static void type_data_last_unref_Wm (GType type,
147 static inline gpointer type_get_qdata_L (TypeNode *node,
149 static inline void type_set_qdata_W (TypeNode *node,
152 static IFaceHolder* type_iface_peek_holder_L (TypeNode *iface,
153 GType instance_type);
154 static gboolean type_node_is_a_L (TypeNode *node,
155 TypeNode *iface_node);
158 /* --- enumeration --- */
160 /* The InitState enumeration is used to track the progress of initializing
161 * both classes and interface vtables. Keeping the state of initialization
162 * is necessary to handle new interfaces being added while we are initializing
163 * the class or other interfaces.
175 /* --- structures --- */
179 guint n_children : 12;
181 guint _prot_n_ifaces_prerequisites : 9;
182 guint is_classed : 1;
183 guint is_instantiatable : 1;
184 guint mutatable_check_cache : 1; /* combines some common path checks */
186 TypeData * volatile data;
190 IFaceEntry *iface_entries; /* for !iface types */
191 GType *prerequisistes;
193 GType supers[1]; /* flexible array */
195 #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
196 #define MAX_N_SUPERS (255)
197 #define MAX_N_CHILDREN (4095)
198 #define MAX_N_IFACES (511)
199 #define MAX_N_PREREQUISITES (MAX_N_IFACES)
200 #define NODE_TYPE(node) (node->supers[0])
201 #define NODE_PARENT_TYPE(node) (node->supers[1])
202 #define NODE_FUNDAMENTAL_TYPE(node) (node->supers[node->n_supers])
203 #define NODE_NAME(node) (g_quark_to_string (node->qname))
204 #define NODE_IS_IFACE(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
205 #define CLASSED_NODE_N_IFACES(node) ((node)->_prot_n_ifaces_prerequisites)
206 #define CLASSED_NODE_IFACES_ENTRIES(node) ((node)->_prot.iface_entries)
207 #define IFACE_NODE_N_PREREQUISITES(node) ((node)->_prot_n_ifaces_prerequisites)
208 #define IFACE_NODE_PREREQUISITES(node) ((node)->_prot.prerequisistes)
209 #define iface_node_get_holders_L(node) ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
210 #define iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
211 #define iface_node_get_dependants_array_L(n) ((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
212 #define iface_node_set_dependants_array_W(n,d) (type_set_qdata_W ((n), static_quark_dependants_array, (d)))
213 #define TYPE_ID_MASK ((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1))
215 #define NODE_IS_ANCESTOR(ancestor, node) \
216 ((ancestor)->n_supers <= (node)->n_supers && \
217 (node)->supers[(node)->n_supers - (ancestor)->n_supers] == NODE_TYPE (ancestor))
223 GInterfaceInfo *info;
230 GTypeInterface *vtable;
231 InitState init_state;
236 GTypeValueTable *value_table;
242 GBaseInitFunc vtable_init_base;
243 GBaseFinalizeFunc vtable_finalize_base;
244 GClassInitFunc dflt_init;
245 GClassFinalizeFunc dflt_finalize;
246 gconstpointer dflt_data;
247 gpointer dflt_vtable;
253 guint init_state : 4;
254 GBaseInitFunc class_init_base;
255 GBaseFinalizeFunc class_finalize_base;
256 GClassInitFunc class_init;
257 GClassFinalizeFunc class_finalize;
258 gconstpointer class_data;
265 guint init_state : 4;
266 GBaseInitFunc class_init_base;
267 GBaseFinalizeFunc class_finalize_base;
268 GClassInitFunc class_init;
269 GClassFinalizeFunc class_finalize;
270 gconstpointer class_data;
272 guint16 instance_size;
273 guint16 private_size;
275 GInstanceInitFunc instance_init;
276 GMemChunk *mem_chunk;
283 InstanceData instance;
287 GTypeClassCacheFunc cache_func;
291 /* --- variables --- */
292 static guint static_n_class_cache_funcs = 0;
293 static ClassCacheFunc *static_class_cache_funcs = NULL;
294 static GQuark static_quark_type_flags = 0;
295 static GQuark static_quark_iface_holder = 0;
296 static GQuark static_quark_dependants_array = 0;
297 GTypeDebugFlags _g_type_debug_flags = 0;
300 /* --- type nodes --- */
301 static GHashTable *static_type_nodes_ht = NULL;
302 static TypeNode *static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) + 1] = { 0, };
303 static GType static_fundamental_next = G_TYPE_RESERVED_USER_FIRST;
305 static inline TypeNode*
306 lookup_type_node_I (register GType utype)
308 if (utype > G_TYPE_FUNDAMENTAL_MAX)
309 return (TypeNode*) (utype & ~TYPE_ID_MASK);
311 return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT];
315 type_node_any_new_W (TypeNode *pnode,
319 GTypeFundamentalFlags type_flags)
324 guint i, node_size = 0;
326 n_supers = pnode ? pnode->n_supers + 1 : 0;
329 node_size += SIZEOF_FUNDAMENTAL_INFO; /* fundamental type info */
330 node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
331 node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */
332 node = g_malloc0 (node_size);
333 if (!pnode) /* offset fundamental types */
335 node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
336 static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;
342 g_assert ((type & TYPE_ID_MASK) == 0);
344 node->n_supers = n_supers;
347 node->supers[0] = type;
350 node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
351 node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
353 if (NODE_IS_IFACE (node))
355 IFACE_NODE_N_PREREQUISITES (node) = 0;
356 IFACE_NODE_PREREQUISITES (node) = NULL;
360 CLASSED_NODE_N_IFACES (node) = 0;
361 CLASSED_NODE_IFACES_ENTRIES (node) = NULL;
366 node->supers[0] = type;
367 memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
369 node->is_classed = pnode->is_classed;
370 node->is_instantiatable = pnode->is_instantiatable;
372 if (NODE_IS_IFACE (node))
374 IFACE_NODE_N_PREREQUISITES (node) = 0;
375 IFACE_NODE_PREREQUISITES (node) = NULL;
381 CLASSED_NODE_N_IFACES (node) = CLASSED_NODE_N_IFACES (pnode);
382 CLASSED_NODE_IFACES_ENTRIES (node) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode),
383 sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode)[0]) *
384 CLASSED_NODE_N_IFACES (node));
385 for (j = 0; j < CLASSED_NODE_N_IFACES (node); j++)
387 CLASSED_NODE_IFACES_ENTRIES (node)[j].vtable = NULL;
388 CLASSED_NODE_IFACES_ENTRIES (node)[j].init_state = UNINITIALIZED;
392 i = pnode->n_children++;
393 pnode->children = g_renew (GType, pnode->children, pnode->n_children);
394 pnode->children[i] = type;
397 node->plugin = plugin;
398 node->n_children = 0;
399 node->children = NULL;
401 node->qname = g_quark_from_string (name);
402 node->global_gdata = NULL;
404 g_hash_table_insert (static_type_nodes_ht,
405 GUINT_TO_POINTER (node->qname),
410 static inline GTypeFundamentalInfo*
411 type_node_fundamental_info_I (TypeNode *node)
413 GType ftype = NODE_FUNDAMENTAL_TYPE (node);
415 if (ftype != NODE_TYPE (node))
416 node = lookup_type_node_I (ftype);
418 return node ? G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO) : NULL;
422 type_node_fundamental_new_W (GType ftype,
424 GTypeFundamentalFlags type_flags)
426 GTypeFundamentalInfo *finfo;
429 g_assert ((ftype & TYPE_ID_MASK) == 0);
430 g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX);
432 if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next)
433 static_fundamental_next++;
435 type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
437 node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
439 finfo = type_node_fundamental_info_I (node);
440 finfo->type_flags = type_flags;
446 type_node_new_W (TypeNode *pnode,
452 g_assert (pnode->n_supers < MAX_N_SUPERS);
453 g_assert (pnode->n_children < MAX_N_CHILDREN);
455 return type_node_any_new_W (pnode, NODE_FUNDAMENTAL_TYPE (pnode), name, plugin, 0);
458 static inline IFaceEntry*
459 type_lookup_iface_entry_L (TypeNode *node,
460 TypeNode *iface_node)
462 if (NODE_IS_IFACE (iface_node) && CLASSED_NODE_N_IFACES (node))
464 IFaceEntry *ifaces = CLASSED_NODE_IFACES_ENTRIES (node) - 1;
465 guint n_ifaces = CLASSED_NODE_N_IFACES (node);
466 GType iface_type = NODE_TYPE (iface_node);
473 i = (n_ifaces + 1) >> 1;
475 if (iface_type == check->iface_type)
477 else if (iface_type > check->iface_type)
482 else /* if (iface_type < check->iface_type) */
491 static inline gboolean
492 type_lookup_prerequisite_L (TypeNode *iface,
493 GType prerequisite_type)
495 if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface))
497 GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1;
498 guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface);
505 i = (n_prerequisites + 1) >> 1;
506 check = prerequisites + i;
507 if (prerequisite_type == *check)
509 else if (prerequisite_type > *check)
511 n_prerequisites -= i;
512 prerequisites = check;
514 else /* if (prerequisite_type < *check) */
515 n_prerequisites = i - 1;
517 while (n_prerequisites);
523 type_descriptive_name_I (GType type)
527 TypeNode *node = lookup_type_node_I (type);
529 return node ? NODE_NAME (node) : "<unknown>";
536 /* --- type consistency checks --- */
538 check_plugin_U (GTypePlugin *plugin,
539 gboolean need_complete_type_info,
540 gboolean need_complete_interface_info,
541 const gchar *type_name)
543 /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U
547 g_warning ("plugin handle for type `%s' is NULL",
551 if (!G_IS_TYPE_PLUGIN (plugin))
553 g_warning ("plugin pointer (%p) for type `%s' is invalid",
557 if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
559 g_warning ("plugin for type `%s' has no complete_type_info() implementation",
563 if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
565 g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
573 check_type_name_I (const gchar *type_name)
575 static const gchar *extra_chars = "-_+";
576 const gchar *p = type_name;
579 if (!type_name[0] || !type_name[1] || !type_name[2])
581 g_warning ("type name `%s' is too short", type_name);
584 /* check the first letter */
585 name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
586 for (p = type_name + 1; *p; p++)
587 name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
588 (p[0] >= 'a' && p[0] <= 'z') ||
589 (p[0] >= '0' && p[0] <= '9') ||
590 strchr (extra_chars, p[0]));
593 g_warning ("type name `%s' contains invalid characters", type_name);
596 if (g_type_from_name (type_name))
598 g_warning ("cannot register existing type `%s'", type_name);
606 check_derivation_I (GType parent_type,
607 const gchar *type_name)
610 GTypeFundamentalInfo* finfo;
612 pnode = lookup_type_node_I (parent_type);
615 g_warning ("cannot derive type `%s' from invalid parent type `%s'",
617 type_descriptive_name_I (parent_type));
620 finfo = type_node_fundamental_info_I (pnode);
621 /* ensure flat derivability */
622 if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
624 g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
629 /* ensure deep derivability */
630 if (parent_type != NODE_FUNDAMENTAL_TYPE (pnode) &&
631 !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
633 g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
643 check_collect_format_I (const gchar *collect_format)
645 const gchar *p = collect_format;
646 gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
647 G_VALUE_COLLECT_INT64, G_VALUE_COLLECT_DOUBLE,
648 G_VALUE_COLLECT_POINTER, 0 };
651 if (!strchr (valid_format, *p++))
653 return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
657 check_value_table_I (const gchar *type_name,
658 const GTypeValueTable *value_table)
662 else if (value_table->value_init == NULL)
664 if (value_table->value_free || value_table->value_copy ||
665 value_table->value_peek_pointer ||
666 value_table->collect_format || value_table->collect_value ||
667 value_table->lcopy_format || value_table->lcopy_value)
668 g_warning ("cannot handle uninitializable values of type `%s'",
672 else /* value_table->value_init != NULL */
674 if (!value_table->value_free)
677 * g_warning ("missing `value_free()' for type `%s'", type_name);
681 if (!value_table->value_copy)
683 g_warning ("missing `value_copy()' for type `%s'", type_name);
686 if ((value_table->collect_format || value_table->collect_value) &&
687 (!value_table->collect_format || !value_table->collect_value))
689 g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
693 if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
695 g_warning ("the `%s' specification for type `%s' is too long or invalid",
700 if ((value_table->lcopy_format || value_table->lcopy_value) &&
701 (!value_table->lcopy_format || !value_table->lcopy_value))
703 g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
707 if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
709 g_warning ("the `%s' specification for type `%s' is too long or invalid",
719 check_type_info_I (TypeNode *pnode,
721 const gchar *type_name,
722 const GTypeInfo *info)
724 GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (lookup_type_node_I (ftype));
725 gboolean is_interface = ftype == G_TYPE_INTERFACE;
727 g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX && !(ftype & TYPE_ID_MASK));
729 /* check instance members */
730 if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
731 (info->instance_size || info->n_preallocs || info->instance_init))
734 g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
738 g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
742 /* check class & interface members */
743 if (!((finfo->type_flags & G_TYPE_FLAG_CLASSED) || is_interface) &&
744 (info->class_init || info->class_finalize || info->class_data ||
745 info->class_size || info->base_init || info->base_finalize))
748 g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
752 g_warning ("cannot create class for `%s' as non-classed fundamental",
756 /* check interface size */
757 if (is_interface && info->class_size < sizeof (GTypeInterface))
759 g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
763 /* check class size */
764 if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
766 if (info->class_size < sizeof (GTypeClass))
768 g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
772 if (pnode && info->class_size < pnode->data->class.class_size)
774 g_warning ("specified class size for type `%s' is smaller "
775 "than the parent type's `%s' class size",
781 /* check instance size */
782 if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
784 if (info->instance_size < sizeof (GTypeInstance))
786 g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
790 if (pnode && info->instance_size < pnode->data->instance.instance_size)
792 g_warning ("specified instance size for type `%s' is smaller "
793 "than the parent type's `%s' instance size",
804 find_conforming_child_type_L (TypeNode *pnode,
807 TypeNode *node = NULL;
810 if (type_lookup_iface_entry_L (pnode, iface))
813 for (i = 0; i < pnode->n_children && !node; i++)
814 node = find_conforming_child_type_L (lookup_type_node_I (pnode->children[i]), iface);
820 check_add_interface_L (GType instance_type,
823 TypeNode *node = lookup_type_node_I (instance_type);
824 TypeNode *iface = lookup_type_node_I (iface_type);
827 GType *prerequisites;
831 if (!node || !node->is_instantiatable)
833 g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
834 type_descriptive_name_I (instance_type));
837 if (!iface || !NODE_IS_IFACE (iface))
839 g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
840 type_descriptive_name_I (iface_type),
844 tnode = lookup_type_node_I (NODE_PARENT_TYPE (iface));
845 if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
847 /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
848 g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
854 /* allow overriding of interface type introduced for parent type */
855 entry = type_lookup_iface_entry_L (node, iface);
856 if (entry && entry->vtable == NULL && !type_iface_peek_holder_L (iface, NODE_TYPE (node)))
858 /* ok, we do conform to this interface already, but the interface vtable was not
859 * yet intialized, and we just conform to the interface because it got added to
860 * one of our parents. so we allow overriding of holder info here.
864 /* check whether one of our children already conforms (or whether the interface
865 * got added to this node already)
867 tnode = find_conforming_child_type_L (node, iface); /* tnode is_a node */
870 g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
876 prerequisites = IFACE_NODE_PREREQUISITES (iface);
877 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
879 tnode = lookup_type_node_I (prerequisites[i]);
880 if (!type_node_is_a_L (node, tnode))
882 g_warning ("cannot add interface type `%s' to type `%s' which does not conform to prerequisite `%s'",
893 check_interface_info_I (TypeNode *iface,
895 const GInterfaceInfo *info)
897 if ((info->interface_finalize || info->interface_data) && !info->interface_init)
899 g_warning ("interface type `%s' for type `%s' comes without initializer",
901 type_descriptive_name_I (instance_type));
908 /* --- type info (type node data) --- */
910 type_data_make_W (TypeNode *node,
911 const GTypeInfo *info,
912 const GTypeValueTable *value_table)
915 GTypeValueTable *vtable = NULL;
916 guint vtable_size = 0;
918 g_assert (node->data == NULL && info != NULL);
922 TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
925 vtable = pnode->data->common.value_table;
928 static const GTypeValueTable zero_vtable = { NULL, };
930 value_table = &zero_vtable;
935 /* need to setup vtable_size since we have to allocate it with data in one chunk */
936 vtable_size = sizeof (GTypeValueTable);
937 if (value_table->collect_format)
938 vtable_size += strlen (value_table->collect_format);
939 if (value_table->lcopy_format)
940 vtable_size += strlen (value_table->lcopy_format);
944 if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
946 data = g_malloc0 (sizeof (InstanceData) + vtable_size);
948 vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
949 data->instance.class_size = info->class_size;
950 data->instance.class_init_base = info->base_init;
951 data->instance.class_finalize_base = info->base_finalize;
952 data->instance.class_init = info->class_init;
953 data->instance.class_finalize = info->class_finalize;
954 data->instance.class_data = info->class_data;
955 data->instance.class = NULL;
956 data->instance.init_state = UNINITIALIZED;
957 data->instance.instance_size = info->instance_size;
958 /* We'll set the final value for data->instance.private size
959 * after the parent class has been initialized
961 data->instance.private_size = 0;
962 #ifdef DISABLE_MEM_POOLS
963 data->instance.n_preallocs = 0;
964 #else /* !DISABLE_MEM_POOLS */
965 data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
966 #endif /* !DISABLE_MEM_POOLS */
967 data->instance.instance_init = info->instance_init;
968 data->instance.mem_chunk = NULL;
970 else if (node->is_classed) /* only classed */
972 data = g_malloc0 (sizeof (ClassData) + vtable_size);
974 vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
975 data->class.class_size = info->class_size;
976 data->class.class_init_base = info->base_init;
977 data->class.class_finalize_base = info->base_finalize;
978 data->class.class_init = info->class_init;
979 data->class.class_finalize = info->class_finalize;
980 data->class.class_data = info->class_data;
981 data->class.class = NULL;
982 data->class.init_state = UNINITIALIZED;
984 else if (NODE_IS_IFACE (node))
986 data = g_malloc0 (sizeof (IFaceData) + vtable_size);
988 vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
989 data->iface.vtable_size = info->class_size;
990 data->iface.vtable_init_base = info->base_init;
991 data->iface.vtable_finalize_base = info->base_finalize;
992 data->iface.dflt_init = info->class_init;
993 data->iface.dflt_finalize = info->class_finalize;
994 data->iface.dflt_data = info->class_data;
995 data->iface.dflt_vtable = NULL;
999 data = g_malloc0 (sizeof (CommonData) + vtable_size);
1001 vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
1005 node->data->common.ref_count = 1;
1011 /* we allocate the vtable and its strings together with the type data, so
1012 * children can take over their parent's vtable pointer, and we don't
1013 * need to worry freeing it or not when the child data is destroyed
1015 *vtable = *value_table;
1016 p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable));
1018 vtable->collect_format = p;
1019 if (value_table->collect_format)
1021 strcat (p, value_table->collect_format);
1022 p += strlen (value_table->collect_format);
1026 vtable->lcopy_format = p;
1027 if (value_table->lcopy_format)
1028 strcat (p, value_table->lcopy_format);
1030 node->data->common.value_table = vtable;
1031 node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL &&
1032 !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) &
1033 GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))));
1035 g_assert (node->data->common.value_table != NULL); /* paranoid */
1039 type_data_ref_Wm (TypeNode *node)
1043 TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1045 GTypeValueTable tmp_value_table;
1047 g_assert (node->plugin != NULL);
1051 type_data_ref_Wm (pnode);
1053 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1056 memset (&tmp_info, 0, sizeof (tmp_info));
1057 memset (&tmp_value_table, 0, sizeof (tmp_value_table));
1059 G_WRITE_UNLOCK (&type_rw_lock);
1060 g_type_plugin_use (node->plugin);
1061 g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
1062 G_WRITE_LOCK (&type_rw_lock);
1064 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1066 check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (node), NODE_NAME (node), &tmp_info);
1067 type_data_make_W (node, &tmp_info,
1068 check_value_table_I (NODE_NAME (node),
1069 &tmp_value_table) ? &tmp_value_table : NULL);
1073 g_assert (node->data->common.ref_count > 0);
1075 node->data->common.ref_count += 1;
1080 type_data_unref_Wm (TypeNode *node,
1083 g_assert (node->data && node->data->common.ref_count);
1085 if (node->data->common.ref_count > 1)
1086 node->data->common.ref_count -= 1;
1091 g_warning ("static type `%s' unreferenced too often",
1096 type_data_last_unref_Wm (NODE_TYPE (node), uncached);
1101 type_node_add_iface_entry_W (TypeNode *node,
1104 IFaceEntry *entries;
1107 g_assert (node->is_instantiatable && CLASSED_NODE_N_IFACES (node) < MAX_N_IFACES);
1109 entries = CLASSED_NODE_IFACES_ENTRIES (node);
1110 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1111 if (entries[i].iface_type == iface_type)
1113 /* this can (should) only happen if our parent type already conformed
1114 * to iface_type and node got it's own holder info. here, our
1115 * children should already have entries with NULL vtables, so
1116 * we're actually done.
1118 g_assert (entries[i].vtable == NULL);
1121 else if (entries[i].iface_type > iface_type)
1123 CLASSED_NODE_N_IFACES (node) += 1;
1124 CLASSED_NODE_IFACES_ENTRIES (node) = g_renew (IFaceEntry,
1125 CLASSED_NODE_IFACES_ENTRIES (node),
1126 CLASSED_NODE_N_IFACES (node));
1127 entries = CLASSED_NODE_IFACES_ENTRIES (node);
1128 g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (CLASSED_NODE_N_IFACES (node) - i - 1));
1129 entries[i].iface_type = iface_type;
1130 entries[i].vtable = NULL;
1131 entries[i].init_state = UNINITIALIZED;
1133 for (i = 0; i < node->n_children; i++)
1134 type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), iface_type);
1138 type_add_interface_W (TypeNode *node,
1140 const GInterfaceInfo *info,
1141 GTypePlugin *plugin)
1143 IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
1145 /* we must not call any functions of GInterfaceInfo from within here, since
1146 * we got most probably called from _within_ a type registration function
1148 g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin)));
1150 iholder->next = iface_node_get_holders_L (iface);
1151 iface_node_set_holders_W (iface, iholder);
1152 iholder->instance_type = NODE_TYPE (node);
1153 iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
1154 iholder->plugin = plugin;
1156 type_node_add_iface_entry_W (node, NODE_TYPE (iface));
1160 type_iface_add_prerequisite_W (TypeNode *iface,
1161 TypeNode *prerequisite_node)
1163 GType prerequisite_type = NODE_TYPE (prerequisite_node);
1164 GType *prerequisites, *dependants;
1165 guint n_dependants, i;
1167 g_assert (NODE_IS_IFACE (iface) &&
1168 IFACE_NODE_N_PREREQUISITES (iface) < MAX_N_PREREQUISITES &&
1169 (prerequisite_node->is_instantiatable || NODE_IS_IFACE (prerequisite_node)));
1171 prerequisites = IFACE_NODE_PREREQUISITES (iface);
1172 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1173 if (prerequisites[i] == prerequisite_type)
1174 return; /* we already have that prerequisiste */
1175 else if (prerequisites[i] > prerequisite_type)
1177 IFACE_NODE_N_PREREQUISITES (iface) += 1;
1178 IFACE_NODE_PREREQUISITES (iface) = g_renew (GType,
1179 IFACE_NODE_PREREQUISITES (iface),
1180 IFACE_NODE_N_PREREQUISITES (iface));
1181 prerequisites = IFACE_NODE_PREREQUISITES (iface);
1182 g_memmove (prerequisites + i + 1, prerequisites + i,
1183 sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1));
1184 prerequisites[i] = prerequisite_type;
1186 /* we want to get notified when prerequisites get added to prerequisite_node */
1187 if (NODE_IS_IFACE (prerequisite_node))
1189 dependants = iface_node_get_dependants_array_L (prerequisite_node);
1190 n_dependants = dependants ? dependants[0] : 0;
1192 dependants = g_renew (GType, dependants, n_dependants + 1);
1193 dependants[n_dependants] = NODE_TYPE (iface);
1194 dependants[0] = n_dependants;
1195 iface_node_set_dependants_array_W (prerequisite_node, dependants);
1198 /* we need to notify all dependants */
1199 dependants = iface_node_get_dependants_array_L (iface);
1200 n_dependants = dependants ? dependants[0] : 0;
1201 for (i = 1; i <= n_dependants; i++)
1202 type_iface_add_prerequisite_W (lookup_type_node_I (dependants[i]), prerequisite_node);
1206 g_type_interface_add_prerequisite (GType interface_type,
1207 GType prerequisite_type)
1209 TypeNode *iface, *prerequisite_node;
1210 IFaceHolder *holders;
1212 g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type)); /* G_TYPE_IS_INTERFACE() is an external call: _U */
1213 g_return_if_fail (!g_type_is_a (interface_type, prerequisite_type));
1214 g_return_if_fail (!g_type_is_a (prerequisite_type, interface_type));
1216 iface = lookup_type_node_I (interface_type);
1217 prerequisite_node = lookup_type_node_I (prerequisite_type);
1218 if (!iface || !prerequisite_node || !NODE_IS_IFACE (iface))
1220 g_warning ("interface type `%s' or prerequisite type `%s' invalid",
1221 type_descriptive_name_I (interface_type),
1222 type_descriptive_name_I (prerequisite_type));
1225 G_WRITE_LOCK (&type_rw_lock);
1226 holders = iface_node_get_holders_L (iface);
1229 G_WRITE_UNLOCK (&type_rw_lock);
1230 g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'",
1231 type_descriptive_name_I (prerequisite_type),
1232 type_descriptive_name_I (interface_type),
1233 type_descriptive_name_I (holders->instance_type));
1236 if (prerequisite_node->is_instantiatable)
1240 /* can have at most one publically installable instantiatable prerequisite */
1241 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1243 TypeNode *prnode = lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface)[i]);
1245 if (prnode->is_instantiatable)
1247 G_WRITE_UNLOCK (&type_rw_lock);
1248 g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
1249 type_descriptive_name_I (prerequisite_type),
1250 type_descriptive_name_I (interface_type),
1251 type_descriptive_name_I (NODE_TYPE (prnode)));
1256 for (i = 0; i < prerequisite_node->n_supers + 1; i++)
1257 type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisite_node->supers[i]));
1258 G_WRITE_UNLOCK (&type_rw_lock);
1260 else if (NODE_IS_IFACE (prerequisite_node))
1262 GType *prerequisites;
1265 prerequisites = IFACE_NODE_PREREQUISITES (prerequisite_node);
1266 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (prerequisite_node); i++)
1267 type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisites[i]));
1268 type_iface_add_prerequisite_W (iface, prerequisite_node);
1269 G_WRITE_UNLOCK (&type_rw_lock);
1273 G_WRITE_UNLOCK (&type_rw_lock);
1274 g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface",
1275 type_descriptive_name_I (prerequisite_type),
1276 type_descriptive_name_I (interface_type));
1280 GType* /* free result */
1281 g_type_interface_prerequisites (GType interface_type,
1282 guint *n_prerequisites)
1286 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
1288 iface = lookup_type_node_I (interface_type);
1292 TypeNode *inode = NULL;
1295 G_READ_LOCK (&type_rw_lock);
1296 types = g_new0 (GType, IFACE_NODE_N_PREREQUISITES (iface) + 1);
1297 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1299 GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
1300 TypeNode *node = lookup_type_node_I (prerequisite);
1301 if (node->is_instantiatable &&
1302 (!inode || type_node_is_a_L (node, inode)))
1305 types[n++] = NODE_TYPE (node);
1308 types[n++] = NODE_TYPE (inode);
1310 if (n_prerequisites)
1311 *n_prerequisites = n;
1312 G_READ_UNLOCK (&type_rw_lock);
1318 if (n_prerequisites)
1319 *n_prerequisites = 0;
1327 type_iface_peek_holder_L (TypeNode *iface,
1328 GType instance_type)
1330 IFaceHolder *iholder;
1332 g_assert (NODE_IS_IFACE (iface));
1334 iholder = iface_node_get_holders_L (iface);
1335 while (iholder && iholder->instance_type != instance_type)
1336 iholder = iholder->next;
1341 type_iface_retrieve_holder_info_Wm (TypeNode *iface,
1342 GType instance_type,
1345 IFaceHolder *iholder = type_iface_peek_holder_L (iface, instance_type);
1347 if (iholder && !iholder->info && need_info)
1349 GInterfaceInfo tmp_info;
1351 g_assert (iholder->plugin != NULL);
1353 type_data_ref_Wm (iface);
1355 INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface));
1357 memset (&tmp_info, 0, sizeof (tmp_info));
1359 G_WRITE_UNLOCK (&type_rw_lock);
1360 g_type_plugin_use (iholder->plugin);
1361 g_type_plugin_complete_interface_info (iholder->plugin, instance_type, NODE_TYPE (iface), &tmp_info);
1362 G_WRITE_LOCK (&type_rw_lock);
1364 INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
1366 check_interface_info_I (iface, instance_type, &tmp_info);
1367 iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
1370 return iholder; /* we don't modify write lock upon returning NULL */
1374 type_iface_blow_holder_info_Wm (TypeNode *iface,
1375 GType instance_type)
1377 IFaceHolder *iholder = iface_node_get_holders_L (iface);
1379 g_assert (NODE_IS_IFACE (iface));
1381 while (iholder->instance_type != instance_type)
1382 iholder = iholder->next;
1384 if (iholder->info && iholder->plugin)
1386 g_free (iholder->info);
1387 iholder->info = NULL;
1389 G_WRITE_UNLOCK (&type_rw_lock);
1390 g_type_plugin_unuse (iholder->plugin);
1391 G_WRITE_LOCK (&type_rw_lock);
1393 type_data_unref_Wm (iface, FALSE);
1397 /* Assumes type's class already exists
1399 static inline size_t
1400 type_total_instance_size_I (TypeNode *node)
1402 gsize total_instance_size;
1404 total_instance_size = node->data->instance.instance_size;
1405 if (node->data->instance.private_size != 0)
1406 total_instance_size = ALIGN_STRUCT (total_instance_size) + node->data->instance.private_size;
1408 return total_instance_size;
1411 /* --- type structure creation/destruction --- */
1415 } InstanceRealClass;
1417 instance_real_class_cmp (gconstpointer p1,
1420 const InstanceRealClass *irc1 = p1;
1421 const InstanceRealClass *irc2 = p2;
1422 guint8 *i1 = irc1->instance;
1423 guint8 *i2 = irc2->instance;
1424 return G_BSEARCH_ARRAY_CMP (i1, i2);
1426 G_LOCK_DEFINE_STATIC (instance_real_class);
1427 static GBSearchArray *instance_real_class_bsa = NULL;
1428 static GBSearchConfig instance_real_class_bconfig = {
1429 sizeof (InstanceRealClass),
1430 instance_real_class_cmp,
1434 instance_real_class_set (gpointer instance,
1437 InstanceRealClass key;
1438 key.instance = instance;
1440 G_LOCK (instance_real_class);
1441 if (!instance_real_class_bsa)
1442 instance_real_class_bsa = g_bsearch_array_create (&instance_real_class_bconfig);
1443 instance_real_class_bsa = g_bsearch_array_replace (instance_real_class_bsa, &instance_real_class_bconfig, &key);
1444 G_UNLOCK (instance_real_class);
1447 instance_real_class_remove (gpointer instance)
1449 InstanceRealClass key, *node;
1451 key.instance = instance;
1452 G_LOCK (instance_real_class);
1453 node = g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key);
1454 index = g_bsearch_array_get_index (instance_real_class_bsa, &instance_real_class_bconfig, node);
1455 instance_real_class_bsa = g_bsearch_array_remove (instance_real_class_bsa, &instance_real_class_bconfig, index);
1456 if (!g_bsearch_array_get_n_nodes (instance_real_class_bsa))
1458 g_bsearch_array_free (instance_real_class_bsa, &instance_real_class_bconfig);
1459 instance_real_class_bsa = NULL;
1461 G_UNLOCK (instance_real_class);
1463 static inline GTypeClass*
1464 instance_real_class_get (gpointer instance)
1466 InstanceRealClass key, *node;
1467 key.instance = instance;
1468 G_LOCK (instance_real_class);
1469 node = g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key);
1470 G_UNLOCK (instance_real_class);
1471 return node ? node->class : NULL;
1475 g_type_create_instance (GType type)
1478 GTypeInstance *instance;
1481 gsize total_instance_size;
1483 node = lookup_type_node_I (type);
1484 if (!node || !node->is_instantiatable)
1486 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1487 type_descriptive_name_I (type));
1490 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1491 if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (type))
1493 g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1494 type_descriptive_name_I (type));
1498 class = g_type_class_ref (type);
1500 total_instance_size = type_total_instance_size_I (node);
1502 if (node->data->instance.n_preallocs)
1504 G_WRITE_LOCK (&type_rw_lock);
1505 if (!node->data->instance.mem_chunk)
1507 /* If there isn't private data, the compiler will have already
1508 * added the necessary padding, but in the private data case, we
1509 * have to pad ourselves to ensure proper alignment of all the
1510 * atoms in the slab.
1512 gsize atom_size = total_instance_size;
1513 if (node->data->instance.private_size)
1514 atom_size = ALIGN_STRUCT (atom_size);
1516 node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
1519 node->data->instance.n_preallocs),
1523 instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
1524 G_WRITE_UNLOCK (&type_rw_lock);
1527 instance = g_malloc0 (total_instance_size); /* fine without read lock */
1529 if (node->data->instance.private_size)
1530 instance_real_class_set (instance, class);
1531 for (i = node->n_supers; i > 0; i--)
1535 pnode = lookup_type_node_I (node->supers[i]);
1536 if (pnode->data->instance.instance_init)
1538 instance->g_class = pnode->data->instance.class;
1539 pnode->data->instance.instance_init (instance, class);
1542 if (node->data->instance.private_size)
1543 instance_real_class_remove (instance);
1545 instance->g_class = class;
1546 if (node->data->instance.instance_init)
1547 node->data->instance.instance_init (instance, class);
1553 g_type_free_instance (GTypeInstance *instance)
1558 g_return_if_fail (instance != NULL && instance->g_class != NULL);
1560 class = instance->g_class;
1561 node = lookup_type_node_I (class->g_type);
1562 if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
1564 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1565 type_descriptive_name_I (class->g_type));
1568 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1569 if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
1571 g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1576 instance->g_class = NULL;
1577 #ifdef G_ENABLE_DEBUG
1578 memset (instance, 0xaa, type_total_instance_size_I (node)); /* debugging hack */
1580 if (node->data->instance.n_preallocs)
1582 G_WRITE_LOCK (&type_rw_lock);
1583 g_chunk_free (instance, node->data->instance.mem_chunk);
1584 G_WRITE_UNLOCK (&type_rw_lock);
1589 g_type_class_unref (class);
1593 type_iface_ensure_dflt_vtable_Wm (TypeNode *iface)
1595 g_assert (iface->data);
1597 if (!iface->data->iface.dflt_vtable)
1599 GTypeInterface *vtable = g_malloc0 (iface->data->iface.vtable_size);
1600 iface->data->iface.dflt_vtable = vtable;
1601 vtable->g_type = NODE_TYPE (iface);
1602 vtable->g_instance_type = 0;
1603 if (iface->data->iface.vtable_init_base ||
1604 iface->data->iface.dflt_init)
1606 G_WRITE_UNLOCK (&type_rw_lock);
1607 if (iface->data->iface.vtable_init_base)
1608 iface->data->iface.vtable_init_base (vtable);
1609 if (iface->data->iface.dflt_init)
1610 iface->data->iface.dflt_init (vtable, (gpointer) iface->data->iface.dflt_data);
1611 G_WRITE_LOCK (&type_rw_lock);
1617 /* This is called to allocate and do the first part of initializing
1618 * the interface vtable; type_iface_vtable_iface_init_Wm() does the remainder.
1620 * A FALSE return indicates that we didn't find an init function for
1621 * this type/iface pair, so the vtable from the parent type should
1622 * be used. Note that the write lock is not modified upon a FALSE
1626 type_iface_vtable_base_init_Wm (TypeNode *iface,
1630 IFaceHolder *iholder;
1631 GTypeInterface *vtable = NULL;
1634 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1635 iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), TRUE);
1637 return FALSE; /* we don't modify write lock upon FALSE */
1639 type_iface_ensure_dflt_vtable_Wm (iface);
1641 entry = type_lookup_iface_entry_L (node, iface);
1643 g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
1645 pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1646 if (pnode) /* want to copy over parent iface contents */
1648 IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
1651 vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
1654 vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
1655 entry->vtable = vtable;
1656 vtable->g_type = NODE_TYPE (iface);
1657 vtable->g_instance_type = NODE_TYPE (node);
1659 if (iface->data->iface.vtable_init_base)
1661 G_WRITE_UNLOCK (&type_rw_lock);
1662 iface->data->iface.vtable_init_base (vtable);
1663 G_WRITE_LOCK (&type_rw_lock);
1665 return TRUE; /* initialized the vtable */
1668 /* Finishes what type_iface_vtable_base_init_Wm started by
1669 * calling the interface init function.
1672 type_iface_vtable_iface_init_Wm (TypeNode *iface,
1675 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1676 IFaceHolder *iholder;
1677 GTypeInterface *vtable = NULL;
1679 iholder = type_iface_peek_holder_L (iface, NODE_TYPE (node));
1683 /* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */
1684 g_assert (iface->data && entry && iholder->info);
1686 vtable = entry->vtable;
1688 if (iholder->info->interface_init)
1690 G_WRITE_UNLOCK (&type_rw_lock);
1691 if (iholder->info->interface_init)
1692 iholder->info->interface_init (vtable, iholder->info->interface_data);
1693 G_WRITE_LOCK (&type_rw_lock);
1698 type_iface_vtable_finalize_Wm (TypeNode *iface,
1700 GTypeInterface *vtable)
1702 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1703 IFaceHolder *iholder;
1705 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1706 iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), FALSE);
1708 return FALSE; /* we don't modify write lock upon FALSE */
1710 g_assert (entry && entry->vtable == vtable && iholder->info);
1712 entry->vtable = NULL;
1713 entry->init_state = UNINITIALIZED;
1714 if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
1716 G_WRITE_UNLOCK (&type_rw_lock);
1717 if (iholder->info->interface_finalize)
1718 iholder->info->interface_finalize (vtable, iholder->info->interface_data);
1719 if (iface->data->iface.vtable_finalize_base)
1720 iface->data->iface.vtable_finalize_base (vtable);
1721 G_WRITE_LOCK (&type_rw_lock);
1724 vtable->g_instance_type = 0;
1727 type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
1729 return TRUE; /* write lock modified */
1733 type_class_init_Wm (TypeNode *node,
1736 GSList *slist, *init_slist = NULL;
1739 TypeNode *bnode, *pnode;
1742 g_assert (node->is_classed && node->data &&
1743 node->data->class.class_size &&
1744 !node->data->class.class &&
1745 node->data->class.init_state == UNINITIALIZED);
1747 class = g_malloc0 (node->data->class.class_size);
1748 node->data->class.class = class;
1749 node->data->class.init_state = BASE_CLASS_INIT;
1753 TypeNode *pnode = lookup_type_node_I (pclass->g_type);
1755 memcpy (class, pclass, pnode->data->class.class_size);
1757 if (node->is_instantiatable)
1759 /* We need to initialize the private_size here rather than in
1760 * type_data_make_W() since the class init for the parent
1761 * class may have changed pnode->data->instance.private_size.
1763 node->data->instance.private_size = pnode->data->instance.private_size;
1766 class->g_type = NODE_TYPE (node);
1768 G_WRITE_UNLOCK (&type_rw_lock);
1770 /* stack all base class initialization functions, so we
1771 * call them in ascending order.
1773 for (bnode = node; bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
1774 if (bnode->data->class.class_init_base)
1775 init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
1776 for (slist = init_slist; slist; slist = slist->next)
1778 GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
1780 class_init_base (class);
1782 g_slist_free (init_slist);
1784 G_WRITE_LOCK (&type_rw_lock);
1786 node->data->class.init_state = BASE_IFACE_INIT;
1788 /* Before we initialize the class, base initialize all interfaces, either
1789 * from parent, or through our holder info
1791 pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1794 while (i < CLASSED_NODE_N_IFACES (node))
1796 entry = &CLASSED_NODE_IFACES_ENTRIES (node)[i];
1797 while (i < CLASSED_NODE_N_IFACES (node) &&
1798 entry->init_state == IFACE_INIT)
1804 if (i == CLASSED_NODE_N_IFACES (node))
1807 entry->init_state = IFACE_INIT;
1809 if (!type_iface_vtable_base_init_Wm (lookup_type_node_I (entry->iface_type), node))
1813 /* need to get this interface from parent, type_iface_vtable_base_init_Wm()
1814 * doesn't modify write lock upon FALSE, so entry is still valid;
1816 g_assert (pnode != NULL);
1818 for (j = 0; j < CLASSED_NODE_N_IFACES (pnode); j++)
1820 IFaceEntry *pentry = CLASSED_NODE_IFACES_ENTRIES (pnode) + j;
1822 if (pentry->iface_type == entry->iface_type)
1824 entry->vtable = pentry->vtable;
1825 entry->init_state = INITIALIZED;
1829 g_assert (entry->vtable != NULL);
1832 /* If the write lock was released, additional interface entries might
1833 * have been inserted into CLASSED_NODE_IFACES_ENTRIES (node); they'll
1834 * be base-initialized when inserted, so we don't have to worry that
1835 * we might miss them. Uninitialized entries can only be moved higher
1836 * when new ones are inserted.
1841 node->data->class.init_state = CLASS_INIT;
1843 G_WRITE_UNLOCK (&type_rw_lock);
1845 if (node->data->class.class_init)
1846 node->data->class.class_init (class, (gpointer) node->data->class.class_data);
1848 G_WRITE_LOCK (&type_rw_lock);
1850 node->data->class.init_state = IFACE_INIT;
1852 /* finish initialize the interfaces through our holder info
1857 entry = &CLASSED_NODE_IFACES_ENTRIES (node)[i];
1858 while (i < CLASSED_NODE_N_IFACES (node) &&
1859 entry->init_state == INITIALIZED)
1865 if (i == CLASSED_NODE_N_IFACES (node))
1868 entry->init_state = INITIALIZED;
1870 type_iface_vtable_iface_init_Wm (lookup_type_node_I (entry->iface_type), node);
1872 /* As in the loop above, additional initialized entries might be inserted
1873 * if the write lock is released, but that's harmless because the entries
1874 * we need to initialize only move higher in the list.
1879 node->data->class.init_state = INITIALIZED;
1882 /* This function is called when we add a new interface to an existing type;
1883 * depending on whether the type already has a class or not, we call
1884 * base-init and interface-init functions. If we are called *while* the
1885 * class is being initialized, then we need to update an array saying which
1886 * interfaces for the class have been initialized.
1889 type_iface_vtable_init_Wm (TypeNode *node,
1892 InitState class_state =
1893 node->data ? node->data->class.init_state : UNINITIALIZED;
1894 InitState new_state = UNINITIALIZED;
1896 if (class_state >= BASE_IFACE_INIT)
1898 type_iface_vtable_base_init_Wm (iface, node);
1899 new_state = IFACE_INIT;
1902 if (class_state >= IFACE_INIT)
1904 type_iface_vtable_iface_init_Wm (iface, node);
1905 new_state = INITIALIZED;
1908 if (class_state != UNINITIALIZED && class_state != INITIALIZED)
1910 /* The interface was added while we were initializing the class
1912 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1915 entry->init_state = new_state;
1920 type_data_finalize_class_ifaces_Wm (TypeNode *node)
1924 g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
1927 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1929 IFaceEntry *entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1932 if (type_iface_vtable_finalize_Wm (lookup_type_node_I (entry->iface_type), node, entry->vtable))
1934 /* refetch entries, IFACES_ENTRIES might be modified */
1939 /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
1940 * iface vtable came from parent
1942 entry->vtable = NULL;
1943 entry->init_state = UNINITIALIZED;
1950 type_data_finalize_class_U (TypeNode *node,
1953 GTypeClass *class = cdata->class;
1956 g_assert (cdata->class && cdata->common.ref_count == 0);
1958 if (cdata->class_finalize)
1959 cdata->class_finalize (class, (gpointer) cdata->class_data);
1961 /* call all base class destruction functions in descending order
1963 if (cdata->class_finalize_base)
1964 cdata->class_finalize_base (class);
1965 for (bnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
1966 if (bnode->data->class.class_finalize_base)
1967 bnode->data->class.class_finalize_base (class);
1969 g_free (cdata->class);
1973 type_data_last_unref_Wm (GType type,
1976 TypeNode *node = lookup_type_node_I (type);
1978 g_return_if_fail (node != NULL && node->plugin != NULL);
1980 if (!node->data || node->data->common.ref_count == 0)
1982 g_warning ("cannot drop last reference to unreferenced type `%s'",
1983 type_descriptive_name_I (type));
1987 if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs)
1991 G_WRITE_UNLOCK (&type_rw_lock);
1992 G_READ_LOCK (&type_rw_lock);
1993 for (i = 0; i < static_n_class_cache_funcs; i++)
1995 GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func;
1996 gpointer cache_data = static_class_cache_funcs[i].cache_data;
1997 gboolean need_break;
1999 G_READ_UNLOCK (&type_rw_lock);
2000 need_break = cache_func (cache_data, node->data->class.class);
2001 G_READ_LOCK (&type_rw_lock);
2002 if (!node->data || node->data->common.ref_count == 0)
2003 INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
2007 G_READ_UNLOCK (&type_rw_lock);
2008 G_WRITE_LOCK (&type_rw_lock);
2011 if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */
2012 node->data->common.ref_count -= 1;
2015 GType ptype = NODE_PARENT_TYPE (node);
2018 node->data->common.ref_count = 0;
2020 if (node->is_instantiatable && node->data->instance.mem_chunk)
2022 g_mem_chunk_destroy (node->data->instance.mem_chunk);
2023 node->data->instance.mem_chunk = NULL;
2027 if (node->is_classed && tdata->class.class)
2029 if (CLASSED_NODE_N_IFACES (node))
2030 type_data_finalize_class_ifaces_Wm (node);
2031 node->mutatable_check_cache = FALSE;
2033 G_WRITE_UNLOCK (&type_rw_lock);
2034 type_data_finalize_class_U (node, &tdata->class);
2035 G_WRITE_LOCK (&type_rw_lock);
2037 else if (NODE_IS_IFACE (node) && tdata->iface.dflt_vtable)
2039 node->mutatable_check_cache = FALSE;
2041 if (tdata->iface.dflt_finalize || tdata->iface.vtable_finalize_base)
2043 G_WRITE_UNLOCK (&type_rw_lock);
2044 if (tdata->iface.dflt_finalize)
2045 tdata->iface.dflt_finalize (tdata->iface.dflt_vtable, (gpointer) tdata->iface.dflt_data);
2046 if (tdata->iface.vtable_finalize_base)
2047 tdata->iface.vtable_finalize_base (tdata->iface.dflt_vtable);
2048 G_WRITE_LOCK (&type_rw_lock);
2050 g_free (tdata->iface.dflt_vtable);
2054 node->mutatable_check_cache = FALSE;
2058 /* freeing tdata->common.value_table and its contents is taken care of
2059 * by allocating it in one chunk with tdata
2063 G_WRITE_UNLOCK (&type_rw_lock);
2064 g_type_plugin_unuse (node->plugin);
2065 G_WRITE_LOCK (&type_rw_lock);
2067 type_data_unref_Wm (lookup_type_node_I (ptype), FALSE);
2072 g_type_add_class_cache_func (gpointer cache_data,
2073 GTypeClassCacheFunc cache_func)
2077 g_return_if_fail (cache_func != NULL);
2079 G_WRITE_LOCK (&type_rw_lock);
2080 i = static_n_class_cache_funcs++;
2081 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
2082 static_class_cache_funcs[i].cache_data = cache_data;
2083 static_class_cache_funcs[i].cache_func = cache_func;
2084 G_WRITE_UNLOCK (&type_rw_lock);
2088 g_type_remove_class_cache_func (gpointer cache_data,
2089 GTypeClassCacheFunc cache_func)
2091 gboolean found_it = FALSE;
2094 g_return_if_fail (cache_func != NULL);
2096 G_WRITE_LOCK (&type_rw_lock);
2097 for (i = 0; i < static_n_class_cache_funcs; i++)
2098 if (static_class_cache_funcs[i].cache_data == cache_data &&
2099 static_class_cache_funcs[i].cache_func == cache_func)
2101 static_n_class_cache_funcs--;
2102 g_memmove (static_class_cache_funcs + i,
2103 static_class_cache_funcs + i + 1,
2104 sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
2105 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
2109 G_WRITE_UNLOCK (&type_rw_lock);
2112 g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
2113 cache_func, cache_data);
2117 /* --- type registration --- */
2119 g_type_register_fundamental (GType type_id,
2120 const gchar *type_name,
2121 const GTypeInfo *info,
2122 const GTypeFundamentalInfo *finfo,
2125 GTypeFundamentalInfo *node_finfo;
2128 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
2129 g_return_val_if_fail (type_id > 0, 0);
2130 g_return_val_if_fail (type_name != NULL, 0);
2131 g_return_val_if_fail (info != NULL, 0);
2132 g_return_val_if_fail (finfo != NULL, 0);
2134 if (!check_type_name_I (type_name))
2136 if ((type_id & TYPE_ID_MASK) ||
2137 type_id > G_TYPE_FUNDAMENTAL_MAX)
2139 g_warning ("attempt to register fundamental type `%s' with invalid type id (%lu)",
2144 if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
2145 !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
2147 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
2151 if (lookup_type_node_I (type_id))
2153 g_warning ("cannot register existing fundamental type `%s' (as `%s')",
2154 type_descriptive_name_I (type_id),
2159 G_WRITE_LOCK (&type_rw_lock);
2160 node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
2161 node_finfo = type_node_fundamental_info_I (node);
2162 type_add_flags_W (node, flags);
2164 if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info))
2165 type_data_make_W (node, info,
2166 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
2167 G_WRITE_UNLOCK (&type_rw_lock);
2169 return NODE_TYPE (node);
2173 g_type_register_static (GType parent_type,
2174 const gchar *type_name,
2175 const GTypeInfo *info,
2178 TypeNode *pnode, *node;
2181 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
2182 g_return_val_if_fail (parent_type > 0, 0);
2183 g_return_val_if_fail (type_name != NULL, 0);
2184 g_return_val_if_fail (info != NULL, 0);
2186 if (!check_type_name_I (type_name) ||
2187 !check_derivation_I (parent_type, type_name))
2189 if (info->class_finalize)
2191 g_warning ("class finalizer specified for static type `%s'",
2196 pnode = lookup_type_node_I (parent_type);
2197 G_WRITE_LOCK (&type_rw_lock);
2198 type_data_ref_Wm (pnode);
2199 if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info))
2201 node = type_node_new_W (pnode, type_name, NULL);
2202 type_add_flags_W (node, flags);
2203 type = NODE_TYPE (node);
2204 type_data_make_W (node, info,
2205 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
2207 G_WRITE_UNLOCK (&type_rw_lock);
2213 g_type_register_dynamic (GType parent_type,
2214 const gchar *type_name,
2215 GTypePlugin *plugin,
2218 TypeNode *pnode, *node;
2221 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
2222 g_return_val_if_fail (parent_type > 0, 0);
2223 g_return_val_if_fail (type_name != NULL, 0);
2224 g_return_val_if_fail (plugin != NULL, 0);
2226 if (!check_type_name_I (type_name) ||
2227 !check_derivation_I (parent_type, type_name) ||
2228 !check_plugin_U (plugin, TRUE, FALSE, type_name))
2231 G_WRITE_LOCK (&type_rw_lock);
2232 pnode = lookup_type_node_I (parent_type);
2233 node = type_node_new_W (pnode, type_name, plugin);
2234 type_add_flags_W (node, flags);
2235 type = NODE_TYPE (node);
2236 G_WRITE_UNLOCK (&type_rw_lock);
2242 g_type_add_interface_static (GType instance_type,
2243 GType interface_type,
2244 const GInterfaceInfo *info)
2246 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2247 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2248 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2250 G_WRITE_LOCK (&type_rw_lock);
2251 if (check_add_interface_L (instance_type, interface_type))
2253 TypeNode *node = lookup_type_node_I (instance_type);
2254 TypeNode *iface = lookup_type_node_I (interface_type);
2256 if (check_interface_info_I (iface, NODE_TYPE (node), info))
2258 type_add_interface_W (node, iface, info, NULL);
2259 /* If we have a class already, we may need to base initalize
2260 * and/or initialize the new interface.
2262 type_iface_vtable_init_Wm (node, iface);
2265 G_WRITE_UNLOCK (&type_rw_lock);
2269 g_type_add_interface_dynamic (GType instance_type,
2270 GType interface_type,
2271 GTypePlugin *plugin)
2275 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2276 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2277 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2279 node = lookup_type_node_I (instance_type);
2280 if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
2283 G_WRITE_LOCK (&type_rw_lock);
2284 if (check_add_interface_L (instance_type, interface_type))
2286 TypeNode *iface = lookup_type_node_I (interface_type);
2288 type_add_interface_W (node, iface, NULL, plugin);
2289 /* If we have a class already, we may need to base initalize
2290 * and/or initialize the new interface.
2292 type_iface_vtable_init_Wm (node, iface);
2294 G_WRITE_UNLOCK (&type_rw_lock);
2298 /* --- public API functions --- */
2300 g_type_class_ref (GType type)
2304 /* optimize for common code path
2306 G_WRITE_LOCK (&type_rw_lock);
2307 node = lookup_type_node_I (type);
2308 if (node && node->is_classed && node->data &&
2309 node->data->class.class && node->data->common.ref_count > 0)
2311 type_data_ref_Wm (node);
2312 G_WRITE_UNLOCK (&type_rw_lock);
2314 return node->data->class.class;
2317 if (!node || !node->is_classed ||
2318 (node->data && node->data->common.ref_count < 1))
2320 G_WRITE_UNLOCK (&type_rw_lock);
2321 g_warning ("cannot retrieve class for invalid (unclassed) type `%s'",
2322 type_descriptive_name_I (type));
2326 type_data_ref_Wm (node);
2328 if (!node->data->class.class)
2330 GType ptype = NODE_PARENT_TYPE (node);
2331 GTypeClass *pclass = NULL;
2335 G_WRITE_UNLOCK (&type_rw_lock);
2336 pclass = g_type_class_ref (ptype);
2337 if (node->data->class.class)
2338 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
2339 G_WRITE_LOCK (&type_rw_lock);
2342 type_class_init_Wm (node, pclass);
2344 G_WRITE_UNLOCK (&type_rw_lock);
2346 return node->data->class.class;
2350 g_type_class_unref (gpointer g_class)
2353 GTypeClass *class = g_class;
2355 g_return_if_fail (g_class != NULL);
2357 node = lookup_type_node_I (class->g_type);
2358 G_WRITE_LOCK (&type_rw_lock);
2359 if (node && node->is_classed && node->data &&
2360 node->data->class.class == class && node->data->common.ref_count > 0)
2361 type_data_unref_Wm (node, FALSE);
2363 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2364 type_descriptive_name_I (class->g_type));
2365 G_WRITE_UNLOCK (&type_rw_lock);
2369 g_type_class_unref_uncached (gpointer g_class)
2372 GTypeClass *class = g_class;
2374 g_return_if_fail (g_class != NULL);
2376 G_WRITE_LOCK (&type_rw_lock);
2377 node = lookup_type_node_I (class->g_type);
2378 if (node && node->is_classed && node->data &&
2379 node->data->class.class == class && node->data->common.ref_count > 0)
2380 type_data_unref_Wm (node, TRUE);
2382 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2383 type_descriptive_name_I (class->g_type));
2384 G_WRITE_UNLOCK (&type_rw_lock);
2388 g_type_class_peek (GType type)
2393 node = lookup_type_node_I (type);
2394 G_READ_LOCK (&type_rw_lock);
2395 if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
2396 class = node->data->class.class;
2399 G_READ_UNLOCK (&type_rw_lock);
2405 g_type_class_peek_parent (gpointer g_class)
2408 gpointer class = NULL;
2410 g_return_val_if_fail (g_class != NULL, NULL);
2412 node = lookup_type_node_I (G_TYPE_FROM_CLASS (g_class));
2413 G_READ_LOCK (&type_rw_lock);
2414 if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
2416 node = lookup_type_node_I (NODE_PARENT_TYPE (node));
2417 class = node->data->class.class;
2419 else if (NODE_PARENT_TYPE (node))
2420 g_warning (G_STRLOC ": invalid class pointer `%p'", g_class);
2421 G_READ_UNLOCK (&type_rw_lock);
2427 g_type_interface_peek (gpointer instance_class,
2432 gpointer vtable = NULL;
2433 GTypeClass *class = instance_class;
2435 g_return_val_if_fail (instance_class != NULL, NULL);
2437 node = lookup_type_node_I (class->g_type);
2438 iface = lookup_type_node_I (iface_type);
2439 if (node && node->is_instantiatable && iface)
2443 G_READ_LOCK (&type_rw_lock);
2445 entry = type_lookup_iface_entry_L (node, iface);
2446 if (entry && entry->vtable) /* entry is relocatable */
2447 vtable = entry->vtable;
2449 G_READ_UNLOCK (&type_rw_lock);
2452 g_warning (G_STRLOC ": invalid class pointer `%p'", class);
2458 g_type_interface_peek_parent (gpointer g_iface)
2462 gpointer vtable = NULL;
2463 GTypeInterface *iface_class = g_iface;
2465 g_return_val_if_fail (g_iface != NULL, NULL);
2467 iface = lookup_type_node_I (iface_class->g_type);
2468 node = lookup_type_node_I (iface_class->g_instance_type);
2470 node = lookup_type_node_I (NODE_PARENT_TYPE (node));
2471 if (node && node->is_instantiatable && iface)
2475 G_READ_LOCK (&type_rw_lock);
2477 entry = type_lookup_iface_entry_L (node, iface);
2478 if (entry && entry->vtable) /* entry is relocatable */
2479 vtable = entry->vtable;
2481 G_READ_UNLOCK (&type_rw_lock);
2484 g_warning (G_STRLOC ": invalid interface pointer `%p'", g_iface);
2490 g_type_default_interface_ref (GType g_type)
2494 G_WRITE_LOCK (&type_rw_lock);
2496 node = lookup_type_node_I (g_type);
2497 if (!node || !NODE_IS_IFACE (node) ||
2498 (node->data && node->data->common.ref_count < 1))
2500 G_WRITE_UNLOCK (&type_rw_lock);
2501 g_warning ("cannot retrieve default vtable for invalid or non-interface type '%s'",
2502 type_descriptive_name_I (g_type));
2506 type_data_ref_Wm (node);
2508 type_iface_ensure_dflt_vtable_Wm (node);
2510 G_WRITE_UNLOCK (&type_rw_lock);
2512 return node->data->iface.dflt_vtable;
2516 g_type_default_interface_peek (GType g_type)
2521 node = lookup_type_node_I (g_type);
2522 G_READ_LOCK (&type_rw_lock);
2523 if (node && NODE_IS_IFACE (node) && node->data && node->data->iface.dflt_vtable)
2524 vtable = node->data->iface.dflt_vtable;
2527 G_READ_UNLOCK (&type_rw_lock);
2533 g_type_default_interface_unref (gpointer g_iface)
2536 GTypeInterface *vtable = g_iface;
2538 g_return_if_fail (g_iface != NULL);
2540 node = lookup_type_node_I (vtable->g_type);
2541 G_WRITE_LOCK (&type_rw_lock);
2542 if (node && NODE_IS_IFACE (node) &&
2543 node->data->iface.dflt_vtable == g_iface &&
2544 node->data->common.ref_count > 0)
2545 type_data_unref_Wm (node, FALSE);
2547 g_warning ("cannot unreference invalid interface default vtable for '%s'",
2548 type_descriptive_name_I (vtable->g_type));
2549 G_WRITE_UNLOCK (&type_rw_lock);
2552 G_CONST_RETURN gchar*
2553 g_type_name (GType type)
2557 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, NULL);
2559 node = lookup_type_node_I (type);
2561 return node ? NODE_NAME (node) : NULL;
2565 g_type_qname (GType type)
2569 node = lookup_type_node_I (type);
2571 return node ? node->qname : 0;
2575 g_type_from_name (const gchar *name)
2580 g_return_val_if_fail (name != NULL, 0);
2582 quark = g_quark_try_string (name);
2585 G_READ_LOCK (&type_rw_lock);
2586 type = (GType) g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark));
2587 G_READ_UNLOCK (&type_rw_lock);
2594 g_type_parent (GType type)
2598 node = lookup_type_node_I (type);
2600 return node ? NODE_PARENT_TYPE (node) : 0;
2604 g_type_depth (GType type)
2608 node = lookup_type_node_I (type);
2610 return node ? node->n_supers + 1 : 0;
2614 g_type_next_base (GType type,
2620 node = lookup_type_node_I (type);
2623 TypeNode *base_node = lookup_type_node_I (base_type);
2625 if (base_node && base_node->n_supers < node->n_supers)
2627 guint n = node->n_supers - base_node->n_supers;
2629 if (node->supers[n] == base_type)
2630 atype = node->supers[n - 1];
2637 static inline gboolean
2638 type_node_check_conformities_UorL (TypeNode *node,
2639 TypeNode *iface_node,
2640 /* support_inheritance */
2641 gboolean support_interfaces,
2642 gboolean support_prerequisites,
2647 if (/* support_inheritance && */
2648 NODE_IS_ANCESTOR (iface_node, node))
2651 support_interfaces = support_interfaces && node->is_instantiatable && NODE_IS_IFACE (iface_node);
2652 support_prerequisites = support_prerequisites && NODE_IS_IFACE (node);
2654 if (support_interfaces || support_prerequisites)
2657 G_READ_LOCK (&type_rw_lock);
2658 if (support_interfaces && type_lookup_iface_entry_L (node, iface_node))
2660 else if (support_prerequisites && type_lookup_prerequisite_L (node, NODE_TYPE (iface_node)))
2663 G_READ_UNLOCK (&type_rw_lock);
2669 type_node_is_a_L (TypeNode *node,
2670 TypeNode *iface_node)
2672 return type_node_check_conformities_UorL (node, iface_node, TRUE, TRUE, TRUE);
2675 static inline gboolean
2676 type_node_conforms_to_U (TypeNode *node,
2677 TypeNode *iface_node,
2678 gboolean support_interfaces,
2679 gboolean support_prerequisites)
2681 return type_node_check_conformities_UorL (node, iface_node, support_interfaces, support_prerequisites, FALSE);
2685 g_type_is_a (GType type,
2688 TypeNode *node, *iface_node;
2691 node = lookup_type_node_I (type);
2692 iface_node = lookup_type_node_I (iface_type);
2693 is_a = node && iface_node && type_node_conforms_to_U (node, iface_node, TRUE, TRUE);
2698 GType* /* free result */
2699 g_type_children (GType type,
2704 node = lookup_type_node_I (type);
2709 G_READ_LOCK (&type_rw_lock); /* ->children is relocatable */
2710 children = g_new (GType, node->n_children + 1);
2711 memcpy (children, node->children, sizeof (GType) * node->n_children);
2712 children[node->n_children] = 0;
2715 *n_children = node->n_children;
2716 G_READ_UNLOCK (&type_rw_lock);
2729 GType* /* free result */
2730 g_type_interfaces (GType type,
2731 guint *n_interfaces)
2735 node = lookup_type_node_I (type);
2736 if (node && node->is_instantiatable)
2741 G_READ_LOCK (&type_rw_lock);
2742 ifaces = g_new (GType, CLASSED_NODE_N_IFACES (node) + 1);
2743 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
2744 ifaces[i] = CLASSED_NODE_IFACES_ENTRIES (node)[i].iface_type;
2748 *n_interfaces = CLASSED_NODE_N_IFACES (node);
2749 G_READ_UNLOCK (&type_rw_lock);
2762 typedef struct _QData QData;
2774 static inline gpointer
2775 type_get_qdata_L (TypeNode *node,
2778 GData *gdata = node->global_gdata;
2780 if (quark && gdata && gdata->n_qdatas)
2782 QData *qdatas = gdata->qdatas - 1;
2783 guint n_qdatas = gdata->n_qdatas;
2790 i = (n_qdatas + 1) / 2;
2792 if (quark == check->quark)
2794 else if (quark > check->quark)
2799 else /* if (quark < check->quark) */
2808 g_type_get_qdata (GType type,
2814 node = lookup_type_node_I (type);
2817 G_READ_LOCK (&type_rw_lock);
2818 data = type_get_qdata_L (node, quark);
2819 G_READ_UNLOCK (&type_rw_lock);
2823 g_return_val_if_fail (node != NULL, NULL);
2830 type_set_qdata_W (TypeNode *node,
2838 /* setup qdata list if necessary */
2839 if (!node->global_gdata)
2840 node->global_gdata = g_new0 (GData, 1);
2841 gdata = node->global_gdata;
2843 /* try resetting old data */
2844 qdata = gdata->qdatas;
2845 for (i = 0; i < gdata->n_qdatas; i++)
2846 if (qdata[i].quark == quark)
2848 qdata[i].data = data;
2854 gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
2855 qdata = gdata->qdatas;
2856 for (i = 0; i < gdata->n_qdatas - 1; i++)
2857 if (qdata[i].quark > quark)
2859 g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
2860 qdata[i].quark = quark;
2861 qdata[i].data = data;
2865 g_type_set_qdata (GType type,
2871 g_return_if_fail (quark != 0);
2873 node = lookup_type_node_I (type);
2876 G_WRITE_LOCK (&type_rw_lock);
2877 type_set_qdata_W (node, quark, data);
2878 G_WRITE_UNLOCK (&type_rw_lock);
2881 g_return_if_fail (node != NULL);
2885 type_add_flags_W (TypeNode *node,
2890 g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
2891 g_return_if_fail (node != NULL);
2893 if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class)
2894 g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
2895 dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
2897 type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
2901 g_type_query (GType type,
2906 g_return_if_fail (query != NULL);
2908 /* if node is not static and classed, we won't allow query */
2910 node = lookup_type_node_I (type);
2911 if (node && node->is_classed && !node->plugin)
2913 /* type is classed and probably even instantiatable */
2914 G_READ_LOCK (&type_rw_lock);
2915 if (node->data) /* type is static or referenced */
2917 query->type = NODE_TYPE (node);
2918 query->type_name = NODE_NAME (node);
2919 query->class_size = node->data->class.class_size;
2920 query->instance_size = node->is_instantiatable ? node->data->instance.instance_size : 0;
2922 G_READ_UNLOCK (&type_rw_lock);
2927 /* --- implementation details --- */
2929 g_type_test_flags (GType type,
2933 gboolean result = FALSE;
2935 node = lookup_type_node_I (type);
2938 guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
2939 guint tflags = flags & TYPE_FLAG_MASK;
2943 GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (node);
2945 fflags = (finfo->type_flags & fflags) == fflags;
2952 G_READ_LOCK (&type_rw_lock);
2953 tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
2954 G_READ_UNLOCK (&type_rw_lock);
2959 result = tflags && fflags;
2966 g_type_get_plugin (GType type)
2970 node = lookup_type_node_I (type);
2972 return node ? node->plugin : NULL;
2976 g_type_interface_get_plugin (GType instance_type,
2977 GType interface_type)
2982 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL); /* G_TYPE_IS_INTERFACE() is an external call: _U */
2984 node = lookup_type_node_I (instance_type);
2985 iface = lookup_type_node_I (interface_type);
2988 IFaceHolder *iholder;
2989 GTypePlugin *plugin;
2991 G_READ_LOCK (&type_rw_lock);
2993 iholder = iface_node_get_holders_L (iface);
2994 while (iholder && iholder->instance_type != instance_type)
2995 iholder = iholder->next;
2996 plugin = iholder ? iholder->plugin : NULL;
2998 G_READ_UNLOCK (&type_rw_lock);
3003 g_return_val_if_fail (node == NULL, NULL);
3004 g_return_val_if_fail (iface == NULL, NULL);
3006 g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
3012 g_type_fundamental_next (void)
3016 G_READ_LOCK (&type_rw_lock);
3017 type = static_fundamental_next;
3018 G_READ_UNLOCK (&type_rw_lock);
3019 type = G_TYPE_MAKE_FUNDAMENTAL (type);
3020 return type <= G_TYPE_FUNDAMENTAL_MAX ? type : 0;
3024 g_type_fundamental (GType type_id)
3026 TypeNode *node = lookup_type_node_I (type_id);
3028 return node ? NODE_FUNDAMENTAL_TYPE (node) : 0;
3032 g_type_check_instance_is_a (GTypeInstance *type_instance,
3035 TypeNode *node, *iface;
3038 if (!type_instance || !type_instance->g_class)
3041 node = lookup_type_node_I (type_instance->g_class->g_type);
3042 iface = lookup_type_node_I (iface_type);
3043 check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
3049 g_type_check_class_is_a (GTypeClass *type_class,
3052 TypeNode *node, *iface;
3058 node = lookup_type_node_I (type_class->g_type);
3059 iface = lookup_type_node_I (is_a_type);
3060 check = node && node->is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
3066 g_type_check_instance_cast (GTypeInstance *type_instance,
3071 if (type_instance->g_class)
3073 TypeNode *node, *iface;
3074 gboolean is_instantiatable, check;
3076 node = lookup_type_node_I (type_instance->g_class->g_type);
3077 is_instantiatable = node && node->is_instantiatable;
3078 iface = lookup_type_node_I (iface_type);
3079 check = is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
3081 return type_instance;
3083 if (is_instantiatable)
3084 g_warning ("invalid cast from `%s' to `%s'",
3085 type_descriptive_name_I (type_instance->g_class->g_type),
3086 type_descriptive_name_I (iface_type));
3088 g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
3089 type_descriptive_name_I (type_instance->g_class->g_type),
3090 type_descriptive_name_I (iface_type));
3093 g_warning ("invalid unclassed pointer in cast to `%s'",
3094 type_descriptive_name_I (iface_type));
3097 return type_instance;
3101 g_type_check_class_cast (GTypeClass *type_class,
3106 TypeNode *node, *iface;
3107 gboolean is_classed, check;
3109 node = lookup_type_node_I (type_class->g_type);
3110 is_classed = node && node->is_classed;
3111 iface = lookup_type_node_I (is_a_type);
3112 check = is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
3117 g_warning ("invalid class cast from `%s' to `%s'",
3118 type_descriptive_name_I (type_class->g_type),
3119 type_descriptive_name_I (is_a_type));
3121 g_warning ("invalid unclassed type `%s' in class cast to `%s'",
3122 type_descriptive_name_I (type_class->g_type),
3123 type_descriptive_name_I (is_a_type));
3126 g_warning ("invalid class cast from (NULL) pointer to `%s'",
3127 type_descriptive_name_I (is_a_type));
3132 g_type_check_instance (GTypeInstance *type_instance)
3134 /* this function is just here to make the signal system
3135 * conveniently elaborated on instance checks
3139 if (type_instance->g_class)
3141 TypeNode *node = lookup_type_node_I (type_instance->g_class->g_type);
3143 if (node && node->is_instantiatable)
3146 g_warning ("instance of invalid non-instantiatable type `%s'",
3147 type_descriptive_name_I (type_instance->g_class->g_type));
3150 g_warning ("instance with invalid (NULL) class pointer");
3153 g_warning ("invalid (NULL) pointer instance");
3158 static inline gboolean
3159 type_check_is_value_type_U (GType type)
3161 GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT;
3164 /* common path speed up */
3165 node = lookup_type_node_I (type);
3166 if (node && node->mutatable_check_cache)
3169 G_READ_LOCK (&type_rw_lock);
3173 if (node->data && node->data->common.ref_count > 0 &&
3174 node->data->common.value_table->value_init)
3175 tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
3176 else if (NODE_IS_IFACE (node))
3180 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
3182 GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
3183 TypeNode *prnode = lookup_type_node_I (prtype);
3185 if (prnode->is_instantiatable)
3188 node = lookup_type_node_I (type);
3194 G_READ_UNLOCK (&type_rw_lock);
3196 return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT);
3200 g_type_check_is_value_type (GType type)
3202 return type_check_is_value_type_U (type);
3206 g_type_check_value (GValue *value)
3208 return value && type_check_is_value_type_U (value->g_type);
3212 g_type_check_value_holds (GValue *value,
3215 return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type);
3219 g_type_value_table_peek (GType type)
3221 GTypeValueTable *vtable = NULL;
3222 TypeNode *node = lookup_type_node_I (type);
3223 gboolean has_refed_data, has_table;
3226 /* speed up common code path, we're not 100% safe here,
3227 * but we should only get called with referenced types anyway
3229 data = node ? node->data : NULL;
3230 if (node && node->mutatable_check_cache)
3231 return data->common.value_table;
3233 G_READ_LOCK (&type_rw_lock);
3236 has_refed_data = node && node->data && node->data->common.ref_count;
3237 has_table = has_refed_data && node->data->common.value_table->value_init;
3241 vtable = node->data->common.value_table;
3242 else if (NODE_IS_IFACE (node))
3246 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
3248 GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
3249 TypeNode *prnode = lookup_type_node_I (prtype);
3251 if (prnode->is_instantiatable)
3254 node = lookup_type_node_I (type);
3255 goto restart_table_peek;
3261 G_READ_UNLOCK (&type_rw_lock);
3267 g_warning (G_STRLOC ": type id `%lu' is invalid", type);
3268 if (!has_refed_data)
3269 g_warning ("can't peek value table for type `%s' which is not currently referenced",
3270 type_descriptive_name_I (type));
3275 G_CONST_RETURN gchar*
3276 g_type_name_from_instance (GTypeInstance *instance)
3279 return "<NULL-instance>";
3281 return g_type_name_from_class (instance->g_class);
3284 G_CONST_RETURN gchar*
3285 g_type_name_from_class (GTypeClass *g_class)
3288 return "<NULL-class>";
3290 return g_type_name (g_class->g_type);
3294 /* --- foreign prototypes --- */
3295 extern void g_value_c_init (void); /* sync with gvalue.c */
3296 extern void g_value_types_init (void); /* sync with gvaluetypes.c */
3297 extern void g_enum_types_init (void); /* sync with genums.c */
3298 extern void g_param_type_init (void); /* sync with gparam.c */
3299 extern void g_boxed_type_init (void); /* sync with gboxed.c */
3300 extern void g_object_type_init (void); /* sync with gobject.c */
3301 extern void g_param_spec_types_init (void); /* sync with gparamspecs.c */
3302 extern void g_value_transforms_init (void); /* sync with gvaluetransform.c */
3303 extern void g_signal_init (void); /* sync with gsignal.c */
3306 /* --- initialization --- */
3308 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
3310 G_LOCK_DEFINE_STATIC (type_init_lock);
3311 const gchar *env_string;
3316 G_LOCK (type_init_lock);
3318 G_WRITE_LOCK (&type_rw_lock);
3320 if (static_quark_type_flags)
3322 G_WRITE_UNLOCK (&type_rw_lock);
3323 G_UNLOCK (type_init_lock);
3327 /* setup GObject library wide debugging flags */
3328 _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
3329 env_string = g_getenv ("GOBJECT_DEBUG");
3330 if (env_string != NULL)
3332 static GDebugKey debug_keys[] = {
3333 { "objects", G_TYPE_DEBUG_OBJECTS },
3334 { "signals", G_TYPE_DEBUG_SIGNALS },
3337 _g_type_debug_flags |= g_parse_debug_string (env_string,
3339 sizeof (debug_keys) / sizeof (debug_keys[0]));
3344 static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
3345 static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
3346 static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
3348 /* type qname hash table */
3349 static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
3351 /* invalid type G_TYPE_INVALID (0)
3353 static_fundamental_type_nodes[0] = NULL;
3355 /* void type G_TYPE_NONE
3357 node = type_node_fundamental_new_W (G_TYPE_NONE, "void", 0);
3358 type = NODE_TYPE (node);
3359 g_assert (type == G_TYPE_NONE);
3361 /* interface fundamental type G_TYPE_INTERFACE (!classed)
3363 memset (&info, 0, sizeof (info));
3364 node = type_node_fundamental_new_W (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
3365 type = NODE_TYPE (node);
3366 type_data_make_W (node, &info, NULL);
3367 g_assert (type == G_TYPE_INTERFACE);
3369 G_WRITE_UNLOCK (&type_rw_lock);
3373 /* G_TYPE_TYPE_PLUGIN
3375 g_type_plugin_get_type ();
3377 /* G_TYPE_* value types
3379 g_value_types_init ();
3381 /* G_TYPE_ENUM & G_TYPE_FLAGS
3383 g_enum_types_init ();
3387 g_boxed_type_init ();
3391 g_param_type_init ();
3395 g_object_type_init ();
3397 /* G_TYPE_PARAM_* pspec types
3399 g_param_spec_types_init ();
3401 /* Value Transformations
3403 g_value_transforms_init ();
3409 G_UNLOCK (type_init_lock);
3415 g_type_init_with_debug_flags (0);
3419 g_type_class_add_private (gpointer g_class,
3422 GType instance_type = ((GTypeClass *)g_class)->g_type;
3423 TypeNode *node = lookup_type_node_I (instance_type);
3426 if (!node || !node->is_instantiatable || !node->data || node->data->class.class != g_class)
3428 g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'",
3429 type_descriptive_name_I (instance_type));
3433 if (NODE_PARENT_TYPE (node))
3435 TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
3436 if (node->data->instance.private_size != pnode->data->instance.private_size)
3438 g_warning ("g_type_add_private() called multiple times for the same type");
3443 G_WRITE_LOCK (&type_rw_lock);
3445 offset = ALIGN_STRUCT (node->data->instance.private_size);
3446 node->data->instance.private_size = offset + private_size;
3448 G_WRITE_UNLOCK (&type_rw_lock);
3452 g_type_instance_get_private (GTypeInstance *instance,
3455 TypeNode *instance_node;
3456 TypeNode *private_node;
3457 TypeNode *parent_node;
3461 g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
3463 /* while instances are initialized, their class pointers change,
3464 * so figure the instances real class first
3466 if (instance_real_class_bsa)
3468 class = instance_real_class_get (instance);
3470 class = instance->g_class;
3473 class = instance->g_class;
3475 instance_node = lookup_type_node_I (class->g_type);
3476 if (G_UNLIKELY (!instance_node || !instance_node->is_instantiatable))
3478 g_warning ("instance of invalid non-instantiatable type `%s'",
3479 type_descriptive_name_I (instance->g_class->g_type));
3483 private_node = lookup_type_node_I (private_type);
3484 if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, instance_node)))
3486 g_warning ("attempt to retrieve private data for invalid type '%s'",
3487 type_descriptive_name_I (private_type));
3491 /* Note that we don't need a read lock, since instance existing
3492 * means that the instance class and all parent classes
3493 * exist, so the node->data, node->data->instance.instance_size,
3494 * and node->data->instance.private_size are not going to be changed.
3495 * for any of the relevant types.
3498 offset = ALIGN_STRUCT (instance_node->data->instance.instance_size);
3500 if (NODE_PARENT_TYPE (private_node))
3502 parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
3503 g_assert (parent_node->data && parent_node->data->common.ref_count);
3505 offset += ALIGN_STRUCT (parent_node->data->instance.private_size);
3508 return G_STRUCT_MEMBER_P (instance, offset);