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"
31 #include "gobjectalias.h"
33 /* NOTE: some functions (some internal variants and exported ones)
34 * invalidate data portions of the TypeNodes. if external functions/callbacks
35 * are called, pointers to memory maintained by TypeNodes have to be looked up
36 * again. this affects most of the struct TypeNode fields, e.g. ->children or
37 * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
38 * not ->supers[]), as all those memory portions can get realloc()ed during
39 * callback invocation.
42 * - g_type_from_name() should do an ordered array lookup after fetching the
43 * the quark, instead of a second hashtable lookup.
46 * lock handling issues when calling static functions are indicated by
47 * uppercase letter postfixes, all static functions have to have
48 * one of the below postfixes:
49 * - _I: [Indifferent about locking]
50 * function doesn't care about locks at all
51 * - _U: [Unlocked invocation]
52 * no read or write lock has to be held across function invocation
53 * (locks may be acquired and released during invocation though)
54 * - _L: [Locked invocation]
55 * a write lock or more than 0 read locks have to be held across
57 * - _W: [Write-locked invocation]
58 * a write lock has to be held across function invocation
59 * - _Wm: [Write-locked invocation, mutatable]
60 * like _W, but the write lock might be released and reacquired
61 * during invocation, watch your pointers
62 * - _WmREC: [Write-locked invocation, mutatable, recursive]
63 * like _Wm, but also acquires recursive mutex class_init_rec_mutex
67 #define G_READ_LOCK(rw_lock) do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0)
68 #define G_READ_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0)
69 #define G_WRITE_LOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL++\n"); g_static_rw_lock_writer_lock (rw_lock); } while (0)
70 #define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_static_rw_lock_writer_unlock (rw_lock); } while (0)
72 #define G_READ_LOCK(rw_lock) g_static_rw_lock_reader_lock (rw_lock)
73 #define G_READ_UNLOCK(rw_lock) g_static_rw_lock_reader_unlock (rw_lock)
74 #define G_WRITE_LOCK(rw_lock) g_static_rw_lock_writer_lock (rw_lock)
75 #define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
77 #define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
78 static const gchar _action[] = " invalidly modified type "; \
79 gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
81 g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
83 g_error ("%s()%s`%s'", _fname, _action, _tname); \
85 #define g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{ \
88 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
89 "%s: initialization assertion failed, use %s() prior to this function", \
90 G_STRLOC, G_STRINGIFY (init_function)); \
91 return (return_value); \
96 #define DEBUG_CODE(debug_type, code_block) G_STMT_START { \
97 if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
100 #else /* !G_ENABLE_DEBUG */
101 #define DEBUG_CODE(debug_type, code_block) /* code_block */
102 #endif /* G_ENABLE_DEBUG */
104 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
105 G_TYPE_FLAG_INSTANTIATABLE | \
106 G_TYPE_FLAG_DERIVABLE | \
107 G_TYPE_FLAG_DEEP_DERIVABLE)
108 #define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
109 #define SIZEOF_FUNDAMENTAL_INFO ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
110 sizeof (gpointer)), \
113 /* The 2*sizeof(size_t) alignment here is borrowed from
114 * GNU libc, so it should be good most everywhere.
115 * It is more conservative than is needed on some 64-bit
116 * platforms, but ia64 does require a 16-byte alignment.
117 * The SIMD extensions for x86 and ppc32 would want a
118 * larger alignment than this, but we don't need to
119 * do better than malloc.
121 #define STRUCT_ALIGNMENT (2 * sizeof (gsize))
122 #define ALIGN_STRUCT(offset) \
123 ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
126 /* --- typedefs --- */
127 typedef struct _TypeNode TypeNode;
128 typedef struct _CommonData CommonData;
129 typedef struct _IFaceData IFaceData;
130 typedef struct _ClassData ClassData;
131 typedef struct _InstanceData InstanceData;
132 typedef union _TypeData TypeData;
133 typedef struct _IFaceEntry IFaceEntry;
134 typedef struct _IFaceHolder IFaceHolder;
137 /* --- prototypes --- */
138 static inline GTypeFundamentalInfo* type_node_fundamental_info_I (TypeNode *node);
139 static void type_add_flags_W (TypeNode *node,
141 static void type_data_make_W (TypeNode *node,
142 const GTypeInfo *info,
143 const GTypeValueTable *value_table);
144 static inline void type_data_ref_Wm (TypeNode *node);
145 static inline void type_data_unref_WmREC (TypeNode *node,
147 static void type_data_last_unref_Wm (GType type,
149 static inline gpointer type_get_qdata_L (TypeNode *node,
151 static inline void type_set_qdata_W (TypeNode *node,
154 static IFaceHolder* type_iface_peek_holder_L (TypeNode *iface,
155 GType instance_type);
156 static gboolean type_iface_vtable_base_init_Wm (TypeNode *iface,
158 static void type_iface_vtable_iface_init_Wm (TypeNode *iface,
160 static gboolean type_node_is_a_L (TypeNode *node,
161 TypeNode *iface_node);
164 /* --- enumeration --- */
166 /* The InitState enumeration is used to track the progress of initializing
167 * both classes and interface vtables. Keeping the state of initialization
168 * is necessary to handle new interfaces being added while we are initializing
169 * the class or other interfaces.
181 /* --- structures --- */
185 guint n_children : 12;
187 guint _prot_n_ifaces_prerequisites : 9;
188 guint is_classed : 1;
189 guint is_instantiatable : 1;
190 guint mutatable_check_cache : 1; /* combines some common path checks */
192 TypeData * volatile data;
196 IFaceEntry *iface_entries; /* for !iface types */
197 GType *prerequisistes;
199 GType supers[1]; /* flexible array */
201 #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
202 #define MAX_N_SUPERS (255)
203 #define MAX_N_CHILDREN (4095)
204 #define MAX_N_IFACES (511)
205 #define MAX_N_PREREQUISITES (MAX_N_IFACES)
206 #define NODE_TYPE(node) (node->supers[0])
207 #define NODE_PARENT_TYPE(node) (node->supers[1])
208 #define NODE_FUNDAMENTAL_TYPE(node) (node->supers[node->n_supers])
209 #define NODE_NAME(node) (g_quark_to_string (node->qname))
210 #define NODE_IS_IFACE(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
211 #define CLASSED_NODE_N_IFACES(node) ((node)->_prot_n_ifaces_prerequisites)
212 #define CLASSED_NODE_IFACES_ENTRIES(node) ((node)->_prot.iface_entries)
213 #define IFACE_NODE_N_PREREQUISITES(node) ((node)->_prot_n_ifaces_prerequisites)
214 #define IFACE_NODE_PREREQUISITES(node) ((node)->_prot.prerequisistes)
215 #define iface_node_get_holders_L(node) ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
216 #define iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
217 #define iface_node_get_dependants_array_L(n) ((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
218 #define iface_node_set_dependants_array_W(n,d) (type_set_qdata_W ((n), static_quark_dependants_array, (d)))
219 #define TYPE_ID_MASK ((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1))
221 #define NODE_IS_ANCESTOR(ancestor, node) \
222 ((ancestor)->n_supers <= (node)->n_supers && \
223 (node)->supers[(node)->n_supers - (ancestor)->n_supers] == NODE_TYPE (ancestor))
229 GInterfaceInfo *info;
236 GTypeInterface *vtable;
237 InitState init_state;
242 GTypeValueTable *value_table;
248 GBaseInitFunc vtable_init_base;
249 GBaseFinalizeFunc vtable_finalize_base;
250 GClassInitFunc dflt_init;
251 GClassFinalizeFunc dflt_finalize;
252 gconstpointer dflt_data;
253 gpointer dflt_vtable;
259 guint init_state : 4;
260 GBaseInitFunc class_init_base;
261 GBaseFinalizeFunc class_finalize_base;
262 GClassInitFunc class_init;
263 GClassFinalizeFunc class_finalize;
264 gconstpointer class_data;
271 guint init_state : 4;
272 GBaseInitFunc class_init_base;
273 GBaseFinalizeFunc class_finalize_base;
274 GClassInitFunc class_init;
275 GClassFinalizeFunc class_finalize;
276 gconstpointer class_data;
278 guint16 instance_size;
279 guint16 private_size;
281 GInstanceInitFunc instance_init;
288 InstanceData instance;
292 GTypeClassCacheFunc cache_func;
296 GTypeInterfaceCheckFunc check_func;
300 /* --- variables --- */
301 static GStaticRWLock type_rw_lock = G_STATIC_RW_LOCK_INIT;
302 static GStaticRecMutex class_init_rec_mutex = G_STATIC_REC_MUTEX_INIT;
303 static guint static_n_class_cache_funcs = 0;
304 static ClassCacheFunc *static_class_cache_funcs = NULL;
305 static guint static_n_iface_check_funcs = 0;
306 static IFaceCheckFunc *static_iface_check_funcs = NULL;
307 static GQuark static_quark_type_flags = 0;
308 static GQuark static_quark_iface_holder = 0;
309 static GQuark static_quark_dependants_array = 0;
310 GTypeDebugFlags _g_type_debug_flags = 0;
313 /* --- type nodes --- */
314 static GHashTable *static_type_nodes_ht = NULL;
315 static TypeNode *static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) + 1] = { NULL, };
316 static GType static_fundamental_next = G_TYPE_RESERVED_USER_FIRST;
318 static inline TypeNode*
319 lookup_type_node_I (register GType utype)
321 if (utype > G_TYPE_FUNDAMENTAL_MAX)
322 return (TypeNode*) (utype & ~TYPE_ID_MASK);
324 return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT];
328 type_node_any_new_W (TypeNode *pnode,
332 GTypeFundamentalFlags type_flags)
337 guint i, node_size = 0;
339 n_supers = pnode ? pnode->n_supers + 1 : 0;
342 node_size += SIZEOF_FUNDAMENTAL_INFO; /* fundamental type info */
343 node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
344 node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */
345 node = g_malloc0 (node_size);
346 if (!pnode) /* offset fundamental types */
348 node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
349 static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;
355 g_assert ((type & TYPE_ID_MASK) == 0);
357 node->n_supers = n_supers;
360 node->supers[0] = type;
363 node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
364 node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
366 if (NODE_IS_IFACE (node))
368 IFACE_NODE_N_PREREQUISITES (node) = 0;
369 IFACE_NODE_PREREQUISITES (node) = NULL;
373 CLASSED_NODE_N_IFACES (node) = 0;
374 CLASSED_NODE_IFACES_ENTRIES (node) = NULL;
379 node->supers[0] = type;
380 memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
382 node->is_classed = pnode->is_classed;
383 node->is_instantiatable = pnode->is_instantiatable;
385 if (NODE_IS_IFACE (node))
387 IFACE_NODE_N_PREREQUISITES (node) = 0;
388 IFACE_NODE_PREREQUISITES (node) = NULL;
394 CLASSED_NODE_N_IFACES (node) = CLASSED_NODE_N_IFACES (pnode);
395 CLASSED_NODE_IFACES_ENTRIES (node) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode),
396 sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode)[0]) *
397 CLASSED_NODE_N_IFACES (node));
398 for (j = 0; j < CLASSED_NODE_N_IFACES (node); j++)
400 CLASSED_NODE_IFACES_ENTRIES (node)[j].vtable = NULL;
401 CLASSED_NODE_IFACES_ENTRIES (node)[j].init_state = UNINITIALIZED;
405 i = pnode->n_children++;
406 pnode->children = g_renew (GType, pnode->children, pnode->n_children);
407 pnode->children[i] = type;
410 node->plugin = plugin;
411 node->n_children = 0;
412 node->children = NULL;
414 node->qname = g_quark_from_string (name);
415 node->global_gdata = NULL;
417 g_hash_table_insert (static_type_nodes_ht,
418 GUINT_TO_POINTER (node->qname),
423 static inline GTypeFundamentalInfo*
424 type_node_fundamental_info_I (TypeNode *node)
426 GType ftype = NODE_FUNDAMENTAL_TYPE (node);
428 if (ftype != NODE_TYPE (node))
429 node = lookup_type_node_I (ftype);
431 return node ? G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO) : NULL;
435 type_node_fundamental_new_W (GType ftype,
437 GTypeFundamentalFlags type_flags)
439 GTypeFundamentalInfo *finfo;
442 g_assert ((ftype & TYPE_ID_MASK) == 0);
443 g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX);
445 if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next)
446 static_fundamental_next++;
448 type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
450 node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
452 finfo = type_node_fundamental_info_I (node);
453 finfo->type_flags = type_flags;
459 type_node_new_W (TypeNode *pnode,
465 g_assert (pnode->n_supers < MAX_N_SUPERS);
466 g_assert (pnode->n_children < MAX_N_CHILDREN);
468 return type_node_any_new_W (pnode, NODE_FUNDAMENTAL_TYPE (pnode), name, plugin, 0);
471 static inline IFaceEntry*
472 type_lookup_iface_entry_L (TypeNode *node,
473 TypeNode *iface_node)
475 if (NODE_IS_IFACE (iface_node) && CLASSED_NODE_N_IFACES (node))
477 IFaceEntry *ifaces = CLASSED_NODE_IFACES_ENTRIES (node) - 1;
478 guint n_ifaces = CLASSED_NODE_N_IFACES (node);
479 GType iface_type = NODE_TYPE (iface_node);
486 i = (n_ifaces + 1) >> 1;
488 if (iface_type == check->iface_type)
490 else if (iface_type > check->iface_type)
495 else /* if (iface_type < check->iface_type) */
504 static inline gboolean
505 type_lookup_prerequisite_L (TypeNode *iface,
506 GType prerequisite_type)
508 if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface))
510 GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1;
511 guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface);
518 i = (n_prerequisites + 1) >> 1;
519 check = prerequisites + i;
520 if (prerequisite_type == *check)
522 else if (prerequisite_type > *check)
524 n_prerequisites -= i;
525 prerequisites = check;
527 else /* if (prerequisite_type < *check) */
528 n_prerequisites = i - 1;
530 while (n_prerequisites);
536 type_descriptive_name_I (GType type)
540 TypeNode *node = lookup_type_node_I (type);
542 return node ? NODE_NAME (node) : "<unknown>";
549 /* --- type consistency checks --- */
551 check_plugin_U (GTypePlugin *plugin,
552 gboolean need_complete_type_info,
553 gboolean need_complete_interface_info,
554 const gchar *type_name)
556 /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U
560 g_warning ("plugin handle for type `%s' is NULL",
564 if (!G_IS_TYPE_PLUGIN (plugin))
566 g_warning ("plugin pointer (%p) for type `%s' is invalid",
570 if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
572 g_warning ("plugin for type `%s' has no complete_type_info() implementation",
576 if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
578 g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
586 check_type_name_I (const gchar *type_name)
588 static const gchar extra_chars[] = "-_+";
589 const gchar *p = type_name;
592 if (!type_name[0] || !type_name[1] || !type_name[2])
594 g_warning ("type name `%s' is too short", type_name);
597 /* check the first letter */
598 name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
599 for (p = type_name + 1; *p; p++)
600 name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
601 (p[0] >= 'a' && p[0] <= 'z') ||
602 (p[0] >= '0' && p[0] <= '9') ||
603 strchr (extra_chars, p[0]));
606 g_warning ("type name `%s' contains invalid characters", type_name);
609 if (g_type_from_name (type_name))
611 g_warning ("cannot register existing type `%s'", type_name);
619 check_derivation_I (GType parent_type,
620 const gchar *type_name)
623 GTypeFundamentalInfo* finfo;
625 pnode = lookup_type_node_I (parent_type);
628 g_warning ("cannot derive type `%s' from invalid parent type `%s'",
630 type_descriptive_name_I (parent_type));
633 finfo = type_node_fundamental_info_I (pnode);
634 /* ensure flat derivability */
635 if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
637 g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
642 /* ensure deep derivability */
643 if (parent_type != NODE_FUNDAMENTAL_TYPE (pnode) &&
644 !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
646 g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
656 check_collect_format_I (const gchar *collect_format)
658 const gchar *p = collect_format;
659 gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
660 G_VALUE_COLLECT_INT64, G_VALUE_COLLECT_DOUBLE,
661 G_VALUE_COLLECT_POINTER, 0 };
664 if (!strchr (valid_format, *p++))
666 return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
670 check_value_table_I (const gchar *type_name,
671 const GTypeValueTable *value_table)
675 else if (value_table->value_init == NULL)
677 if (value_table->value_free || value_table->value_copy ||
678 value_table->value_peek_pointer ||
679 value_table->collect_format || value_table->collect_value ||
680 value_table->lcopy_format || value_table->lcopy_value)
681 g_warning ("cannot handle uninitializable values of type `%s'",
685 else /* value_table->value_init != NULL */
687 if (!value_table->value_free)
690 * g_warning ("missing `value_free()' for type `%s'", type_name);
694 if (!value_table->value_copy)
696 g_warning ("missing `value_copy()' for type `%s'", type_name);
699 if ((value_table->collect_format || value_table->collect_value) &&
700 (!value_table->collect_format || !value_table->collect_value))
702 g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
706 if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
708 g_warning ("the `%s' specification for type `%s' is too long or invalid",
713 if ((value_table->lcopy_format || value_table->lcopy_value) &&
714 (!value_table->lcopy_format || !value_table->lcopy_value))
716 g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
720 if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
722 g_warning ("the `%s' specification for type `%s' is too long or invalid",
732 check_type_info_I (TypeNode *pnode,
734 const gchar *type_name,
735 const GTypeInfo *info)
737 GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (lookup_type_node_I (ftype));
738 gboolean is_interface = ftype == G_TYPE_INTERFACE;
740 g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX && !(ftype & TYPE_ID_MASK));
742 /* check instance members */
743 if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
744 (info->instance_size || info->n_preallocs || info->instance_init))
747 g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
751 g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
755 /* check class & interface members */
756 if (!((finfo->type_flags & G_TYPE_FLAG_CLASSED) || is_interface) &&
757 (info->class_init || info->class_finalize || info->class_data ||
758 info->class_size || info->base_init || info->base_finalize))
761 g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
765 g_warning ("cannot create class for `%s' as non-classed fundamental",
769 /* check interface size */
770 if (is_interface && info->class_size < sizeof (GTypeInterface))
772 g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
776 /* check class size */
777 if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
779 if (info->class_size < sizeof (GTypeClass))
781 g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
785 if (pnode && info->class_size < pnode->data->class.class_size)
787 g_warning ("specified class size for type `%s' is smaller "
788 "than the parent type's `%s' class size",
794 /* check instance size */
795 if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
797 if (info->instance_size < sizeof (GTypeInstance))
799 g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
803 if (pnode && info->instance_size < pnode->data->instance.instance_size)
805 g_warning ("specified instance size for type `%s' is smaller "
806 "than the parent type's `%s' instance size",
817 find_conforming_child_type_L (TypeNode *pnode,
820 TypeNode *node = NULL;
823 if (type_lookup_iface_entry_L (pnode, iface))
826 for (i = 0; i < pnode->n_children && !node; i++)
827 node = find_conforming_child_type_L (lookup_type_node_I (pnode->children[i]), iface);
833 check_add_interface_L (GType instance_type,
836 TypeNode *node = lookup_type_node_I (instance_type);
837 TypeNode *iface = lookup_type_node_I (iface_type);
840 GType *prerequisites;
844 if (!node || !node->is_instantiatable)
846 g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
847 type_descriptive_name_I (instance_type));
850 if (!iface || !NODE_IS_IFACE (iface))
852 g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
853 type_descriptive_name_I (iface_type),
857 tnode = lookup_type_node_I (NODE_PARENT_TYPE (iface));
858 if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
860 /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
861 g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
867 /* allow overriding of interface type introduced for parent type */
868 entry = type_lookup_iface_entry_L (node, iface);
869 if (entry && entry->vtable == NULL && !type_iface_peek_holder_L (iface, NODE_TYPE (node)))
871 /* ok, we do conform to this interface already, but the interface vtable was not
872 * yet intialized, and we just conform to the interface because it got added to
873 * one of our parents. so we allow overriding of holder info here.
877 /* check whether one of our children already conforms (or whether the interface
878 * got added to this node already)
880 tnode = find_conforming_child_type_L (node, iface); /* tnode is_a node */
883 g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
889 prerequisites = IFACE_NODE_PREREQUISITES (iface);
890 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
892 tnode = lookup_type_node_I (prerequisites[i]);
893 if (!type_node_is_a_L (node, tnode))
895 g_warning ("cannot add interface type `%s' to type `%s' which does not conform to prerequisite `%s'",
906 check_interface_info_I (TypeNode *iface,
908 const GInterfaceInfo *info)
910 if ((info->interface_finalize || info->interface_data) && !info->interface_init)
912 g_warning ("interface type `%s' for type `%s' comes without initializer",
914 type_descriptive_name_I (instance_type));
921 /* --- type info (type node data) --- */
923 type_data_make_W (TypeNode *node,
924 const GTypeInfo *info,
925 const GTypeValueTable *value_table)
928 GTypeValueTable *vtable = NULL;
929 guint vtable_size = 0;
931 g_assert (node->data == NULL && info != NULL);
935 TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
938 vtable = pnode->data->common.value_table;
941 static const GTypeValueTable zero_vtable = { NULL, };
943 value_table = &zero_vtable;
948 /* need to setup vtable_size since we have to allocate it with data in one chunk */
949 vtable_size = sizeof (GTypeValueTable);
950 if (value_table->collect_format)
951 vtable_size += strlen (value_table->collect_format);
952 if (value_table->lcopy_format)
953 vtable_size += strlen (value_table->lcopy_format);
957 if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
959 data = g_malloc0 (sizeof (InstanceData) + vtable_size);
961 vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
962 data->instance.class_size = info->class_size;
963 data->instance.class_init_base = info->base_init;
964 data->instance.class_finalize_base = info->base_finalize;
965 data->instance.class_init = info->class_init;
966 data->instance.class_finalize = info->class_finalize;
967 data->instance.class_data = info->class_data;
968 data->instance.class = NULL;
969 data->instance.init_state = UNINITIALIZED;
970 data->instance.instance_size = info->instance_size;
971 /* We'll set the final value for data->instance.private size
972 * after the parent class has been initialized
974 data->instance.private_size = 0;
975 #ifdef DISABLE_MEM_POOLS
976 data->instance.n_preallocs = 0;
977 #else /* !DISABLE_MEM_POOLS */
978 data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
979 #endif /* !DISABLE_MEM_POOLS */
980 data->instance.instance_init = info->instance_init;
982 else if (node->is_classed) /* only classed */
984 data = g_malloc0 (sizeof (ClassData) + vtable_size);
986 vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
987 data->class.class_size = info->class_size;
988 data->class.class_init_base = info->base_init;
989 data->class.class_finalize_base = info->base_finalize;
990 data->class.class_init = info->class_init;
991 data->class.class_finalize = info->class_finalize;
992 data->class.class_data = info->class_data;
993 data->class.class = NULL;
994 data->class.init_state = UNINITIALIZED;
996 else if (NODE_IS_IFACE (node))
998 data = g_malloc0 (sizeof (IFaceData) + vtable_size);
1000 vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
1001 data->iface.vtable_size = info->class_size;
1002 data->iface.vtable_init_base = info->base_init;
1003 data->iface.vtable_finalize_base = info->base_finalize;
1004 data->iface.dflt_init = info->class_init;
1005 data->iface.dflt_finalize = info->class_finalize;
1006 data->iface.dflt_data = info->class_data;
1007 data->iface.dflt_vtable = NULL;
1011 data = g_malloc0 (sizeof (CommonData) + vtable_size);
1013 vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
1017 node->data->common.ref_count = 1;
1023 /* we allocate the vtable and its strings together with the type data, so
1024 * children can take over their parent's vtable pointer, and we don't
1025 * need to worry freeing it or not when the child data is destroyed
1027 *vtable = *value_table;
1028 p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable));
1030 vtable->collect_format = p;
1031 if (value_table->collect_format)
1033 strcat (p, value_table->collect_format);
1034 p += strlen (value_table->collect_format);
1038 vtable->lcopy_format = p;
1039 if (value_table->lcopy_format)
1040 strcat (p, value_table->lcopy_format);
1042 node->data->common.value_table = vtable;
1043 node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL &&
1044 !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) &
1045 GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))));
1047 g_assert (node->data->common.value_table != NULL); /* paranoid */
1051 type_data_ref_Wm (TypeNode *node)
1055 TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1057 GTypeValueTable tmp_value_table;
1059 g_assert (node->plugin != NULL);
1063 type_data_ref_Wm (pnode);
1065 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1068 memset (&tmp_info, 0, sizeof (tmp_info));
1069 memset (&tmp_value_table, 0, sizeof (tmp_value_table));
1071 G_WRITE_UNLOCK (&type_rw_lock);
1072 g_type_plugin_use (node->plugin);
1073 g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
1074 G_WRITE_LOCK (&type_rw_lock);
1076 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1078 check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (node), NODE_NAME (node), &tmp_info);
1079 type_data_make_W (node, &tmp_info,
1080 check_value_table_I (NODE_NAME (node),
1081 &tmp_value_table) ? &tmp_value_table : NULL);
1085 g_assert (node->data->common.ref_count > 0);
1087 node->data->common.ref_count += 1;
1092 type_data_unref_WmREC (TypeNode *node,
1095 g_assert (node->data && node->data->common.ref_count);
1096 if (node->data->common.ref_count > 1)
1097 node->data->common.ref_count -= 1;
1100 GType node_type = NODE_TYPE (node);
1103 g_warning ("static type `%s' unreferenced too often",
1107 G_WRITE_UNLOCK (&type_rw_lock);
1108 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
1109 G_WRITE_LOCK (&type_rw_lock);
1110 type_data_last_unref_Wm (node_type, uncached);
1111 g_static_rec_mutex_unlock (&class_init_rec_mutex);
1116 type_node_add_iface_entry_W (TypeNode *node,
1118 IFaceEntry *parent_entry)
1120 IFaceEntry *entries;
1123 g_assert (node->is_instantiatable && CLASSED_NODE_N_IFACES (node) < MAX_N_IFACES);
1125 entries = CLASSED_NODE_IFACES_ENTRIES (node);
1126 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1127 if (entries[i].iface_type == iface_type)
1129 /* this can happen in two cases:
1130 * - our parent type already conformed to iface_type and node
1131 * got it's own holder info. here, our children already have
1132 * entries and NULL vtables, since this will only work for
1133 * uninitialized classes.
1134 * - an interface type is added to an ancestor after it was
1135 * added to a child type.
1138 g_assert (entries[i].vtable == NULL && entries[i].init_state == UNINITIALIZED);
1141 /* sick, interface is added to ancestor *after* child type;
1142 * nothing todo, the entry and our children were already setup correctly
1147 else if (entries[i].iface_type > iface_type)
1149 CLASSED_NODE_N_IFACES (node) += 1;
1150 CLASSED_NODE_IFACES_ENTRIES (node) = g_renew (IFaceEntry,
1151 CLASSED_NODE_IFACES_ENTRIES (node),
1152 CLASSED_NODE_N_IFACES (node));
1153 entries = CLASSED_NODE_IFACES_ENTRIES (node);
1154 g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (CLASSED_NODE_N_IFACES (node) - i - 1));
1155 entries[i].iface_type = iface_type;
1156 entries[i].vtable = NULL;
1157 entries[i].init_state = UNINITIALIZED;
1161 if (node->data && node->data->class.init_state >= BASE_IFACE_INIT)
1163 entries[i].init_state = INITIALIZED;
1164 entries[i].vtable = parent_entry->vtable;
1166 for (i = 0; i < node->n_children; i++)
1167 type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), iface_type, &entries[i]);
1172 type_add_interface_Wm (TypeNode *node,
1174 const GInterfaceInfo *info,
1175 GTypePlugin *plugin)
1177 IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
1181 g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin)));
1183 iholder->next = iface_node_get_holders_L (iface);
1184 iface_node_set_holders_W (iface, iholder);
1185 iholder->instance_type = NODE_TYPE (node);
1186 iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
1187 iholder->plugin = plugin;
1189 /* create an iface entry for this type */
1190 type_node_add_iface_entry_W (node, NODE_TYPE (iface), NULL);
1192 /* if the class is already (partly) initialized, we may need to base
1193 * initalize and/or initialize the new interface.
1197 InitState class_state = node->data->class.init_state;
1199 if (class_state >= BASE_IFACE_INIT)
1200 type_iface_vtable_base_init_Wm (iface, node);
1202 if (class_state >= IFACE_INIT)
1203 type_iface_vtable_iface_init_Wm (iface, node);
1206 /* create iface entries for children of this type */
1207 entry = type_lookup_iface_entry_L (node, iface);
1208 for (i = 0; i < node->n_children; i++)
1209 type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), NODE_TYPE (iface), entry);
1213 type_iface_add_prerequisite_W (TypeNode *iface,
1214 TypeNode *prerequisite_node)
1216 GType prerequisite_type = NODE_TYPE (prerequisite_node);
1217 GType *prerequisites, *dependants;
1218 guint n_dependants, i;
1220 g_assert (NODE_IS_IFACE (iface) &&
1221 IFACE_NODE_N_PREREQUISITES (iface) < MAX_N_PREREQUISITES &&
1222 (prerequisite_node->is_instantiatable || NODE_IS_IFACE (prerequisite_node)));
1224 prerequisites = IFACE_NODE_PREREQUISITES (iface);
1225 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1226 if (prerequisites[i] == prerequisite_type)
1227 return; /* we already have that prerequisiste */
1228 else if (prerequisites[i] > prerequisite_type)
1230 IFACE_NODE_N_PREREQUISITES (iface) += 1;
1231 IFACE_NODE_PREREQUISITES (iface) = g_renew (GType,
1232 IFACE_NODE_PREREQUISITES (iface),
1233 IFACE_NODE_N_PREREQUISITES (iface));
1234 prerequisites = IFACE_NODE_PREREQUISITES (iface);
1235 g_memmove (prerequisites + i + 1, prerequisites + i,
1236 sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1));
1237 prerequisites[i] = prerequisite_type;
1239 /* we want to get notified when prerequisites get added to prerequisite_node */
1240 if (NODE_IS_IFACE (prerequisite_node))
1242 dependants = iface_node_get_dependants_array_L (prerequisite_node);
1243 n_dependants = dependants ? dependants[0] : 0;
1245 dependants = g_renew (GType, dependants, n_dependants + 1);
1246 dependants[n_dependants] = NODE_TYPE (iface);
1247 dependants[0] = n_dependants;
1248 iface_node_set_dependants_array_W (prerequisite_node, dependants);
1251 /* we need to notify all dependants */
1252 dependants = iface_node_get_dependants_array_L (iface);
1253 n_dependants = dependants ? dependants[0] : 0;
1254 for (i = 1; i <= n_dependants; i++)
1255 type_iface_add_prerequisite_W (lookup_type_node_I (dependants[i]), prerequisite_node);
1259 g_type_interface_add_prerequisite (GType interface_type,
1260 GType prerequisite_type)
1262 TypeNode *iface, *prerequisite_node;
1263 IFaceHolder *holders;
1265 g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type)); /* G_TYPE_IS_INTERFACE() is an external call: _U */
1266 g_return_if_fail (!g_type_is_a (interface_type, prerequisite_type));
1267 g_return_if_fail (!g_type_is_a (prerequisite_type, interface_type));
1269 iface = lookup_type_node_I (interface_type);
1270 prerequisite_node = lookup_type_node_I (prerequisite_type);
1271 if (!iface || !prerequisite_node || !NODE_IS_IFACE (iface))
1273 g_warning ("interface type `%s' or prerequisite type `%s' invalid",
1274 type_descriptive_name_I (interface_type),
1275 type_descriptive_name_I (prerequisite_type));
1278 G_WRITE_LOCK (&type_rw_lock);
1279 holders = iface_node_get_holders_L (iface);
1282 G_WRITE_UNLOCK (&type_rw_lock);
1283 g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'",
1284 type_descriptive_name_I (prerequisite_type),
1285 type_descriptive_name_I (interface_type),
1286 type_descriptive_name_I (holders->instance_type));
1289 if (prerequisite_node->is_instantiatable)
1293 /* can have at most one publically installable instantiatable prerequisite */
1294 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1296 TypeNode *prnode = lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface)[i]);
1298 if (prnode->is_instantiatable)
1300 G_WRITE_UNLOCK (&type_rw_lock);
1301 g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
1302 type_descriptive_name_I (prerequisite_type),
1303 type_descriptive_name_I (interface_type),
1304 type_descriptive_name_I (NODE_TYPE (prnode)));
1309 for (i = 0; i < prerequisite_node->n_supers + 1; i++)
1310 type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisite_node->supers[i]));
1311 G_WRITE_UNLOCK (&type_rw_lock);
1313 else if (NODE_IS_IFACE (prerequisite_node))
1315 GType *prerequisites;
1318 prerequisites = IFACE_NODE_PREREQUISITES (prerequisite_node);
1319 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (prerequisite_node); i++)
1320 type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisites[i]));
1321 type_iface_add_prerequisite_W (iface, prerequisite_node);
1322 G_WRITE_UNLOCK (&type_rw_lock);
1326 G_WRITE_UNLOCK (&type_rw_lock);
1327 g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface",
1328 type_descriptive_name_I (prerequisite_type),
1329 type_descriptive_name_I (interface_type));
1333 GType* /* free result */
1334 g_type_interface_prerequisites (GType interface_type,
1335 guint *n_prerequisites)
1339 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
1341 iface = lookup_type_node_I (interface_type);
1345 TypeNode *inode = NULL;
1348 G_READ_LOCK (&type_rw_lock);
1349 types = g_new0 (GType, IFACE_NODE_N_PREREQUISITES (iface) + 1);
1350 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1352 GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
1353 TypeNode *node = lookup_type_node_I (prerequisite);
1354 if (node->is_instantiatable &&
1355 (!inode || type_node_is_a_L (node, inode)))
1358 types[n++] = NODE_TYPE (node);
1361 types[n++] = NODE_TYPE (inode);
1363 if (n_prerequisites)
1364 *n_prerequisites = n;
1365 G_READ_UNLOCK (&type_rw_lock);
1371 if (n_prerequisites)
1372 *n_prerequisites = 0;
1380 type_iface_peek_holder_L (TypeNode *iface,
1381 GType instance_type)
1383 IFaceHolder *iholder;
1385 g_assert (NODE_IS_IFACE (iface));
1387 iholder = iface_node_get_holders_L (iface);
1388 while (iholder && iholder->instance_type != instance_type)
1389 iholder = iholder->next;
1394 type_iface_retrieve_holder_info_Wm (TypeNode *iface,
1395 GType instance_type,
1398 IFaceHolder *iholder = type_iface_peek_holder_L (iface, instance_type);
1400 if (iholder && !iholder->info && need_info)
1402 GInterfaceInfo tmp_info;
1404 g_assert (iholder->plugin != NULL);
1406 type_data_ref_Wm (iface);
1408 INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface));
1410 memset (&tmp_info, 0, sizeof (tmp_info));
1412 G_WRITE_UNLOCK (&type_rw_lock);
1413 g_type_plugin_use (iholder->plugin);
1414 g_type_plugin_complete_interface_info (iholder->plugin, instance_type, NODE_TYPE (iface), &tmp_info);
1415 G_WRITE_LOCK (&type_rw_lock);
1417 INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
1419 check_interface_info_I (iface, instance_type, &tmp_info);
1420 iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
1423 return iholder; /* we don't modify write lock upon returning NULL */
1427 type_iface_blow_holder_info_Wm (TypeNode *iface,
1428 GType instance_type)
1430 IFaceHolder *iholder = iface_node_get_holders_L (iface);
1432 g_assert (NODE_IS_IFACE (iface));
1434 while (iholder->instance_type != instance_type)
1435 iholder = iholder->next;
1437 if (iholder->info && iholder->plugin)
1439 g_free (iholder->info);
1440 iholder->info = NULL;
1442 G_WRITE_UNLOCK (&type_rw_lock);
1443 g_type_plugin_unuse (iholder->plugin);
1444 G_WRITE_LOCK (&type_rw_lock);
1446 type_data_unref_WmREC (iface, FALSE);
1450 /* Assumes type's class already exists
1452 static inline size_t
1453 type_total_instance_size_I (TypeNode *node)
1455 gsize total_instance_size;
1457 total_instance_size = node->data->instance.instance_size;
1458 if (node->data->instance.private_size != 0)
1459 total_instance_size = ALIGN_STRUCT (total_instance_size) + node->data->instance.private_size;
1461 return total_instance_size;
1464 /* --- type structure creation/destruction --- */
1468 } InstanceRealClass;
1470 instance_real_class_cmp (gconstpointer p1,
1473 const InstanceRealClass *irc1 = p1;
1474 const InstanceRealClass *irc2 = p2;
1475 guint8 *i1 = irc1->instance;
1476 guint8 *i2 = irc2->instance;
1477 return G_BSEARCH_ARRAY_CMP (i1, i2);
1479 G_LOCK_DEFINE_STATIC (instance_real_class);
1480 static GBSearchArray *instance_real_class_bsa = NULL;
1481 static GBSearchConfig instance_real_class_bconfig = {
1482 sizeof (InstanceRealClass),
1483 instance_real_class_cmp,
1487 instance_real_class_set (gpointer instance,
1490 InstanceRealClass key;
1491 key.instance = instance;
1493 G_LOCK (instance_real_class);
1494 if (!instance_real_class_bsa)
1495 instance_real_class_bsa = g_bsearch_array_create (&instance_real_class_bconfig);
1496 instance_real_class_bsa = g_bsearch_array_replace (instance_real_class_bsa, &instance_real_class_bconfig, &key);
1497 G_UNLOCK (instance_real_class);
1500 instance_real_class_remove (gpointer instance)
1502 InstanceRealClass key, *node;
1504 key.instance = instance;
1505 G_LOCK (instance_real_class);
1506 node = g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key);
1507 index = g_bsearch_array_get_index (instance_real_class_bsa, &instance_real_class_bconfig, node);
1508 instance_real_class_bsa = g_bsearch_array_remove (instance_real_class_bsa, &instance_real_class_bconfig, index);
1509 if (!g_bsearch_array_get_n_nodes (instance_real_class_bsa))
1511 g_bsearch_array_free (instance_real_class_bsa, &instance_real_class_bconfig);
1512 instance_real_class_bsa = NULL;
1514 G_UNLOCK (instance_real_class);
1516 static inline GTypeClass*
1517 instance_real_class_get (gpointer instance)
1519 InstanceRealClass key, *node;
1521 key.instance = instance;
1522 G_LOCK (instance_real_class);
1523 node = instance_real_class_bsa ? g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key) : NULL;
1524 class = node ? node->class : NULL;
1525 G_UNLOCK (instance_real_class);
1530 g_type_create_instance (GType type)
1533 GTypeInstance *instance;
1535 guint i, total_size;
1537 node = lookup_type_node_I (type);
1538 if (!node || !node->is_instantiatable)
1540 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1541 type_descriptive_name_I (type));
1544 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1545 if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (type))
1547 g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1548 type_descriptive_name_I (type));
1552 class = g_type_class_ref (type);
1553 total_size = type_total_instance_size_I (node);
1555 instance = g_slice_alloc0 (total_size);
1557 if (node->data->instance.private_size)
1558 instance_real_class_set (instance, class);
1559 for (i = node->n_supers; i > 0; i--)
1563 pnode = lookup_type_node_I (node->supers[i]);
1564 if (pnode->data->instance.instance_init)
1566 instance->g_class = pnode->data->instance.class;
1567 pnode->data->instance.instance_init (instance, class);
1570 if (node->data->instance.private_size)
1571 instance_real_class_remove (instance);
1573 instance->g_class = class;
1574 if (node->data->instance.instance_init)
1575 node->data->instance.instance_init (instance, class);
1581 g_type_free_instance (GTypeInstance *instance)
1586 g_return_if_fail (instance != NULL && instance->g_class != NULL);
1588 class = instance->g_class;
1589 node = lookup_type_node_I (class->g_type);
1590 if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
1592 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1593 type_descriptive_name_I (class->g_type));
1596 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1597 if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
1599 g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1604 instance->g_class = NULL;
1605 #ifdef G_ENABLE_DEBUG
1606 memset (instance, 0xaa, type_total_instance_size_I (node));
1608 g_slice_free1 (type_total_instance_size_I (node), instance);
1610 g_type_class_unref (class);
1614 type_iface_ensure_dflt_vtable_Wm (TypeNode *iface)
1616 g_assert (iface->data);
1618 if (!iface->data->iface.dflt_vtable)
1620 GTypeInterface *vtable = g_malloc0 (iface->data->iface.vtable_size);
1621 iface->data->iface.dflt_vtable = vtable;
1622 vtable->g_type = NODE_TYPE (iface);
1623 vtable->g_instance_type = 0;
1624 if (iface->data->iface.vtable_init_base ||
1625 iface->data->iface.dflt_init)
1627 G_WRITE_UNLOCK (&type_rw_lock);
1628 if (iface->data->iface.vtable_init_base)
1629 iface->data->iface.vtable_init_base (vtable);
1630 if (iface->data->iface.dflt_init)
1631 iface->data->iface.dflt_init (vtable, (gpointer) iface->data->iface.dflt_data);
1632 G_WRITE_LOCK (&type_rw_lock);
1638 /* This is called to allocate and do the first part of initializing
1639 * the interface vtable; type_iface_vtable_iface_init_Wm() does the remainder.
1641 * A FALSE return indicates that we didn't find an init function for
1642 * this type/iface pair, so the vtable from the parent type should
1643 * be used. Note that the write lock is not modified upon a FALSE
1647 type_iface_vtable_base_init_Wm (TypeNode *iface,
1651 IFaceHolder *iholder;
1652 GTypeInterface *vtable = NULL;
1655 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1656 iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), TRUE);
1658 return FALSE; /* we don't modify write lock upon FALSE */
1660 type_iface_ensure_dflt_vtable_Wm (iface);
1662 entry = type_lookup_iface_entry_L (node, iface);
1664 g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
1666 entry->init_state = IFACE_INIT;
1668 pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1669 if (pnode) /* want to copy over parent iface contents */
1671 IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
1674 vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
1677 vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
1678 entry->vtable = vtable;
1679 vtable->g_type = NODE_TYPE (iface);
1680 vtable->g_instance_type = NODE_TYPE (node);
1682 if (iface->data->iface.vtable_init_base)
1684 G_WRITE_UNLOCK (&type_rw_lock);
1685 iface->data->iface.vtable_init_base (vtable);
1686 G_WRITE_LOCK (&type_rw_lock);
1688 return TRUE; /* initialized the vtable */
1691 /* Finishes what type_iface_vtable_base_init_Wm started by
1692 * calling the interface init function.
1693 * this function may only be called for types with their
1694 * own interface holder info, i.e. types for which
1695 * g_type_add_interface*() was called and not children thereof.
1698 type_iface_vtable_iface_init_Wm (TypeNode *iface,
1701 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1702 IFaceHolder *iholder = type_iface_peek_holder_L (iface, NODE_TYPE (node));
1703 GTypeInterface *vtable = NULL;
1706 /* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */
1707 g_assert (iface->data && entry && iholder && iholder->info);
1708 g_assert (entry->init_state == IFACE_INIT); /* assert prior base_init() */
1710 entry->init_state = INITIALIZED;
1712 vtable = entry->vtable;
1714 if (iholder->info->interface_init)
1716 G_WRITE_UNLOCK (&type_rw_lock);
1717 if (iholder->info->interface_init)
1718 iholder->info->interface_init (vtable, iholder->info->interface_data);
1719 G_WRITE_LOCK (&type_rw_lock);
1722 for (i = 0; i < static_n_iface_check_funcs; i++)
1724 GTypeInterfaceCheckFunc check_func = static_iface_check_funcs[i].check_func;
1725 gpointer check_data = static_iface_check_funcs[i].check_data;
1727 G_WRITE_UNLOCK (&type_rw_lock);
1728 check_func (check_data, (gpointer)vtable);
1729 G_WRITE_LOCK (&type_rw_lock);
1734 type_iface_vtable_finalize_Wm (TypeNode *iface,
1736 GTypeInterface *vtable)
1738 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1739 IFaceHolder *iholder;
1741 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1742 iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), FALSE);
1744 return FALSE; /* we don't modify write lock upon FALSE */
1746 g_assert (entry && entry->vtable == vtable && iholder->info);
1748 entry->vtable = NULL;
1749 entry->init_state = UNINITIALIZED;
1750 if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
1752 G_WRITE_UNLOCK (&type_rw_lock);
1753 if (iholder->info->interface_finalize)
1754 iholder->info->interface_finalize (vtable, iholder->info->interface_data);
1755 if (iface->data->iface.vtable_finalize_base)
1756 iface->data->iface.vtable_finalize_base (vtable);
1757 G_WRITE_LOCK (&type_rw_lock);
1760 vtable->g_instance_type = 0;
1763 type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
1765 return TRUE; /* write lock modified */
1769 type_class_init_Wm (TypeNode *node,
1772 GSList *slist, *init_slist = NULL;
1775 TypeNode *bnode, *pnode;
1778 g_assert (node->is_classed && node->data &&
1779 node->data->class.class_size &&
1780 !node->data->class.class &&
1781 node->data->class.init_state == UNINITIALIZED);
1783 class = g_malloc0 (node->data->class.class_size);
1784 node->data->class.class = class;
1785 node->data->class.init_state = BASE_CLASS_INIT;
1789 TypeNode *pnode = lookup_type_node_I (pclass->g_type);
1791 memcpy (class, pclass, pnode->data->class.class_size);
1793 if (node->is_instantiatable)
1795 /* We need to initialize the private_size here rather than in
1796 * type_data_make_W() since the class init for the parent
1797 * class may have changed pnode->data->instance.private_size.
1799 node->data->instance.private_size = pnode->data->instance.private_size;
1802 class->g_type = NODE_TYPE (node);
1804 G_WRITE_UNLOCK (&type_rw_lock);
1806 /* stack all base class initialization functions, so we
1807 * call them in ascending order.
1809 for (bnode = node; bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
1810 if (bnode->data->class.class_init_base)
1811 init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
1812 for (slist = init_slist; slist; slist = slist->next)
1814 GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
1816 class_init_base (class);
1818 g_slist_free (init_slist);
1820 G_WRITE_LOCK (&type_rw_lock);
1822 node->data->class.init_state = BASE_IFACE_INIT;
1824 /* Before we initialize the class, base initialize all interfaces, either
1825 * from parent, or through our holder info
1827 pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1830 while (i < CLASSED_NODE_N_IFACES (node))
1832 entry = &CLASSED_NODE_IFACES_ENTRIES (node)[i];
1833 while (i < CLASSED_NODE_N_IFACES (node) &&
1834 entry->init_state == IFACE_INIT)
1840 if (i == CLASSED_NODE_N_IFACES (node))
1843 if (!type_iface_vtable_base_init_Wm (lookup_type_node_I (entry->iface_type), node))
1847 /* need to get this interface from parent, type_iface_vtable_base_init_Wm()
1848 * doesn't modify write lock upon FALSE, so entry is still valid;
1850 g_assert (pnode != NULL);
1852 for (j = 0; j < CLASSED_NODE_N_IFACES (pnode); j++)
1854 IFaceEntry *pentry = CLASSED_NODE_IFACES_ENTRIES (pnode) + j;
1856 if (pentry->iface_type == entry->iface_type)
1858 entry->vtable = pentry->vtable;
1859 entry->init_state = INITIALIZED;
1863 g_assert (entry->vtable != NULL);
1866 /* If the write lock was released, additional interface entries might
1867 * have been inserted into CLASSED_NODE_IFACES_ENTRIES (node); they'll
1868 * be base-initialized when inserted, so we don't have to worry that
1869 * we might miss them. Uninitialized entries can only be moved higher
1870 * when new ones are inserted.
1875 node->data->class.init_state = CLASS_INIT;
1877 G_WRITE_UNLOCK (&type_rw_lock);
1879 if (node->data->class.class_init)
1880 node->data->class.class_init (class, (gpointer) node->data->class.class_data);
1882 G_WRITE_LOCK (&type_rw_lock);
1884 node->data->class.init_state = IFACE_INIT;
1886 /* finish initializing the interfaces through our holder info.
1887 * inherited interfaces are already init_state == INITIALIZED, because
1888 * they either got setup in the above base_init loop, or during
1889 * class_init from within type_add_interface_Wm() for this or
1890 * an anchestor type.
1895 entry = &CLASSED_NODE_IFACES_ENTRIES (node)[i];
1896 while (i < CLASSED_NODE_N_IFACES (node) &&
1897 entry->init_state == INITIALIZED)
1903 if (i == CLASSED_NODE_N_IFACES (node))
1906 type_iface_vtable_iface_init_Wm (lookup_type_node_I (entry->iface_type), node);
1908 /* As in the loop above, additional initialized entries might be inserted
1909 * if the write lock is released, but that's harmless because the entries
1910 * we need to initialize only move higher in the list.
1915 node->data->class.init_state = INITIALIZED;
1919 type_data_finalize_class_ifaces_Wm (TypeNode *node)
1923 g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
1926 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1928 IFaceEntry *entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1931 if (type_iface_vtable_finalize_Wm (lookup_type_node_I (entry->iface_type), node, entry->vtable))
1933 /* refetch entries, IFACES_ENTRIES might be modified */
1938 /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
1939 * iface vtable came from parent
1941 entry->vtable = NULL;
1942 entry->init_state = UNINITIALIZED;
1949 type_data_finalize_class_U (TypeNode *node,
1952 GTypeClass *class = cdata->class;
1955 g_assert (cdata->class && cdata->common.ref_count == 0);
1957 if (cdata->class_finalize)
1958 cdata->class_finalize (class, (gpointer) cdata->class_data);
1960 /* call all base class destruction functions in descending order
1962 if (cdata->class_finalize_base)
1963 cdata->class_finalize_base (class);
1964 for (bnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
1965 if (bnode->data->class.class_finalize_base)
1966 bnode->data->class.class_finalize_base (class);
1968 g_free (cdata->class);
1972 type_data_last_unref_Wm (GType type,
1975 TypeNode *node = lookup_type_node_I (type);
1977 g_return_if_fail (node != NULL && node->plugin != NULL);
1979 if (!node->data || node->data->common.ref_count == 0)
1981 g_warning ("cannot drop last reference to unreferenced type `%s'",
1982 type_descriptive_name_I (type));
1986 /* call class cache hooks */
1987 if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs && !uncached)
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)
2022 /* destroy node->data->instance.mem_chunk */
2026 if (node->is_classed && tdata->class.class)
2028 if (CLASSED_NODE_N_IFACES (node))
2029 type_data_finalize_class_ifaces_Wm (node);
2030 node->mutatable_check_cache = FALSE;
2032 G_WRITE_UNLOCK (&type_rw_lock);
2033 type_data_finalize_class_U (node, &tdata->class);
2034 G_WRITE_LOCK (&type_rw_lock);
2036 else if (NODE_IS_IFACE (node) && tdata->iface.dflt_vtable)
2038 node->mutatable_check_cache = FALSE;
2040 if (tdata->iface.dflt_finalize || tdata->iface.vtable_finalize_base)
2042 G_WRITE_UNLOCK (&type_rw_lock);
2043 if (tdata->iface.dflt_finalize)
2044 tdata->iface.dflt_finalize (tdata->iface.dflt_vtable, (gpointer) tdata->iface.dflt_data);
2045 if (tdata->iface.vtable_finalize_base)
2046 tdata->iface.vtable_finalize_base (tdata->iface.dflt_vtable);
2047 G_WRITE_LOCK (&type_rw_lock);
2049 g_free (tdata->iface.dflt_vtable);
2053 node->mutatable_check_cache = FALSE;
2057 /* freeing tdata->common.value_table and its contents is taken care of
2058 * by allocating it in one chunk with tdata
2062 G_WRITE_UNLOCK (&type_rw_lock);
2063 g_type_plugin_unuse (node->plugin);
2064 G_WRITE_LOCK (&type_rw_lock);
2066 type_data_unref_WmREC (lookup_type_node_I (ptype), FALSE);
2071 g_type_add_class_cache_func (gpointer cache_data,
2072 GTypeClassCacheFunc cache_func)
2076 g_return_if_fail (cache_func != NULL);
2078 G_WRITE_LOCK (&type_rw_lock);
2079 i = static_n_class_cache_funcs++;
2080 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
2081 static_class_cache_funcs[i].cache_data = cache_data;
2082 static_class_cache_funcs[i].cache_func = cache_func;
2083 G_WRITE_UNLOCK (&type_rw_lock);
2087 g_type_remove_class_cache_func (gpointer cache_data,
2088 GTypeClassCacheFunc cache_func)
2090 gboolean found_it = FALSE;
2093 g_return_if_fail (cache_func != NULL);
2095 G_WRITE_LOCK (&type_rw_lock);
2096 for (i = 0; i < static_n_class_cache_funcs; i++)
2097 if (static_class_cache_funcs[i].cache_data == cache_data &&
2098 static_class_cache_funcs[i].cache_func == cache_func)
2100 static_n_class_cache_funcs--;
2101 g_memmove (static_class_cache_funcs + i,
2102 static_class_cache_funcs + i + 1,
2103 sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
2104 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
2108 G_WRITE_UNLOCK (&type_rw_lock);
2111 g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
2112 cache_func, cache_data);
2117 g_type_add_interface_check (gpointer check_data,
2118 GTypeInterfaceCheckFunc check_func)
2122 g_return_if_fail (check_func != NULL);
2124 G_WRITE_LOCK (&type_rw_lock);
2125 i = static_n_iface_check_funcs++;
2126 static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
2127 static_iface_check_funcs[i].check_data = check_data;
2128 static_iface_check_funcs[i].check_func = check_func;
2129 G_WRITE_UNLOCK (&type_rw_lock);
2133 g_type_remove_interface_check (gpointer check_data,
2134 GTypeInterfaceCheckFunc check_func)
2136 gboolean found_it = FALSE;
2139 g_return_if_fail (check_func != NULL);
2141 G_WRITE_LOCK (&type_rw_lock);
2142 for (i = 0; i < static_n_iface_check_funcs; i++)
2143 if (static_iface_check_funcs[i].check_data == check_data &&
2144 static_iface_check_funcs[i].check_func == check_func)
2146 static_n_iface_check_funcs--;
2147 g_memmove (static_iface_check_funcs + i,
2148 static_iface_check_funcs + i + 1,
2149 sizeof (static_iface_check_funcs[0]) * (static_n_iface_check_funcs - i));
2150 static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
2154 G_WRITE_UNLOCK (&type_rw_lock);
2157 g_warning (G_STRLOC ": cannot remove unregistered class check func %p with data %p",
2158 check_func, check_data);
2161 /* --- type registration --- */
2163 g_type_register_fundamental (GType type_id,
2164 const gchar *type_name,
2165 const GTypeInfo *info,
2166 const GTypeFundamentalInfo *finfo,
2171 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
2172 g_return_val_if_fail (type_id > 0, 0);
2173 g_return_val_if_fail (type_name != NULL, 0);
2174 g_return_val_if_fail (info != NULL, 0);
2175 g_return_val_if_fail (finfo != NULL, 0);
2177 if (!check_type_name_I (type_name))
2179 if ((type_id & TYPE_ID_MASK) ||
2180 type_id > G_TYPE_FUNDAMENTAL_MAX)
2182 g_warning ("attempt to register fundamental type `%s' with invalid type id (%zu)",
2187 if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
2188 !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
2190 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
2194 if (lookup_type_node_I (type_id))
2196 g_warning ("cannot register existing fundamental type `%s' (as `%s')",
2197 type_descriptive_name_I (type_id),
2202 G_WRITE_LOCK (&type_rw_lock);
2203 node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
2204 type_add_flags_W (node, flags);
2206 if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info))
2207 type_data_make_W (node, info,
2208 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
2209 G_WRITE_UNLOCK (&type_rw_lock);
2211 return NODE_TYPE (node);
2215 g_type_register_static_simple (GType parent_type,
2216 const gchar *type_name,
2218 GClassInitFunc class_init,
2219 guint instance_size,
2220 GInstanceInitFunc instance_init,
2225 info.class_size = class_size;
2226 info.base_init = NULL;
2227 info.base_finalize = NULL;
2228 info.class_init = class_init;
2229 info.class_finalize = NULL;
2230 info.class_data = NULL;
2231 info.instance_size = instance_size;
2232 info.n_preallocs = 0;
2233 info.instance_init = instance_init;
2234 info.value_table = NULL;
2236 return g_type_register_static (parent_type, type_name, &info, flags);
2240 g_type_register_static (GType parent_type,
2241 const gchar *type_name,
2242 const GTypeInfo *info,
2245 TypeNode *pnode, *node;
2248 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
2249 g_return_val_if_fail (parent_type > 0, 0);
2250 g_return_val_if_fail (type_name != NULL, 0);
2251 g_return_val_if_fail (info != NULL, 0);
2253 if (!check_type_name_I (type_name) ||
2254 !check_derivation_I (parent_type, type_name))
2256 if (info->class_finalize)
2258 g_warning ("class finalizer specified for static type `%s'",
2263 pnode = lookup_type_node_I (parent_type);
2264 G_WRITE_LOCK (&type_rw_lock);
2265 type_data_ref_Wm (pnode);
2266 if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info))
2268 node = type_node_new_W (pnode, type_name, NULL);
2269 type_add_flags_W (node, flags);
2270 type = NODE_TYPE (node);
2271 type_data_make_W (node, info,
2272 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
2274 G_WRITE_UNLOCK (&type_rw_lock);
2280 g_type_register_dynamic (GType parent_type,
2281 const gchar *type_name,
2282 GTypePlugin *plugin,
2285 TypeNode *pnode, *node;
2288 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0);
2289 g_return_val_if_fail (parent_type > 0, 0);
2290 g_return_val_if_fail (type_name != NULL, 0);
2291 g_return_val_if_fail (plugin != NULL, 0);
2293 if (!check_type_name_I (type_name) ||
2294 !check_derivation_I (parent_type, type_name) ||
2295 !check_plugin_U (plugin, TRUE, FALSE, type_name))
2298 G_WRITE_LOCK (&type_rw_lock);
2299 pnode = lookup_type_node_I (parent_type);
2300 node = type_node_new_W (pnode, type_name, plugin);
2301 type_add_flags_W (node, flags);
2302 type = NODE_TYPE (node);
2303 G_WRITE_UNLOCK (&type_rw_lock);
2309 g_type_add_interface_static (GType instance_type,
2310 GType interface_type,
2311 const GInterfaceInfo *info)
2313 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2314 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2315 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2317 /* we only need to lock class_init_rec_mutex if instance_type already has its
2318 * class initialized, however this function is rarely enough called to take
2319 * the simple route and always acquire class_init_rec_mutex.
2321 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2322 G_WRITE_LOCK (&type_rw_lock);
2323 if (check_add_interface_L (instance_type, interface_type))
2325 TypeNode *node = lookup_type_node_I (instance_type);
2326 TypeNode *iface = lookup_type_node_I (interface_type);
2327 if (check_interface_info_I (iface, NODE_TYPE (node), info))
2328 type_add_interface_Wm (node, iface, info, NULL);
2330 G_WRITE_UNLOCK (&type_rw_lock);
2331 g_static_rec_mutex_unlock (&class_init_rec_mutex);
2335 g_type_add_interface_dynamic (GType instance_type,
2336 GType interface_type,
2337 GTypePlugin *plugin)
2340 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2341 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2342 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2344 node = lookup_type_node_I (instance_type);
2345 if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
2348 /* see comment in g_type_add_interface_static() about class_init_rec_mutex */
2349 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2350 G_WRITE_LOCK (&type_rw_lock);
2351 if (check_add_interface_L (instance_type, interface_type))
2353 TypeNode *iface = lookup_type_node_I (interface_type);
2354 type_add_interface_Wm (node, iface, NULL, plugin);
2356 G_WRITE_UNLOCK (&type_rw_lock);
2357 g_static_rec_mutex_unlock (&class_init_rec_mutex);
2361 /* --- public API functions --- */
2363 g_type_class_ref (GType type)
2368 /* optimize for common code path */
2369 G_WRITE_LOCK (&type_rw_lock);
2370 node = lookup_type_node_I (type);
2371 if (node && node->is_classed && node->data &&
2372 node->data->class.class &&
2373 node->data->class.init_state == INITIALIZED)
2375 type_data_ref_Wm (node);
2376 G_WRITE_UNLOCK (&type_rw_lock);
2377 return node->data->class.class;
2379 if (!node || !node->is_classed ||
2380 (node->data && node->data->common.ref_count < 1))
2382 G_WRITE_UNLOCK (&type_rw_lock);
2383 g_warning ("cannot retrieve class for invalid (unclassed) type `%s'",
2384 type_descriptive_name_I (type));
2387 type_data_ref_Wm (node);
2388 ptype = NODE_PARENT_TYPE (node);
2389 G_WRITE_UNLOCK (&type_rw_lock);
2391 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2392 /* here, we either have node->data->class.class == NULL, or
2393 * node->data->class.init_state == INITIALIZED, because any
2394 * concurrently running initialization was guarded by class_init_rec_mutex.
2396 if (!node->data->class.class) /* class uninitialized */
2398 /* acquire reference on parent class */
2399 GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL;
2400 G_WRITE_LOCK (&type_rw_lock);
2401 if (node->data->class.class) /* class was initialized during parent class initialization? */
2402 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
2403 type_class_init_Wm (node, pclass);
2404 G_WRITE_UNLOCK (&type_rw_lock);
2406 g_static_rec_mutex_unlock (&class_init_rec_mutex);
2408 return node->data->class.class;
2412 g_type_class_unref (gpointer g_class)
2415 GTypeClass *class = g_class;
2417 g_return_if_fail (g_class != NULL);
2419 node = lookup_type_node_I (class->g_type);
2420 G_WRITE_LOCK (&type_rw_lock);
2421 if (node && node->is_classed && node->data &&
2422 node->data->class.class == class && node->data->common.ref_count > 0)
2423 type_data_unref_WmREC (node, FALSE);
2425 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2426 type_descriptive_name_I (class->g_type));
2427 G_WRITE_UNLOCK (&type_rw_lock);
2431 g_type_class_unref_uncached (gpointer g_class)
2434 GTypeClass *class = g_class;
2436 g_return_if_fail (g_class != NULL);
2438 G_WRITE_LOCK (&type_rw_lock);
2439 node = lookup_type_node_I (class->g_type);
2440 if (node && node->is_classed && node->data &&
2441 node->data->class.class == class && node->data->common.ref_count > 0)
2442 type_data_unref_WmREC (node, TRUE);
2444 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2445 type_descriptive_name_I (class->g_type));
2446 G_WRITE_UNLOCK (&type_rw_lock);
2450 g_type_class_peek (GType type)
2455 node = lookup_type_node_I (type);
2456 G_READ_LOCK (&type_rw_lock);
2457 if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
2458 class = node->data->class.class;
2461 G_READ_UNLOCK (&type_rw_lock);
2467 g_type_class_peek_static (GType type)
2472 node = lookup_type_node_I (type);
2473 G_READ_LOCK (&type_rw_lock);
2474 if (node && node->is_classed && node->data &&
2475 /* peek only static types: */ node->plugin == NULL &&
2476 node->data->class.class) /* common.ref_count _may_ be 0 */
2477 class = node->data->class.class;
2480 G_READ_UNLOCK (&type_rw_lock);
2486 g_type_class_peek_parent (gpointer g_class)
2489 gpointer class = NULL;
2491 g_return_val_if_fail (g_class != NULL, NULL);
2493 node = lookup_type_node_I (G_TYPE_FROM_CLASS (g_class));
2494 /* We used to acquire a read lock here. That is not necessary, since
2495 * parent->data->class.class is constant as long as the derived class
2498 if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
2500 node = lookup_type_node_I (NODE_PARENT_TYPE (node));
2501 class = node->data->class.class;
2503 else if (NODE_PARENT_TYPE (node))
2504 g_warning (G_STRLOC ": invalid class pointer `%p'", g_class);
2510 g_type_interface_peek (gpointer instance_class,
2515 gpointer vtable = NULL;
2516 GTypeClass *class = instance_class;
2518 g_return_val_if_fail (instance_class != NULL, NULL);
2520 node = lookup_type_node_I (class->g_type);
2521 iface = lookup_type_node_I (iface_type);
2522 if (node && node->is_instantiatable && iface)
2526 G_READ_LOCK (&type_rw_lock);
2528 entry = type_lookup_iface_entry_L (node, iface);
2529 if (entry && entry->vtable) /* entry is relocatable */
2530 vtable = entry->vtable;
2532 G_READ_UNLOCK (&type_rw_lock);
2535 g_warning (G_STRLOC ": invalid class pointer `%p'", class);
2541 g_type_interface_peek_parent (gpointer g_iface)
2545 gpointer vtable = NULL;
2546 GTypeInterface *iface_class = g_iface;
2548 g_return_val_if_fail (g_iface != NULL, NULL);
2550 iface = lookup_type_node_I (iface_class->g_type);
2551 node = lookup_type_node_I (iface_class->g_instance_type);
2553 node = lookup_type_node_I (NODE_PARENT_TYPE (node));
2554 if (node && node->is_instantiatable && iface)
2558 G_READ_LOCK (&type_rw_lock);
2560 entry = type_lookup_iface_entry_L (node, iface);
2561 if (entry && entry->vtable) /* entry is relocatable */
2562 vtable = entry->vtable;
2564 G_READ_UNLOCK (&type_rw_lock);
2567 g_warning (G_STRLOC ": invalid interface pointer `%p'", g_iface);
2573 g_type_default_interface_ref (GType g_type)
2576 gpointer dflt_vtable;
2578 G_WRITE_LOCK (&type_rw_lock);
2580 node = lookup_type_node_I (g_type);
2581 if (!node || !NODE_IS_IFACE (node) ||
2582 (node->data && node->data->common.ref_count < 1))
2584 G_WRITE_UNLOCK (&type_rw_lock);
2585 g_warning ("cannot retrieve default vtable for invalid or non-interface type '%s'",
2586 type_descriptive_name_I (g_type));
2590 if (!node->data || !node->data->iface.dflt_vtable)
2592 G_WRITE_UNLOCK (&type_rw_lock);
2593 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2594 G_WRITE_LOCK (&type_rw_lock);
2595 node = lookup_type_node_I (g_type);
2596 type_data_ref_Wm (node);
2597 type_iface_ensure_dflt_vtable_Wm (node);
2598 g_static_rec_mutex_unlock (&class_init_rec_mutex);
2601 type_data_ref_Wm (node); /* ref_count >= 1 already */
2603 dflt_vtable = node->data->iface.dflt_vtable;
2604 G_WRITE_UNLOCK (&type_rw_lock);
2610 g_type_default_interface_peek (GType g_type)
2615 node = lookup_type_node_I (g_type);
2616 G_READ_LOCK (&type_rw_lock);
2617 if (node && NODE_IS_IFACE (node) && node->data && node->data->iface.dflt_vtable)
2618 vtable = node->data->iface.dflt_vtable;
2621 G_READ_UNLOCK (&type_rw_lock);
2627 g_type_default_interface_unref (gpointer g_iface)
2630 GTypeInterface *vtable = g_iface;
2632 g_return_if_fail (g_iface != NULL);
2634 node = lookup_type_node_I (vtable->g_type);
2635 G_WRITE_LOCK (&type_rw_lock);
2636 if (node && NODE_IS_IFACE (node) &&
2637 node->data->iface.dflt_vtable == g_iface &&
2638 node->data->common.ref_count > 0)
2639 type_data_unref_WmREC (node, FALSE);
2641 g_warning ("cannot unreference invalid interface default vtable for '%s'",
2642 type_descriptive_name_I (vtable->g_type));
2643 G_WRITE_UNLOCK (&type_rw_lock);
2646 G_CONST_RETURN gchar*
2647 g_type_name (GType type)
2651 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, NULL);
2653 node = lookup_type_node_I (type);
2655 return node ? NODE_NAME (node) : NULL;
2659 g_type_qname (GType type)
2663 node = lookup_type_node_I (type);
2665 return node ? node->qname : 0;
2669 g_type_from_name (const gchar *name)
2674 g_return_val_if_fail (name != NULL, 0);
2676 quark = g_quark_try_string (name);
2679 G_READ_LOCK (&type_rw_lock);
2680 type = (GType) g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark));
2681 G_READ_UNLOCK (&type_rw_lock);
2688 g_type_parent (GType type)
2692 node = lookup_type_node_I (type);
2694 return node ? NODE_PARENT_TYPE (node) : 0;
2698 g_type_depth (GType type)
2702 node = lookup_type_node_I (type);
2704 return node ? node->n_supers + 1 : 0;
2708 g_type_next_base (GType type,
2714 node = lookup_type_node_I (type);
2717 TypeNode *base_node = lookup_type_node_I (base_type);
2719 if (base_node && base_node->n_supers < node->n_supers)
2721 guint n = node->n_supers - base_node->n_supers;
2723 if (node->supers[n] == base_type)
2724 atype = node->supers[n - 1];
2731 static inline gboolean
2732 type_node_check_conformities_UorL (TypeNode *node,
2733 TypeNode *iface_node,
2734 /* support_inheritance */
2735 gboolean support_interfaces,
2736 gboolean support_prerequisites,
2741 if (/* support_inheritance && */
2742 NODE_IS_ANCESTOR (iface_node, node))
2745 support_interfaces = support_interfaces && node->is_instantiatable && NODE_IS_IFACE (iface_node);
2746 support_prerequisites = support_prerequisites && NODE_IS_IFACE (node);
2748 if (support_interfaces || support_prerequisites)
2751 G_READ_LOCK (&type_rw_lock);
2752 if (support_interfaces && type_lookup_iface_entry_L (node, iface_node))
2754 else if (support_prerequisites && type_lookup_prerequisite_L (node, NODE_TYPE (iface_node)))
2757 G_READ_UNLOCK (&type_rw_lock);
2763 type_node_is_a_L (TypeNode *node,
2764 TypeNode *iface_node)
2766 return type_node_check_conformities_UorL (node, iface_node, TRUE, TRUE, TRUE);
2769 static inline gboolean
2770 type_node_conforms_to_U (TypeNode *node,
2771 TypeNode *iface_node,
2772 gboolean support_interfaces,
2773 gboolean support_prerequisites)
2775 return type_node_check_conformities_UorL (node, iface_node, support_interfaces, support_prerequisites, FALSE);
2779 g_type_is_a (GType type,
2782 TypeNode *node, *iface_node;
2785 node = lookup_type_node_I (type);
2786 iface_node = lookup_type_node_I (iface_type);
2787 is_a = node && iface_node && type_node_conforms_to_U (node, iface_node, TRUE, TRUE);
2792 GType* /* free result */
2793 g_type_children (GType type,
2798 node = lookup_type_node_I (type);
2803 G_READ_LOCK (&type_rw_lock); /* ->children is relocatable */
2804 children = g_new (GType, node->n_children + 1);
2805 memcpy (children, node->children, sizeof (GType) * node->n_children);
2806 children[node->n_children] = 0;
2809 *n_children = node->n_children;
2810 G_READ_UNLOCK (&type_rw_lock);
2823 GType* /* free result */
2824 g_type_interfaces (GType type,
2825 guint *n_interfaces)
2829 node = lookup_type_node_I (type);
2830 if (node && node->is_instantiatable)
2835 G_READ_LOCK (&type_rw_lock);
2836 ifaces = g_new (GType, CLASSED_NODE_N_IFACES (node) + 1);
2837 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
2838 ifaces[i] = CLASSED_NODE_IFACES_ENTRIES (node)[i].iface_type;
2842 *n_interfaces = CLASSED_NODE_N_IFACES (node);
2843 G_READ_UNLOCK (&type_rw_lock);
2856 typedef struct _QData QData;
2868 static inline gpointer
2869 type_get_qdata_L (TypeNode *node,
2872 GData *gdata = node->global_gdata;
2874 if (quark && gdata && gdata->n_qdatas)
2876 QData *qdatas = gdata->qdatas - 1;
2877 guint n_qdatas = gdata->n_qdatas;
2884 i = (n_qdatas + 1) / 2;
2886 if (quark == check->quark)
2888 else if (quark > check->quark)
2893 else /* if (quark < check->quark) */
2902 g_type_get_qdata (GType type,
2908 node = lookup_type_node_I (type);
2911 G_READ_LOCK (&type_rw_lock);
2912 data = type_get_qdata_L (node, quark);
2913 G_READ_UNLOCK (&type_rw_lock);
2917 g_return_val_if_fail (node != NULL, NULL);
2924 type_set_qdata_W (TypeNode *node,
2932 /* setup qdata list if necessary */
2933 if (!node->global_gdata)
2934 node->global_gdata = g_new0 (GData, 1);
2935 gdata = node->global_gdata;
2937 /* try resetting old data */
2938 qdata = gdata->qdatas;
2939 for (i = 0; i < gdata->n_qdatas; i++)
2940 if (qdata[i].quark == quark)
2942 qdata[i].data = data;
2948 gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
2949 qdata = gdata->qdatas;
2950 for (i = 0; i < gdata->n_qdatas - 1; i++)
2951 if (qdata[i].quark > quark)
2953 g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
2954 qdata[i].quark = quark;
2955 qdata[i].data = data;
2959 g_type_set_qdata (GType type,
2965 g_return_if_fail (quark != 0);
2967 node = lookup_type_node_I (type);
2970 G_WRITE_LOCK (&type_rw_lock);
2971 type_set_qdata_W (node, quark, data);
2972 G_WRITE_UNLOCK (&type_rw_lock);
2975 g_return_if_fail (node != NULL);
2979 type_add_flags_W (TypeNode *node,
2984 g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
2985 g_return_if_fail (node != NULL);
2987 if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class)
2988 g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
2989 dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
2991 type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
2995 g_type_query (GType type,
3000 g_return_if_fail (query != NULL);
3002 /* if node is not static and classed, we won't allow query */
3004 node = lookup_type_node_I (type);
3005 if (node && node->is_classed && !node->plugin)
3007 /* type is classed and probably even instantiatable */
3008 G_READ_LOCK (&type_rw_lock);
3009 if (node->data) /* type is static or referenced */
3011 query->type = NODE_TYPE (node);
3012 query->type_name = NODE_NAME (node);
3013 query->class_size = node->data->class.class_size;
3014 query->instance_size = node->is_instantiatable ? node->data->instance.instance_size : 0;
3016 G_READ_UNLOCK (&type_rw_lock);
3021 /* --- implementation details --- */
3023 g_type_test_flags (GType type,
3027 gboolean result = FALSE;
3029 node = lookup_type_node_I (type);
3032 guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
3033 guint tflags = flags & TYPE_FLAG_MASK;
3037 GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (node);
3039 fflags = (finfo->type_flags & fflags) == fflags;
3046 G_READ_LOCK (&type_rw_lock);
3047 tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
3048 G_READ_UNLOCK (&type_rw_lock);
3053 result = tflags && fflags;
3060 g_type_get_plugin (GType type)
3064 node = lookup_type_node_I (type);
3066 return node ? node->plugin : NULL;
3070 g_type_interface_get_plugin (GType instance_type,
3071 GType interface_type)
3076 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL); /* G_TYPE_IS_INTERFACE() is an external call: _U */
3078 node = lookup_type_node_I (instance_type);
3079 iface = lookup_type_node_I (interface_type);
3082 IFaceHolder *iholder;
3083 GTypePlugin *plugin;
3085 G_READ_LOCK (&type_rw_lock);
3087 iholder = iface_node_get_holders_L (iface);
3088 while (iholder && iholder->instance_type != instance_type)
3089 iholder = iholder->next;
3090 plugin = iholder ? iholder->plugin : NULL;
3092 G_READ_UNLOCK (&type_rw_lock);
3097 g_return_val_if_fail (node == NULL, NULL);
3098 g_return_val_if_fail (iface == NULL, NULL);
3100 g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
3106 g_type_fundamental_next (void)
3110 G_READ_LOCK (&type_rw_lock);
3111 type = static_fundamental_next;
3112 G_READ_UNLOCK (&type_rw_lock);
3113 type = G_TYPE_MAKE_FUNDAMENTAL (type);
3114 return type <= G_TYPE_FUNDAMENTAL_MAX ? type : 0;
3118 g_type_fundamental (GType type_id)
3120 TypeNode *node = lookup_type_node_I (type_id);
3122 return node ? NODE_FUNDAMENTAL_TYPE (node) : 0;
3126 g_type_check_instance_is_a (GTypeInstance *type_instance,
3129 TypeNode *node, *iface;
3132 if (!type_instance || !type_instance->g_class)
3135 node = lookup_type_node_I (type_instance->g_class->g_type);
3136 iface = lookup_type_node_I (iface_type);
3137 check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
3143 g_type_check_class_is_a (GTypeClass *type_class,
3146 TypeNode *node, *iface;
3152 node = lookup_type_node_I (type_class->g_type);
3153 iface = lookup_type_node_I (is_a_type);
3154 check = node && node->is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
3160 g_type_check_instance_cast (GTypeInstance *type_instance,
3165 if (type_instance->g_class)
3167 TypeNode *node, *iface;
3168 gboolean is_instantiatable, check;
3170 node = lookup_type_node_I (type_instance->g_class->g_type);
3171 is_instantiatable = node && node->is_instantiatable;
3172 iface = lookup_type_node_I (iface_type);
3173 check = is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
3175 return type_instance;
3177 if (is_instantiatable)
3178 g_warning ("invalid cast from `%s' to `%s'",
3179 type_descriptive_name_I (type_instance->g_class->g_type),
3180 type_descriptive_name_I (iface_type));
3182 g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
3183 type_descriptive_name_I (type_instance->g_class->g_type),
3184 type_descriptive_name_I (iface_type));
3187 g_warning ("invalid unclassed pointer in cast to `%s'",
3188 type_descriptive_name_I (iface_type));
3191 return type_instance;
3195 g_type_check_class_cast (GTypeClass *type_class,
3200 TypeNode *node, *iface;
3201 gboolean is_classed, check;
3203 node = lookup_type_node_I (type_class->g_type);
3204 is_classed = node && node->is_classed;
3205 iface = lookup_type_node_I (is_a_type);
3206 check = is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
3211 g_warning ("invalid class cast from `%s' to `%s'",
3212 type_descriptive_name_I (type_class->g_type),
3213 type_descriptive_name_I (is_a_type));
3215 g_warning ("invalid unclassed type `%s' in class cast to `%s'",
3216 type_descriptive_name_I (type_class->g_type),
3217 type_descriptive_name_I (is_a_type));
3220 g_warning ("invalid class cast from (NULL) pointer to `%s'",
3221 type_descriptive_name_I (is_a_type));
3226 g_type_check_instance (GTypeInstance *type_instance)
3228 /* this function is just here to make the signal system
3229 * conveniently elaborated on instance checks
3233 if (type_instance->g_class)
3235 TypeNode *node = lookup_type_node_I (type_instance->g_class->g_type);
3237 if (node && node->is_instantiatable)
3240 g_warning ("instance of invalid non-instantiatable type `%s'",
3241 type_descriptive_name_I (type_instance->g_class->g_type));
3244 g_warning ("instance with invalid (NULL) class pointer");
3247 g_warning ("invalid (NULL) pointer instance");
3252 static inline gboolean
3253 type_check_is_value_type_U (GType type)
3255 GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT;
3258 /* common path speed up */
3259 node = lookup_type_node_I (type);
3260 if (node && node->mutatable_check_cache)
3263 G_READ_LOCK (&type_rw_lock);
3267 if (node->data && node->data->common.ref_count > 0 &&
3268 node->data->common.value_table->value_init)
3269 tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
3270 else if (NODE_IS_IFACE (node))
3274 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
3276 GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
3277 TypeNode *prnode = lookup_type_node_I (prtype);
3279 if (prnode->is_instantiatable)
3282 node = lookup_type_node_I (type);
3288 G_READ_UNLOCK (&type_rw_lock);
3290 return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT);
3294 g_type_check_is_value_type (GType type)
3296 return type_check_is_value_type_U (type);
3300 g_type_check_value (GValue *value)
3302 return value && type_check_is_value_type_U (value->g_type);
3306 g_type_check_value_holds (GValue *value,
3309 return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type);
3313 g_type_value_table_peek (GType type)
3315 GTypeValueTable *vtable = NULL;
3316 TypeNode *node = lookup_type_node_I (type);
3317 gboolean has_refed_data, has_table;
3320 /* speed up common code path, we're not 100% safe here,
3321 * but we should only get called with referenced types anyway
3323 data = node ? node->data : NULL;
3324 if (node && node->mutatable_check_cache)
3325 return data->common.value_table;
3327 G_READ_LOCK (&type_rw_lock);
3330 has_refed_data = node && node->data && node->data->common.ref_count;
3331 has_table = has_refed_data && node->data->common.value_table->value_init;
3335 vtable = node->data->common.value_table;
3336 else if (NODE_IS_IFACE (node))
3340 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
3342 GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
3343 TypeNode *prnode = lookup_type_node_I (prtype);
3345 if (prnode->is_instantiatable)
3348 node = lookup_type_node_I (type);
3349 goto restart_table_peek;
3355 G_READ_UNLOCK (&type_rw_lock);
3361 g_warning (G_STRLOC ": type id `%zu' is invalid", type);
3362 if (!has_refed_data)
3363 g_warning ("can't peek value table for type `%s' which is not currently referenced",
3364 type_descriptive_name_I (type));
3369 G_CONST_RETURN gchar*
3370 g_type_name_from_instance (GTypeInstance *instance)
3373 return "<NULL-instance>";
3375 return g_type_name_from_class (instance->g_class);
3378 G_CONST_RETURN gchar*
3379 g_type_name_from_class (GTypeClass *g_class)
3382 return "<NULL-class>";
3384 return g_type_name (g_class->g_type);
3388 /* --- initialization --- */
3390 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
3392 G_LOCK_DEFINE_STATIC (type_init_lock);
3393 const gchar *env_string;
3396 volatile GType votype;
3398 G_LOCK (type_init_lock);
3400 G_WRITE_LOCK (&type_rw_lock);
3402 if (static_quark_type_flags)
3404 G_WRITE_UNLOCK (&type_rw_lock);
3405 G_UNLOCK (type_init_lock);
3409 /* setup GObject library wide debugging flags */
3410 _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
3411 env_string = g_getenv ("GOBJECT_DEBUG");
3412 if (env_string != NULL)
3414 static GDebugKey debug_keys[] = {
3415 { "objects", G_TYPE_DEBUG_OBJECTS },
3416 { "signals", G_TYPE_DEBUG_SIGNALS },
3419 _g_type_debug_flags |= g_parse_debug_string (env_string,
3421 sizeof (debug_keys) / sizeof (debug_keys[0]));
3426 static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
3427 static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
3428 static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
3430 /* type qname hash table */
3431 static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
3433 /* invalid type G_TYPE_INVALID (0)
3435 static_fundamental_type_nodes[0] = NULL;
3437 /* void type G_TYPE_NONE
3439 node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0);
3440 votype = NODE_TYPE (node);
3441 g_assert (votype == G_TYPE_NONE);
3443 /* interface fundamental type G_TYPE_INTERFACE (!classed)
3445 memset (&info, 0, sizeof (info));
3446 node = type_node_fundamental_new_W (G_TYPE_INTERFACE, g_intern_static_string ("GInterface"), G_TYPE_FLAG_DERIVABLE);
3447 votype = NODE_TYPE (node);
3448 type_data_make_W (node, &info, NULL);
3449 g_assert (votype == G_TYPE_INTERFACE);
3451 G_WRITE_UNLOCK (&type_rw_lock);
3455 /* G_TYPE_TYPE_PLUGIN
3457 votype = g_type_plugin_get_type ();
3459 /* G_TYPE_* value types
3461 g_value_types_init ();
3463 /* G_TYPE_ENUM & G_TYPE_FLAGS
3465 g_enum_types_init ();
3469 g_boxed_type_init ();
3473 g_param_type_init ();
3477 g_object_type_init ();
3479 /* G_TYPE_PARAM_* pspec types
3481 g_param_spec_types_init ();
3483 /* Value Transformations
3485 g_value_transforms_init ();
3491 G_UNLOCK (type_init_lock);
3497 g_type_init_with_debug_flags (0);
3501 g_type_class_add_private (gpointer g_class,
3504 GType instance_type = ((GTypeClass *)g_class)->g_type;
3505 TypeNode *node = lookup_type_node_I (instance_type);
3508 g_return_if_fail (private_size > 0);
3510 if (!node || !node->is_instantiatable || !node->data || node->data->class.class != g_class)
3512 g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'",
3513 type_descriptive_name_I (instance_type));
3517 if (NODE_PARENT_TYPE (node))
3519 TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
3520 if (node->data->instance.private_size != pnode->data->instance.private_size)
3522 g_warning ("g_type_add_private() called multiple times for the same type");
3527 G_WRITE_LOCK (&type_rw_lock);
3529 offset = ALIGN_STRUCT (node->data->instance.private_size);
3530 node->data->instance.private_size = offset + private_size;
3532 G_WRITE_UNLOCK (&type_rw_lock);
3536 g_type_instance_get_private (GTypeInstance *instance,
3539 TypeNode *instance_node;
3540 TypeNode *private_node;
3541 TypeNode *parent_node;
3545 g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
3547 /* while instances are initialized, their class pointers change,
3548 * so figure the instances real class first
3550 class = instance_real_class_get (instance);
3552 class = instance->g_class;
3554 instance_node = lookup_type_node_I (class->g_type);
3555 if (G_UNLIKELY (!instance_node || !instance_node->is_instantiatable))
3557 g_warning ("instance of invalid non-instantiatable type `%s'",
3558 type_descriptive_name_I (instance->g_class->g_type));
3562 private_node = lookup_type_node_I (private_type);
3563 if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, instance_node)))
3565 g_warning ("attempt to retrieve private data for invalid type '%s'",
3566 type_descriptive_name_I (private_type));
3570 /* Note that we don't need a read lock, since instance existing
3571 * means that the instance class and all parent classes
3572 * exist, so the node->data, node->data->instance.instance_size,
3573 * and node->data->instance.private_size are not going to be changed.
3574 * for any of the relevant types.
3577 offset = ALIGN_STRUCT (instance_node->data->instance.instance_size);
3579 if (NODE_PARENT_TYPE (private_node))
3581 parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
3582 g_assert (parent_node->data && parent_node->data->common.ref_count);
3584 if (G_UNLIKELY (private_node->data->instance.private_size == parent_node->data->instance.private_size))
3586 g_warning ("g_type_instance_get_private() requires a prior call to g_type_class_add_private()");
3590 offset += ALIGN_STRUCT (parent_node->data->instance.private_size);
3593 return G_STRUCT_MEMBER_P (instance, offset);
3596 #define __G_TYPE_C__
3597 #include "gobjectaliasdef.c"