1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 1998, 1999, 2000 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.
25 #include "gtypeplugin.h"
26 #include "gvaluecollector.h"
30 /* NOTE: some functions (some internal variants and exported ones)
31 * invalidate data portions of the TypeNodes. if external functions/callbacks
32 * are called, pointers to memory maintained by TypeNodes have to be looked up
33 * again. this affects most of the struct TypeNode fields, e.g. ->children or
34 * ->iface_entries (not ->supers[] as of recently), as all those memory portions can
35 * get realloc()ed during callback invocation.
38 * - g_type_from_name() should do an ordered array lookup after fetching the
39 * the quark, instead of a second hashtable lookup.
40 * - speedup checks for virtual types, steal a bit somewhere
43 * - force interface initialization for already existing classes
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 invokation
59 * - _Wm: [Write-locked invocation, mutatable]
60 * like _W, but the write lock might be released and reacquired
61 * during invocation, watch your pointers
64 static GStaticRWLock type_rw_lock = G_STATIC_RW_LOCK_INIT;
65 #define G_READ_LOCK(rw_lock) g_static_rw_lock_reader_lock (rw_lock)
66 #define G_READ_UNLOCK(rw_lock) g_static_rw_lock_reader_unlock (rw_lock)
67 #define G_WRITE_LOCK(rw_lock) g_static_rw_lock_writer_lock (rw_lock)
68 #define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
69 #define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
70 static const gchar *_action = " invalidly modified type "; \
71 gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
73 g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
75 g_error ("%s()%s`%s'", _fname, _action, _tname); \
78 #define DEBUG_CODE(debug_type, code_block) G_STMT_START { \
79 if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
82 #else /* !G_ENABLE_DEBUG */
83 #define DEBUG_CODE(debug_type, code_block) /* code_block */
84 #endif /* G_ENABLE_DEBUG */
86 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
87 G_TYPE_FLAG_INSTANTIATABLE | \
88 G_TYPE_FLAG_DERIVABLE | \
89 G_TYPE_FLAG_DEEP_DERIVABLE)
90 #define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT)
93 /* --- typedefs --- */
94 typedef struct _TypeNode TypeNode;
95 typedef struct _CommonData CommonData;
96 typedef struct _IFaceData IFaceData;
97 typedef struct _ClassData ClassData;
98 typedef struct _InstanceData InstanceData;
99 typedef union _TypeData TypeData;
100 typedef struct _IFaceEntry IFaceEntry;
101 typedef struct _IFaceHolder IFaceHolder;
104 /* --- prototypes --- */
105 static inline GTypeFundamentalInfo* type_node_fundamental_info_L (TypeNode *node);
106 static void type_add_flags_W (TypeNode *node,
108 static void type_data_make_W (TypeNode *node,
109 const GTypeInfo *info,
110 const GTypeValueTable *value_table);
111 static inline void type_data_ref_Wm (TypeNode *node);
112 static inline void type_data_unref_Wm (TypeNode *node,
114 static void type_data_last_unref_Wm (GType type,
118 /* --- structures --- */
119 struct _GValue /* kludge, keep in sync with gvalue.h */
126 guint n_children : 12;
129 guint is_classed : 1;
130 guint is_instantiatable : 1;
137 IFaceEntry *iface_entries;
138 IFaceHolder *iface_conformants;
140 GType supers[1]; /* flexible array */
142 #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
143 #define MAX_N_SUPERS (255)
144 #define MAX_N_CHILDREN (4095)
145 #define MAX_N_IFACES (511)
146 #define NODE_TYPE(node) (node->supers[0])
147 #define NODE_PARENT_TYPE(node) (node->supers[1])
148 #define NODE_NAME(node) ((gchar*)g_quark_to_string (node->qname))
153 GInterfaceInfo *info;
160 GTypeInterface *vtable;
165 GTypeValueTable *value_table;
171 GBaseInitFunc vtable_init_base;
172 GBaseFinalizeFunc vtable_finalize_base;
178 GBaseInitFunc class_init_base;
179 GBaseFinalizeFunc class_finalize_base;
180 GClassInitFunc class_init;
181 GClassFinalizeFunc class_finalize;
182 gconstpointer class_data;
189 GBaseInitFunc class_init_base;
190 GBaseFinalizeFunc class_finalize_base;
191 GClassInitFunc class_init;
192 GClassFinalizeFunc class_finalize;
193 gconstpointer class_data;
195 guint16 instance_size;
197 GInstanceInitFunc instance_init;
198 GMemChunk *mem_chunk;
205 InstanceData instance;
209 GTypeClassCacheFunc cache_func;
213 /* --- variables --- */
214 static guint static_n_class_cache_funcs = 0;
215 static ClassCacheFunc *static_class_cache_funcs = NULL;
216 static GType static_last_fundamental_id = 0;
217 static GQuark static_quark_type_flags = 0;
218 GTypeDebugFlags _g_type_debug_flags = 0;
221 /* --- externs --- */
222 const char *g_log_domain_gruntime = "GRuntime";
225 /* --- type nodes --- */
226 static GHashTable *static_type_nodes_ht = NULL;
227 static GType *static_branch_seqnos = NULL;
228 static TypeNode ***static_type_nodes = NULL;
230 static inline TypeNode*
231 lookup_type_node_L (register GType utype)
233 register GType ftype = G_TYPE_FUNDAMENTAL (utype);
234 register GType b_seqno = G_TYPE_BRANCH_SEQNO (utype);
236 if (ftype < static_last_fundamental_id && b_seqno < static_branch_seqnos[ftype])
237 return static_type_nodes[ftype][b_seqno];
243 type_node_any_new_W (TypeNode *pnode,
247 GTypeFundamentalFlags type_flags)
249 guint branch_last, n_supers;
252 guint i, node_size = 0;
254 n_supers = pnode ? pnode->n_supers + 1 : 0;
255 branch_last = static_branch_seqnos[ftype]++;
256 type = G_TYPE_DERIVE_ID (ftype, branch_last);
257 g_assert ((type & G_TYPE_FLAG_RESERVED_ID_BIT) == 0);
258 if (!branch_last || g_bit_storage (branch_last - 1) < g_bit_storage (static_branch_seqnos[ftype] - 1))
259 static_type_nodes[ftype] = g_renew (TypeNode*, static_type_nodes[ftype], 1 << g_bit_storage (static_branch_seqnos[ftype] - 1));
262 node_size += sizeof (GTypeFundamentalInfo); /* fundamental type info */
263 node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
264 node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + 0 for ->supers[] */
265 node = g_malloc0 (node_size);
266 if (!pnode) /* offset fundamental types */
267 node = G_STRUCT_MEMBER_P (node, sizeof (GTypeFundamentalInfo));
268 static_type_nodes[ftype][branch_last] = node;
270 node->n_supers = n_supers;
273 node->supers[0] = type;
276 node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
277 node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
278 node->is_iface = G_TYPE_IS_INTERFACE (type);
282 node->private.iface_conformants = NULL;
284 node->private.iface_entries = NULL;
288 node->supers[0] = type;
289 memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
291 node->is_classed = pnode->is_classed;
292 node->is_instantiatable = pnode->is_instantiatable;
293 node->is_iface = pnode->is_iface;
298 node->private.iface_conformants = NULL;
302 node->n_ifaces = pnode->n_ifaces;
303 node->private.iface_entries = g_memdup (pnode->private.iface_entries,
304 sizeof (pnode->private.iface_entries[0]) * node->n_ifaces);
307 i = pnode->n_children++;
308 pnode->children = g_renew (GType, pnode->children, pnode->n_children);
309 pnode->children[i] = type;
312 node->plugin = plugin;
313 node->n_children = 0;
314 node->children = NULL;
316 node->qname = g_quark_from_string (name);
317 node->global_gdata = NULL;
319 g_hash_table_insert (static_type_nodes_ht,
320 GUINT_TO_POINTER (node->qname),
321 GUINT_TO_POINTER (type));
325 static inline GTypeFundamentalInfo*
326 type_node_fundamental_info_L (TypeNode *node)
328 GType ftype = G_TYPE_FUNDAMENTAL (NODE_TYPE (node));
330 if (ftype != NODE_TYPE (node))
331 node = lookup_type_node_L (ftype);
333 return node ? G_STRUCT_MEMBER_P (node, - (gssize) sizeof (GTypeFundamentalInfo)) : NULL;
337 type_node_fundamental_new_W (GType ftype,
339 GTypeFundamentalFlags type_flags)
341 GTypeFundamentalInfo *finfo;
345 flast = static_last_fundamental_id;
347 g_assert (ftype == G_TYPE_FUNDAMENTAL (ftype));
349 type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
351 static_last_fundamental_id = MAX (static_last_fundamental_id, ftype + 1);
352 if (static_last_fundamental_id > flast)
354 static_type_nodes = g_renew (TypeNode**, static_type_nodes, static_last_fundamental_id);
355 static_branch_seqnos = g_renew (GType, static_branch_seqnos, static_last_fundamental_id);
356 for (i = flast; i < static_last_fundamental_id; i++)
358 static_type_nodes[i] = NULL;
359 static_branch_seqnos[i] = 0;
362 g_assert (static_branch_seqnos[ftype] == 0);
364 node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
366 finfo = type_node_fundamental_info_L (node);
367 finfo->type_flags = type_flags;
373 type_node_new_W (TypeNode *pnode,
379 g_assert (pnode->n_supers < MAX_N_SUPERS);
380 g_assert (pnode->n_children < MAX_N_CHILDREN);
382 return type_node_any_new_W (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (pnode)), name, plugin, 0);
385 static inline IFaceEntry*
386 type_lookup_iface_entry_L (TypeNode *node,
389 if (iface->is_iface && node->n_ifaces)
391 IFaceEntry *ifaces = node->private.iface_entries - 1;
392 guint n_ifaces = node->n_ifaces;
393 GType iface_type = NODE_TYPE (iface);
400 i = (n_ifaces + 1) / 2;
402 if (iface_type == check->iface_type)
404 else if (iface_type > check->iface_type)
409 else /* if (iface_type < check->iface_type) */
419 type_descriptive_name_L (GType type)
423 TypeNode *node = lookup_type_node_L (type);
425 return node ? NODE_NAME (node) : "<unknown>";
432 type_descriptive_name_U (GType type)
436 G_READ_LOCK (&type_rw_lock);
437 name = type_descriptive_name_L (type);
438 G_READ_UNLOCK (&type_rw_lock);
440 return (gchar *)name;
444 /* --- type consistency checks --- */
446 check_plugin_U (GTypePlugin *plugin,
447 gboolean need_complete_type_info,
448 gboolean need_complete_interface_info,
449 const gchar *type_name)
451 /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U
455 g_warning ("plugin handle for type `%s' is NULL",
459 if (!G_IS_TYPE_PLUGIN (plugin))
461 g_warning ("plugin pointer (%p) for type `%s' is invalid",
465 if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
467 g_warning ("plugin for type `%s' has no complete_type_info() implementation",
471 if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
473 g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
481 check_type_name_U (const gchar *type_name)
483 static const gchar *extra_chars = "-_+";
484 const gchar *p = type_name;
487 if (!type_name[0] || !type_name[1] || !type_name[2])
489 g_warning ("type name `%s' is too short", type_name);
492 /* check the first letter */
493 name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
494 for (p = type_name + 1; *p; p++)
495 name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
496 (p[0] >= 'a' && p[0] <= 'z') ||
497 (p[0] >= '0' && p[0] <= '9') ||
498 strchr (extra_chars, p[0]));
501 g_warning ("type name `%s' contains invalid characters", type_name);
504 if (g_type_from_name (type_name))
506 g_warning ("cannot register existing type `%s'", type_name);
514 check_derivation_U (GType parent_type,
515 const gchar *type_name)
518 GTypeFundamentalInfo* finfo;
520 G_READ_LOCK (&type_rw_lock);
521 pnode = lookup_type_node_L (parent_type);
524 G_READ_UNLOCK (&type_rw_lock);
525 g_warning ("cannot derive type `%s' from invalid parent type `%s'",
527 type_descriptive_name_U (parent_type));
530 finfo = type_node_fundamental_info_L (pnode);
531 /* ensure flat derivability */
532 if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
534 G_READ_UNLOCK (&type_rw_lock);
535 g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
540 /* ensure deep derivability */
541 if (parent_type != G_TYPE_FUNDAMENTAL (parent_type) &&
542 !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
544 G_READ_UNLOCK (&type_rw_lock);
545 g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
550 G_READ_UNLOCK (&type_rw_lock);
556 check_collect_format_I (const gchar *collect_format)
558 const gchar *p = collect_format;
559 gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
560 G_VALUE_COLLECT_DOUBLE, G_VALUE_COLLECT_POINTER,
564 if (!strchr (valid_format, *p++))
566 return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
570 check_value_table_I (const gchar *type_name,
571 const GTypeValueTable *value_table)
575 else if (value_table->value_init == NULL)
577 if (value_table->value_free || value_table->value_copy ||
578 value_table->value_peek_pointer ||
579 value_table->collect_format || value_table->collect_value ||
580 value_table->lcopy_format || value_table->lcopy_value)
581 g_warning ("cannot handle uninitializable values of type `%s'",
585 else /* value_table->value_init != NULL */
587 if (!value_table->value_free)
590 * g_warning ("missing `value_free()' for type `%s'", type_name);
594 if (!value_table->value_copy)
596 g_warning ("missing `value_copy()' for type `%s'", type_name);
599 if ((value_table->collect_format || value_table->collect_value) &&
600 (!value_table->collect_format || !value_table->collect_value))
602 g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
606 if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
608 g_warning ("the `%s' specification for type `%s' is too long or invalid",
613 if ((value_table->lcopy_format || value_table->lcopy_value) &&
614 (!value_table->lcopy_format || !value_table->lcopy_value))
616 g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
620 if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
622 g_warning ("the `%s' specification for type `%s' is too long or invalid",
632 check_type_info_L (TypeNode *pnode,
634 const gchar *type_name,
635 const GTypeInfo *info)
637 GTypeFundamentalInfo *finfo = type_node_fundamental_info_L (lookup_type_node_L (ftype));
638 gboolean is_interface = G_TYPE_IS_INTERFACE (ftype);
640 /* check instance members */
641 if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
642 (info->instance_size || info->n_preallocs || info->instance_init))
645 g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
649 g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
653 /* check class & interface members */
654 if (!(finfo->type_flags & G_TYPE_FLAG_CLASSED) &&
655 (info->class_init || info->class_finalize || info->class_data ||
656 (!is_interface && (info->class_size || info->base_init || info->base_finalize))))
659 g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
663 g_warning ("cannot create class for `%s' as non-classed fundamental",
667 /* check interface size */
668 if (is_interface && info->class_size < sizeof (GTypeInterface))
670 g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
674 /* check class size */
675 if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
677 if (info->class_size < sizeof (GTypeClass))
679 g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
683 if (pnode && info->class_size < pnode->data->class.class_size)
685 g_warning ("specified class size for type `%s' is smaller "
686 "than the parent type's `%s' class size",
692 /* check instance size */
693 if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
695 if (info->instance_size < sizeof (GTypeInstance))
697 g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
701 if (pnode && info->instance_size < pnode->data->instance.instance_size)
703 g_warning ("specified instance size for type `%s' is smaller "
704 "than the parent type's `%s' instance size",
715 find_conforming_type_L (TypeNode *pnode,
718 TypeNode *node = NULL;
721 if (type_lookup_iface_entry_L (pnode, iface))
724 for (i = 0; i < pnode->n_children && !node; i++)
725 node = find_conforming_type_L (lookup_type_node_L (pnode->children[i]), iface);
731 check_add_interface_L (GType instance_type,
734 TypeNode *node = lookup_type_node_L (instance_type);
735 TypeNode *iface = lookup_type_node_L (iface_type);
738 if (!node || !node->is_instantiatable)
740 g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
741 type_descriptive_name_L (instance_type));
744 if (!iface || !iface->is_iface)
746 g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
747 type_descriptive_name_L (iface_type),
751 tnode = lookup_type_node_L (NODE_PARENT_TYPE (iface));
752 if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
754 g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
760 tnode = find_conforming_type_L (node, iface);
763 g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
773 check_interface_info_L (TypeNode *iface,
775 const GInterfaceInfo *info)
777 if ((info->interface_finalize || info->interface_data) && !info->interface_init)
779 g_warning ("interface type `%s' for type `%s' comes without initializer",
781 type_descriptive_name_L (instance_type));
788 /* --- type info (type node data) --- */
790 type_data_make_W (TypeNode *node,
791 const GTypeInfo *info,
792 const GTypeValueTable *value_table)
795 GTypeValueTable *vtable = NULL;
796 guint vtable_size = 0;
798 g_assert (node->data == NULL && info != NULL);
802 TypeNode *pnode = lookup_type_node_L (NODE_PARENT_TYPE (node));
805 vtable = pnode->data->common.value_table;
808 static const GTypeValueTable zero_vtable = { NULL, };
810 value_table = &zero_vtable;
814 vtable_size = sizeof (GTypeValueTable);
816 if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
818 data = g_malloc0 (sizeof (InstanceData) + vtable_size);
820 vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
821 data->instance.class_size = info->class_size;
822 data->instance.class_init_base = info->base_init;
823 data->instance.class_finalize_base = info->base_finalize;
824 data->instance.class_init = info->class_init;
825 data->instance.class_finalize = info->class_finalize;
826 data->instance.class_data = info->class_data;
827 data->instance.class = NULL;
828 data->instance.instance_size = info->instance_size;
829 #ifdef DISABLE_MEM_POOLS
830 data->instance.n_preallocs = 0;
831 #else /* !DISABLE_MEM_POOLS */
832 data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
833 #endif /* !DISABLE_MEM_POOLS */
834 data->instance.instance_init = info->instance_init;
835 data->instance.mem_chunk = NULL;
837 else if (node->is_classed) /* only classed */
839 data = g_malloc0 (sizeof (ClassData) + vtable_size);
841 vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
842 data->class.class_size = info->class_size;
843 data->class.class_init_base = info->base_init;
844 data->class.class_finalize_base = info->base_finalize;
845 data->class.class_init = info->class_init;
846 data->class.class_finalize = info->class_finalize;
847 data->class.class_data = info->class_data;
848 data->class.class = NULL;
850 else if (node->is_iface)
852 data = g_malloc0 (sizeof (IFaceData) + vtable_size);
854 vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
855 data->iface.vtable_size = info->class_size;
856 data->iface.vtable_init_base = info->base_init;
857 data->iface.vtable_finalize_base = info->base_finalize;
861 data = g_malloc0 (sizeof (CommonData) + vtable_size);
863 vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
867 node->data->common.ref_count = 1;
871 *vtable = *value_table;
872 vtable->collect_format = g_strdup (value_table->collect_format ? value_table->collect_format : "");
873 vtable->lcopy_format = g_strdup (value_table->lcopy_format ? value_table->lcopy_format : "");
875 node->data->common.value_table = vtable;
877 g_assert (node->data->common.value_table != NULL); /* paranoid */
881 type_data_ref_Wm (TypeNode *node)
885 TypeNode *pnode = lookup_type_node_L (NODE_PARENT_TYPE (node));
887 GTypeValueTable tmp_value_table;
889 g_assert (node->plugin != NULL);
893 type_data_ref_Wm (pnode);
895 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
898 memset (&tmp_info, 0, sizeof (tmp_info));
899 memset (&tmp_value_table, 0, sizeof (tmp_value_table));
901 G_WRITE_UNLOCK (&type_rw_lock);
902 g_type_plugin_use (node->plugin);
903 g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
904 G_WRITE_LOCK (&type_rw_lock);
906 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
908 check_type_info_L (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmp_info);
909 type_data_make_W (node, &tmp_info,
910 check_value_table_I (NODE_NAME (node),
911 &tmp_value_table) ? &tmp_value_table : NULL);
915 g_assert (node->data->common.ref_count > 0);
917 node->data->common.ref_count += 1;
922 type_data_unref_Wm (TypeNode *node,
925 g_assert (node->data && node->data->common.ref_count);
927 if (node->data->common.ref_count > 1)
928 node->data->common.ref_count -= 1;
933 g_warning ("static type `%s' unreferenced too often",
938 type_data_last_unref_Wm (NODE_TYPE (node), uncached);
943 type_node_add_iface_entry_W (TypeNode *node,
949 g_assert (node->is_instantiatable && node->n_ifaces < MAX_N_IFACES);
952 node->private.iface_entries = g_renew (IFaceEntry, node->private.iface_entries, node->n_ifaces);
953 entries = node->private.iface_entries;
954 for (i = 0; i < node->n_ifaces - 1; i++)
955 if (entries[i].iface_type > iface_type)
957 g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (node->n_ifaces - i - 1));
958 entries[i].iface_type = iface_type;
959 entries[i].vtable = NULL;
961 for (i = 0; i < node->n_children; i++)
962 type_node_add_iface_entry_W (lookup_type_node_L (node->children[i]), iface_type);
966 type_add_interface_W (TypeNode *node,
968 const GInterfaceInfo *info,
971 IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
973 /* we must not call any functions of GInterfaceInfo from within here, since
974 * we got most probably called from _within_ a type registration function
976 g_assert (node->is_instantiatable && iface->is_iface && ((info && !plugin) || (!info && plugin)));
978 iholder->next = iface->private.iface_conformants;
979 iface->private.iface_conformants = iholder;
980 iholder->instance_type = NODE_TYPE (node);
981 iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
982 iholder->plugin = plugin;
984 type_node_add_iface_entry_W (node, NODE_TYPE (iface));
988 type_iface_retrive_holder_info_Wm (TypeNode *iface,
991 IFaceHolder *iholder = iface->private.iface_conformants;
993 g_assert (iface->is_iface);
995 while (iholder->instance_type != instance_type)
996 iholder = iholder->next;
1000 GInterfaceInfo tmp_info;
1002 g_assert (iholder->plugin != NULL);
1004 type_data_ref_Wm (iface);
1006 INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface));
1008 memset (&tmp_info, 0, sizeof (tmp_info));
1010 G_WRITE_UNLOCK (&type_rw_lock);
1011 g_type_plugin_use (iholder->plugin);
1012 g_type_plugin_complete_interface_info (iholder->plugin, NODE_TYPE (iface), instance_type, &tmp_info);
1013 G_WRITE_LOCK (&type_rw_lock);
1015 INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
1017 check_interface_info_L (iface, instance_type, &tmp_info);
1018 iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
1025 type_iface_blow_holder_info_Wm (TypeNode *iface,
1026 GType instance_type)
1028 IFaceHolder *iholder = iface->private.iface_conformants;
1030 g_assert (iface->is_iface);
1032 while (iholder->instance_type != instance_type)
1033 iholder = iholder->next;
1035 if (iholder->info && iholder->plugin)
1037 g_free (iholder->info);
1038 iholder->info = NULL;
1040 G_WRITE_UNLOCK (&type_rw_lock);
1041 g_type_plugin_unuse (iholder->plugin);
1042 G_WRITE_LOCK (&type_rw_lock);
1044 type_data_unref_Wm (iface, FALSE);
1049 /* --- type structure creation/destruction --- */
1051 g_type_create_instance (GType type)
1054 GTypeInstance *instance;
1058 G_READ_LOCK (&type_rw_lock);
1059 node = lookup_type_node_L (type);
1060 G_READ_UNLOCK (&type_rw_lock);
1061 if (!node || !node->is_instantiatable)
1063 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1064 type_descriptive_name_U (type));
1067 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1068 if (G_TYPE_IS_ABSTRACT (type))
1070 g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1071 type_descriptive_name_U (type));
1075 class = g_type_class_ref (type);
1077 if (node->data->instance.n_preallocs)
1079 G_WRITE_LOCK (&type_rw_lock);
1080 if (!node->data->instance.mem_chunk)
1081 node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
1082 node->data->instance.instance_size,
1083 (node->data->instance.instance_size *
1084 node->data->instance.n_preallocs),
1086 instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
1087 G_WRITE_UNLOCK (&type_rw_lock);
1090 instance = g_malloc0 (node->data->instance.instance_size); /* fine without read lock */
1091 for (i = node->n_supers; i > 0; i--)
1095 G_READ_LOCK (&type_rw_lock);
1096 pnode = lookup_type_node_L (node->supers[i]);
1097 G_READ_UNLOCK (&type_rw_lock);
1099 if (pnode->data->instance.instance_init)
1101 instance->g_class = pnode->data->instance.class;
1102 pnode->data->instance.instance_init (instance, class);
1105 instance->g_class = class;
1107 if (node->data->instance.instance_init)
1108 node->data->instance.instance_init (instance, class);
1114 g_type_free_instance (GTypeInstance *instance)
1119 g_return_if_fail (instance != NULL && instance->g_class != NULL);
1121 G_READ_LOCK (&type_rw_lock);
1122 class = instance->g_class;
1123 node = lookup_type_node_L (class->g_type);
1124 if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
1126 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1127 type_descriptive_name_L (class->g_type));
1128 G_READ_UNLOCK (&type_rw_lock);
1131 G_READ_UNLOCK (&type_rw_lock);
1132 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1133 if (G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
1135 g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1140 instance->g_class = NULL;
1141 memset (instance, 0xaa, node->data->instance.instance_size); // FIXME: debugging hack
1142 if (node->data->instance.n_preallocs)
1144 G_WRITE_LOCK (&type_rw_lock);
1145 g_chunk_free (instance, node->data->instance.mem_chunk);
1146 G_WRITE_UNLOCK (&type_rw_lock);
1151 g_type_class_unref (class);
1155 type_propagate_iface_vtable_W (TypeNode *pnode,
1157 GTypeInterface *vtable)
1159 IFaceEntry *entry = type_lookup_iface_entry_L (pnode, iface);
1162 entry->vtable = vtable;
1163 for (i = 0; i < pnode->n_children; i++)
1165 TypeNode *node = lookup_type_node_L (pnode->children[i]);
1167 type_propagate_iface_vtable_W (node, iface, vtable);
1172 type_iface_vtable_init_Wm (TypeNode *iface,
1175 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1176 IFaceHolder *iholder = type_iface_retrive_holder_info_Wm (iface, NODE_TYPE (node));
1177 GTypeInterface *vtable;
1179 g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
1181 vtable = g_malloc0 (iface->data->iface.vtable_size);
1182 type_propagate_iface_vtable_W (node, iface, vtable);
1183 vtable->g_type = NODE_TYPE (iface);
1184 vtable->g_instance_type = NODE_TYPE (node);
1186 if (iface->data->iface.vtable_init_base || iholder->info->interface_init)
1188 G_WRITE_UNLOCK (&type_rw_lock);
1189 if (iface->data->iface.vtable_init_base)
1190 iface->data->iface.vtable_init_base (vtable);
1191 if (iholder->info->interface_init)
1192 iholder->info->interface_init (vtable, iholder->info->interface_data);
1193 G_WRITE_LOCK (&type_rw_lock);
1198 type_iface_vtable_finalize_Wm (TypeNode *iface,
1200 GTypeInterface *vtable)
1202 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1203 IFaceHolder *iholder = iface->private.iface_conformants;
1205 g_assert (entry && entry->vtable == vtable);
1207 while (iholder->instance_type != NODE_TYPE (node))
1208 iholder = iholder->next;
1209 g_assert (iholder && iholder->info);
1211 type_propagate_iface_vtable_W (node, iface, NULL);
1212 if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
1214 G_WRITE_UNLOCK (&type_rw_lock);
1215 if (iholder->info->interface_finalize)
1216 iholder->info->interface_finalize (vtable, iholder->info->interface_data);
1217 if (iface->data->iface.vtable_finalize_base)
1218 iface->data->iface.vtable_finalize_base (vtable);
1219 G_WRITE_LOCK (&type_rw_lock);
1222 vtable->g_instance_type = 0;
1225 type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
1229 type_class_init_Wm (TypeNode *node,
1232 GSList *slist, *init_slist = NULL;
1238 g_assert (node->is_classed && node->data &&
1239 node->data->class.class_size &&
1240 !node->data->class.class);
1242 class = g_malloc0 (node->data->class.class_size);
1243 node->data->class.class = class;
1247 TypeNode *pnode = lookup_type_node_L (pclass->g_type);
1249 memcpy (class, pclass, pnode->data->class.class_size);
1251 class->g_type = NODE_TYPE (node);
1253 G_WRITE_UNLOCK (&type_rw_lock);
1255 /* stack all base class initialization functions, so we
1256 * call them in ascending order.
1258 G_READ_LOCK (&type_rw_lock);
1259 for (bnode = node; bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
1260 if (bnode->data->class.class_init_base)
1261 init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
1262 G_READ_UNLOCK (&type_rw_lock);
1263 for (slist = init_slist; slist; slist = slist->next)
1265 GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
1267 class_init_base (class);
1269 g_slist_free (init_slist);
1271 if (node->data->class.class_init)
1272 node->data->class.class_init (class, (gpointer) node->data->class.class_data);
1274 G_WRITE_LOCK (&type_rw_lock);
1276 /* ok, we got the class done, now initialize all interfaces */
1277 for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1278 if (!node->private.iface_entries[i].vtable)
1279 entry = node->private.iface_entries + i;
1282 type_iface_vtable_init_Wm (lookup_type_node_L (entry->iface_type), node);
1284 for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1285 if (!node->private.iface_entries[i].vtable)
1286 entry = node->private.iface_entries + i;
1291 type_data_finalize_class_ifaces_Wm (TypeNode *node)
1296 g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
1298 g_message ("finalizing interfaces for %sClass `%s'",
1299 type_descriptive_name_L (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1300 type_descriptive_name_L (NODE_TYPE (node)));
1302 for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1303 if (node->private.iface_entries[i].vtable &&
1304 node->private.iface_entries[i].vtable->g_instance_type == NODE_TYPE (node))
1305 entry = node->private.iface_entries + i;
1308 type_iface_vtable_finalize_Wm (lookup_type_node_L (entry->iface_type), node, entry->vtable);
1310 for (entry = NULL, i = 0; i < node->n_ifaces; i++)
1311 if (node->private.iface_entries[i].vtable &&
1312 node->private.iface_entries[i].vtable->g_instance_type == NODE_TYPE (node))
1313 entry = node->private.iface_entries + i;
1318 type_data_finalize_class_U (TypeNode *node,
1321 GTypeClass *class = cdata->class;
1324 g_assert (cdata->class && cdata->common.ref_count == 0);
1326 g_message ("finalizing %sClass `%s'",
1327 type_descriptive_name_U (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1328 type_descriptive_name_U (NODE_TYPE (node)));
1330 if (cdata->class_finalize)
1331 cdata->class_finalize (class, (gpointer) cdata->class_data);
1333 /* call all base class destruction functions in descending order
1335 if (cdata->class_finalize_base)
1336 cdata->class_finalize_base (class);
1337 G_READ_LOCK (&type_rw_lock);
1338 for (bnode = lookup_type_node_L (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
1339 if (bnode->data->class.class_finalize_base)
1341 G_READ_UNLOCK (&type_rw_lock);
1342 bnode->data->class.class_finalize_base (class);
1343 G_READ_LOCK (&type_rw_lock);
1345 G_READ_UNLOCK (&type_rw_lock);
1348 g_free (cdata->class);
1352 type_data_last_unref_Wm (GType type,
1355 TypeNode *node = lookup_type_node_L (type);
1357 g_return_if_fail (node != NULL && node->plugin != NULL);
1359 if (!node->data || node->data->common.ref_count == 0)
1361 g_warning ("cannot drop last reference to unreferenced type `%s'",
1362 type_descriptive_name_U (type));
1366 if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs)
1370 G_WRITE_UNLOCK (&type_rw_lock);
1371 G_READ_LOCK (&type_rw_lock);
1372 for (i = 0; i < static_n_class_cache_funcs; i++)
1374 GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func;
1375 gpointer cache_data = static_class_cache_funcs[i].cache_data;
1376 gboolean need_break;
1378 G_READ_UNLOCK (&type_rw_lock);
1379 need_break = cache_func (cache_data, node->data->class.class);
1380 G_READ_LOCK (&type_rw_lock);
1381 if (!node->data || node->data->common.ref_count == 0)
1382 INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
1386 G_READ_UNLOCK (&type_rw_lock);
1387 G_WRITE_LOCK (&type_rw_lock);
1390 if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */
1391 node->data->common.ref_count -= 1;
1394 GType ptype = NODE_PARENT_TYPE (node);
1397 node->data->common.ref_count = 0;
1399 if (node->is_instantiatable && node->data->instance.mem_chunk)
1401 g_mem_chunk_destroy (node->data->instance.mem_chunk);
1402 node->data->instance.mem_chunk = NULL;
1406 if (node->is_classed && tdata->class.class)
1409 type_data_finalize_class_ifaces_Wm (node);
1411 G_WRITE_UNLOCK (&type_rw_lock);
1412 type_data_finalize_class_U (node, &tdata->class);
1413 G_WRITE_LOCK (&type_rw_lock);
1418 if (tdata->common.value_table)
1420 g_free (tdata->common.value_table->collect_format);
1421 g_free (tdata->common.value_table->lcopy_format);
1426 type_data_unref_Wm (lookup_type_node_L (ptype), FALSE);
1427 G_WRITE_UNLOCK (&type_rw_lock);
1428 g_type_plugin_unuse (node->plugin);
1429 G_WRITE_LOCK (&type_rw_lock);
1434 g_type_add_class_cache_func (gpointer cache_data,
1435 GTypeClassCacheFunc cache_func)
1439 g_return_if_fail (cache_func != NULL);
1441 G_WRITE_LOCK (&type_rw_lock);
1442 i = static_n_class_cache_funcs++;
1443 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
1444 static_class_cache_funcs[i].cache_data = cache_data;
1445 static_class_cache_funcs[i].cache_func = cache_func;
1446 G_WRITE_UNLOCK (&type_rw_lock);
1450 g_type_remove_class_cache_func (gpointer cache_data,
1451 GTypeClassCacheFunc cache_func)
1453 gboolean found_it = FALSE;
1456 g_return_if_fail (cache_func != NULL);
1458 G_WRITE_LOCK (&type_rw_lock);
1459 for (i = 0; i < static_n_class_cache_funcs; i++)
1460 if (static_class_cache_funcs[i].cache_data == cache_data &&
1461 static_class_cache_funcs[i].cache_func == cache_func)
1463 static_n_class_cache_funcs--;
1464 g_memmove (static_class_cache_funcs + i,
1465 static_class_cache_funcs + i + 1,
1466 sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
1467 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
1471 G_WRITE_UNLOCK (&type_rw_lock);
1474 g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
1475 cache_func, cache_data);
1479 /* --- type registration --- */
1481 g_type_register_fundamental (GType type_id,
1482 const gchar *type_name,
1483 const GTypeInfo *info,
1484 const GTypeFundamentalInfo *finfo,
1487 GTypeFundamentalInfo *node_finfo;
1490 g_return_val_if_fail (type_id > 0, 0);
1491 g_return_val_if_fail (type_name != NULL, 0);
1492 g_return_val_if_fail (info != NULL, 0);
1493 g_return_val_if_fail (finfo != NULL, 0);
1495 if (!check_type_name_U (type_name))
1497 if (G_TYPE_FUNDAMENTAL (type_id) != type_id)
1499 g_warning ("cannot register fundamental type `%s' with non-fundamental id (%u)",
1504 if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
1505 !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
1507 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1511 G_WRITE_LOCK (&type_rw_lock);
1512 if (lookup_type_node_L (type_id))
1514 G_WRITE_UNLOCK (&type_rw_lock);
1515 g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1516 type_descriptive_name_U (type_id),
1521 node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
1522 node_finfo = type_node_fundamental_info_L (node);
1523 type_add_flags_W (node, flags);
1525 if (check_type_info_L (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
1526 type_data_make_W (node, info,
1527 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
1528 G_WRITE_UNLOCK (&type_rw_lock);
1530 return NODE_TYPE (node);
1534 g_type_register_static (GType parent_type,
1535 const gchar *type_name,
1536 const GTypeInfo *info,
1539 TypeNode *pnode, *node;
1542 g_return_val_if_fail (parent_type > 0, 0);
1543 g_return_val_if_fail (type_name != NULL, 0);
1544 g_return_val_if_fail (info != NULL, 0);
1546 if (!check_type_name_U (type_name) ||
1547 !check_derivation_U (parent_type, type_name))
1549 if (info->class_finalize)
1551 g_warning ("class finalizer specified for static type `%s'",
1556 G_WRITE_LOCK (&type_rw_lock);
1557 pnode = lookup_type_node_L (parent_type);
1558 type_data_ref_Wm (pnode);
1559 if (check_type_info_L (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
1561 node = type_node_new_W (pnode, type_name, NULL);
1562 type_add_flags_W (node, flags);
1563 type = NODE_TYPE (node);
1564 type_data_make_W (node, info,
1565 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
1567 G_WRITE_UNLOCK (&type_rw_lock);
1573 g_type_register_dynamic (GType parent_type,
1574 const gchar *type_name,
1575 GTypePlugin *plugin,
1578 TypeNode *pnode, *node;
1581 g_return_val_if_fail (parent_type > 0, 0);
1582 g_return_val_if_fail (type_name != NULL, 0);
1583 g_return_val_if_fail (plugin != NULL, 0);
1585 if (!check_type_name_U (type_name) ||
1586 !check_derivation_U (parent_type, type_name) ||
1587 !check_plugin_U (plugin, TRUE, FALSE, type_name))
1590 G_WRITE_LOCK (&type_rw_lock);
1591 pnode = lookup_type_node_L (parent_type);
1592 node = type_node_new_W (pnode, type_name, plugin);
1593 type_add_flags_W (node, flags);
1594 type = NODE_TYPE (node);
1595 G_WRITE_UNLOCK (&type_rw_lock);
1601 g_type_add_interface_static (GType instance_type,
1602 GType interface_type,
1603 const GInterfaceInfo *info)
1605 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1606 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1607 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1609 G_WRITE_LOCK (&type_rw_lock);
1610 if (check_add_interface_L (instance_type, interface_type))
1612 TypeNode *node = lookup_type_node_L (instance_type);
1613 TypeNode *iface = lookup_type_node_L (interface_type);
1615 if (check_interface_info_L (iface, NODE_TYPE (node), info))
1616 type_add_interface_W (node, iface, info, NULL);
1618 G_WRITE_UNLOCK (&type_rw_lock);
1622 g_type_add_interface_dynamic (GType instance_type,
1623 GType interface_type,
1624 GTypePlugin *plugin)
1628 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1629 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1630 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1632 G_READ_LOCK (&type_rw_lock);
1633 node = lookup_type_node_L (instance_type);
1634 G_READ_UNLOCK (&type_rw_lock);
1635 if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
1638 G_WRITE_LOCK (&type_rw_lock);
1639 if (check_add_interface_L (instance_type, interface_type))
1641 TypeNode *iface = lookup_type_node_L (interface_type);
1643 type_add_interface_W (node, iface, NULL, plugin);
1645 G_WRITE_UNLOCK (&type_rw_lock);
1649 /* --- public API functions --- */
1651 g_type_class_ref (GType type)
1655 /* optimize for common code path
1657 G_WRITE_LOCK (&type_rw_lock);
1658 node = lookup_type_node_L (type);
1659 if (node && node->is_classed && node->data &&
1660 node->data->class.class && node->data->common.ref_count > 0)
1662 type_data_ref_Wm (node);
1663 G_WRITE_UNLOCK (&type_rw_lock);
1665 return node->data->class.class;
1668 if (!node || !node->is_classed ||
1669 (node->data && node->data->common.ref_count < 1))
1671 G_WRITE_UNLOCK (&type_rw_lock);
1672 g_warning ("cannot retrive class for invalid (unclassed) type `%s'",
1673 type_descriptive_name_U (type));
1677 type_data_ref_Wm (node);
1679 if (!node->data->class.class)
1681 GType ptype = NODE_PARENT_TYPE (node);
1682 GTypeClass *pclass = NULL;
1686 G_WRITE_UNLOCK (&type_rw_lock);
1687 pclass = g_type_class_ref (ptype);
1688 if (node->data->class.class)
1689 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1690 G_WRITE_LOCK (&type_rw_lock);
1693 type_class_init_Wm (node, pclass);
1695 G_WRITE_UNLOCK (&type_rw_lock);
1697 return node->data->class.class;
1701 g_type_class_unref (gpointer g_class)
1704 GTypeClass *class = g_class;
1706 g_return_if_fail (g_class != NULL);
1708 G_WRITE_LOCK (&type_rw_lock);
1709 node = lookup_type_node_L (class->g_type);
1710 if (node && node->is_classed && node->data &&
1711 node->data->class.class == class && node->data->common.ref_count > 0)
1712 type_data_unref_Wm (node, FALSE);
1714 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1715 type_descriptive_name_L (class->g_type));
1716 G_WRITE_UNLOCK (&type_rw_lock);
1720 g_type_class_unref_uncached (gpointer g_class)
1723 GTypeClass *class = g_class;
1725 g_return_if_fail (g_class != NULL);
1727 G_WRITE_LOCK (&type_rw_lock);
1728 node = lookup_type_node_L (class->g_type);
1729 if (node && node->is_classed && node->data &&
1730 node->data->class.class == class && node->data->common.ref_count > 0)
1731 type_data_unref_Wm (node, TRUE);
1733 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1734 type_descriptive_name_L (class->g_type));
1735 G_WRITE_UNLOCK (&type_rw_lock);
1739 g_type_class_peek (GType type)
1744 G_READ_LOCK (&type_rw_lock);
1745 node = lookup_type_node_L (type);
1746 if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
1747 class = node->data->class.class;
1750 G_READ_UNLOCK (&type_rw_lock);
1756 g_type_class_peek_parent (gpointer g_class)
1761 g_return_val_if_fail (g_class != NULL, NULL);
1763 G_READ_LOCK (&type_rw_lock);
1764 node = lookup_type_node_L (G_TYPE_FROM_CLASS (g_class));
1765 if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
1767 node = lookup_type_node_L (NODE_PARENT_TYPE (node));
1768 class = node->data->class.class;
1772 G_READ_UNLOCK (&type_rw_lock);
1778 g_type_interface_peek (gpointer instance_class,
1783 gpointer vtable = NULL;
1784 GTypeClass *class = instance_class;
1786 g_return_val_if_fail (instance_class != NULL, NULL);
1788 G_READ_LOCK (&type_rw_lock);
1789 node = lookup_type_node_L (class->g_type);
1790 iface = lookup_type_node_L (iface_type);
1791 if (node && node->is_instantiatable && iface)
1793 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1795 if (entry && entry->vtable)
1796 vtable = entry->vtable;
1798 G_READ_UNLOCK (&type_rw_lock);
1804 g_type_value_table_peek (GType type)
1807 GTypeValueTable *vtable = NULL;
1809 G_READ_LOCK (&type_rw_lock);
1810 node = lookup_type_node_L (type);
1811 if (node && node->data && node->data->common.ref_count > 0 &&
1812 node->data->common.value_table->value_init)
1813 vtable = node->data->common.value_table;
1814 G_READ_UNLOCK (&type_rw_lock);
1819 G_CONST_RETURN gchar*
1820 g_type_name (GType type)
1824 G_READ_LOCK (&type_rw_lock);
1825 node = lookup_type_node_L (type);
1826 G_READ_UNLOCK (&type_rw_lock);
1828 return node ? NODE_NAME (node) : NULL;
1832 g_type_qname (GType type)
1836 G_READ_LOCK (&type_rw_lock);
1837 node = lookup_type_node_L (type);
1838 G_READ_UNLOCK (&type_rw_lock);
1840 return node ? node->qname : 0;
1844 g_type_from_name (const gchar *name)
1849 g_return_val_if_fail (name != NULL, 0);
1851 quark = g_quark_try_string (name);
1854 G_READ_LOCK (&type_rw_lock);
1855 type = GPOINTER_TO_UINT (g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark)));
1856 G_READ_UNLOCK (&type_rw_lock);
1863 g_type_parent (GType type)
1867 G_READ_LOCK (&type_rw_lock);
1868 node = lookup_type_node_L (type);
1869 G_READ_UNLOCK (&type_rw_lock);
1871 return node ? NODE_PARENT_TYPE (node) : 0;
1875 g_type_next_base (GType type,
1881 G_READ_LOCK (&type_rw_lock);
1882 node = lookup_type_node_L (type);
1885 TypeNode *base_node = lookup_type_node_L (base_type);
1887 if (base_node && base_node->n_supers < node->n_supers)
1889 guint n = node->n_supers - base_node->n_supers;
1891 if (node->supers[n] == base_type)
1892 atype = node->supers[n - 1];
1895 G_READ_UNLOCK (&type_rw_lock);
1901 g_type_is_a (GType type,
1904 gboolean is_a = FALSE;
1906 G_READ_LOCK (&type_rw_lock);
1907 if (type != iface_type)
1909 TypeNode *node = lookup_type_node_L (type);
1913 TypeNode *iface_node = lookup_type_node_L (iface_type);
1917 if (iface_node->is_iface && node->is_instantiatable)
1918 is_a = type_lookup_iface_entry_L (node, iface_node) != NULL;
1919 else if (iface_node->n_supers <= node->n_supers)
1920 is_a = node->supers[node->n_supers - iface_node->n_supers] == iface_type;
1925 is_a = lookup_type_node_L (type) != NULL;
1926 G_READ_UNLOCK (&type_rw_lock);
1932 g_type_fundamental_branch_last (GType type)
1934 GType ftype = G_TYPE_FUNDAMENTAL (type);
1937 G_READ_LOCK (&type_rw_lock);
1938 last_type = ftype < static_last_fundamental_id ? static_branch_seqnos[ftype] : 0;
1939 G_READ_UNLOCK (&type_rw_lock);
1944 GType* /* free result */
1945 g_type_children (GType type,
1950 G_READ_LOCK (&type_rw_lock);
1951 node = lookup_type_node_L (type);
1954 GType *children = g_new (GType, node->n_children + 1);
1956 memcpy (children, node->children, sizeof (GType) * node->n_children);
1957 children[node->n_children] = 0;
1960 *n_children = node->n_children;
1961 G_READ_UNLOCK (&type_rw_lock);
1967 G_READ_UNLOCK (&type_rw_lock);
1975 GType* /* free result */
1976 g_type_interfaces (GType type,
1977 guint *n_interfaces)
1981 G_READ_LOCK (&type_rw_lock);
1982 node = lookup_type_node_L (type);
1983 if (node && node->is_instantiatable)
1985 GType *ifaces = g_new (GType, node->n_ifaces + 1);
1988 for (i = 0; i < node->n_ifaces; i++)
1989 ifaces[i] = node->private.iface_entries[i].iface_type;
1993 *n_interfaces = node->n_ifaces;
1994 G_READ_UNLOCK (&type_rw_lock);
2000 G_READ_UNLOCK (&type_rw_lock);
2008 typedef struct _QData QData;
2020 static inline gpointer
2021 type_get_qdata_L (TypeNode *node,
2024 GData *gdata = node->global_gdata;
2026 if (quark && gdata && gdata->n_qdatas)
2028 QData *qdatas = gdata->qdatas - 1;
2029 guint n_qdatas = gdata->n_qdatas;
2036 i = (n_qdatas + 1) / 2;
2038 if (quark == check->quark)
2040 else if (quark > check->quark)
2045 else /* if (quark < check->quark) */
2054 g_type_get_qdata (GType type,
2060 G_READ_LOCK (&type_rw_lock);
2061 node = lookup_type_node_L (type);
2064 data = type_get_qdata_L (node, quark);
2065 G_READ_UNLOCK (&type_rw_lock);
2069 G_READ_UNLOCK (&type_rw_lock);
2070 g_return_val_if_fail (node != NULL, NULL);
2077 type_set_qdata_W (TypeNode *node,
2085 /* setup qdata list if necessary */
2086 if (!node->global_gdata)
2087 node->global_gdata = g_new0 (GData, 1);
2088 gdata = node->global_gdata;
2090 /* try resetting old data */
2091 qdata = gdata->qdatas;
2092 for (i = 0; i < gdata->n_qdatas; i++)
2093 if (qdata[i].quark == quark)
2095 qdata[i].data = data;
2101 gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
2102 qdata = gdata->qdatas;
2103 for (i = 0; i < gdata->n_qdatas - 1; i++)
2104 if (qdata[i].quark > quark)
2106 g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
2107 qdata[i].quark = quark;
2108 qdata[i].data = data;
2112 g_type_set_qdata (GType type,
2118 g_return_if_fail (quark != 0);
2120 G_WRITE_LOCK (&type_rw_lock);
2121 node = lookup_type_node_L (type);
2124 type_set_qdata_W (node, quark, data);
2125 G_WRITE_UNLOCK (&type_rw_lock);
2129 G_WRITE_UNLOCK (&type_rw_lock);
2130 g_return_if_fail (node != NULL);
2135 type_add_flags_W (TypeNode *node,
2140 g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
2141 g_return_if_fail (node != NULL);
2143 if ((flags & G_TYPE_FLAG_ABSTRACT) && node->is_classed && node->data && node->data->class.class)
2144 g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
2145 dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
2147 type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
2151 /* --- implementation details --- */
2153 g_type_check_flags (GType type,
2157 gboolean result = FALSE;
2159 G_READ_LOCK (&type_rw_lock);
2160 node = lookup_type_node_L (type);
2163 guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
2164 guint tflags = flags & TYPE_FLAG_MASK;
2168 GTypeFundamentalInfo *finfo = type_node_fundamental_info_L (node);
2170 fflags = (finfo->type_flags & fflags) == fflags;
2176 tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
2180 result = tflags && fflags;
2182 G_READ_UNLOCK (&type_rw_lock);
2188 g_type_get_plugin (GType type)
2192 G_READ_LOCK (&type_rw_lock);
2193 node = lookup_type_node_L (type);
2194 G_READ_UNLOCK (&type_rw_lock);
2196 return node ? node->plugin : NULL;
2200 g_type_interface_get_plugin (GType instance_type,
2201 GType interface_type)
2206 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
2208 G_READ_LOCK (&type_rw_lock);
2209 node = lookup_type_node_L (instance_type);
2210 iface = lookup_type_node_L (interface_type);
2213 IFaceHolder *iholder = iface->private.iface_conformants;
2215 while (iholder && iholder->instance_type != instance_type)
2216 iholder = iholder->next;
2217 G_READ_UNLOCK (&type_rw_lock);
2220 return iholder->plugin;
2223 G_READ_UNLOCK (&type_rw_lock);
2225 g_return_val_if_fail (node == NULL, NULL);
2226 g_return_val_if_fail (iface == NULL, NULL);
2228 g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
2234 g_type_fundamental_last (void)
2238 G_READ_LOCK (&type_rw_lock);
2239 type = static_last_fundamental_id;
2240 G_READ_UNLOCK (&type_rw_lock);
2246 g_type_instance_is_a (GTypeInstance *type_instance,
2249 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2250 return (type_instance && type_instance->g_class &&
2251 G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type) &&
2252 g_type_is_a (type_instance->g_class->g_type, iface_type));
2256 g_type_class_is_a (GTypeClass *type_class,
2259 /* G_TYPE_IS_CLASSED() is an external call: _U */
2260 return (type_class && G_TYPE_IS_CLASSED (type_class->g_type) &&
2261 g_type_is_a (type_class->g_type, is_a_type));
2265 g_type_value_is_a (GValue *value,
2273 G_READ_LOCK (&type_rw_lock);
2274 node = lookup_type_node_L (value->g_type);
2276 if (!G_TYPE_IS_FUNDAMENTAL (value->g_type) && !node || !node->data)
2277 node = lookup_type_node_L (G_TYPE_FUNDAMENTAL (value->g_type));
2279 if (!node || !node->data || node->data->common.ref_count < 1 ||
2280 !node->data->common.value_table->value_init)
2282 G_READ_UNLOCK (&type_rw_lock);
2286 G_READ_UNLOCK (&type_rw_lock);
2288 return g_type_is_a (value->g_type, type);
2292 g_type_check_value (GValue *value)
2294 return value && g_type_value_is_a (value, value->g_type);
2298 g_type_check_instance_cast (GTypeInstance *type_instance,
2303 g_warning ("invalid cast from (NULL) pointer to `%s'",
2304 type_descriptive_name_U (iface_type));
2305 return type_instance;
2307 if (!type_instance->g_class)
2309 g_warning ("invalid unclassed pointer in cast to `%s'",
2310 type_descriptive_name_U (iface_type));
2311 return type_instance;
2313 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2314 if (!G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type))
2316 g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
2317 type_descriptive_name_U (type_instance->g_class->g_type),
2318 type_descriptive_name_U (iface_type));
2319 return type_instance;
2321 if (!g_type_is_a (type_instance->g_class->g_type, iface_type))
2323 g_warning ("invalid cast from `%s' to `%s'",
2324 type_descriptive_name_U (type_instance->g_class->g_type),
2325 type_descriptive_name_U (iface_type));
2326 return type_instance;
2329 return type_instance;
2333 g_type_check_class_cast (GTypeClass *type_class,
2338 g_warning ("invalid class cast from (NULL) pointer to `%s'",
2339 type_descriptive_name_U (is_a_type));
2342 /* G_TYPE_IS_CLASSED() is an external call: _U */
2343 if (!G_TYPE_IS_CLASSED (type_class->g_type))
2345 g_warning ("invalid unclassed type `%s' in class cast to `%s'",
2346 type_descriptive_name_U (type_class->g_type),
2347 type_descriptive_name_U (is_a_type));
2350 if (!g_type_is_a (type_class->g_type, is_a_type))
2352 g_warning ("invalid class cast from `%s' to `%s'",
2353 type_descriptive_name_U (type_class->g_type),
2354 type_descriptive_name_U (is_a_type));
2362 g_type_check_instance (GTypeInstance *type_instance)
2364 /* this function is just here to make the signal system
2365 * conveniently elaborated on instance checks
2369 g_warning ("instance is invalid (NULL) pointer");
2372 if (!type_instance->g_class)
2374 g_warning ("instance with invalid (NULL) class pointer");
2377 /* G_TYPE_IS_CLASSED() is an external call: _U */
2378 if (!G_TYPE_IS_CLASSED (type_instance->g_class->g_type))
2380 g_warning ("instance of invalid unclassed type `%s'",
2381 type_descriptive_name_U (type_instance->g_class->g_type));
2384 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2385 if (!G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type))
2387 g_warning ("instance of invalid non-instantiatable type `%s'",
2388 type_descriptive_name_U (type_instance->g_class->g_type));
2396 /* --- foreign prototypes --- */
2397 extern void g_value_types_init (void); /* sync with gvaluetypes.c */
2398 extern void g_enum_types_init (void); /* sync with genums.c */
2399 extern void g_param_type_init (void); /* sync with gparam.c */
2400 extern void g_boxed_type_init (void); /* sync with gboxed.c */
2401 extern void g_object_type_init (void); /* sync with gobject.c */
2402 extern void g_param_spec_types_init (void); /* sync with gparamspecs.c */
2403 extern void g_signal_init (void); /* sync with gsignal.c */
2406 /* --- initialization --- */
2408 g_type_init (GTypeDebugFlags debug_flags)
2410 G_LOCK_DEFINE_STATIC (type_init_lock);
2411 static TypeNode *type0_node = NULL;
2412 const gchar *env_string;
2417 G_LOCK (type_init_lock);
2419 G_WRITE_LOCK (&type_rw_lock);
2421 if (static_last_fundamental_id)
2423 G_WRITE_UNLOCK (&type_rw_lock);
2424 G_UNLOCK (type_init_lock);
2428 /* setup GRuntime wide debugging flags */
2429 _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
2430 env_string = g_getenv ("GRUNTIME_DEBUG");
2431 if (env_string != NULL)
2433 static GDebugKey debug_keys[] = {
2434 { "objects", G_TYPE_DEBUG_OBJECTS },
2435 { "signals", G_TYPE_DEBUG_SIGNALS },
2438 _g_type_debug_flags |= g_parse_debug_string (env_string,
2440 sizeof (debug_keys) / sizeof (debug_keys[0]));
2445 static_quark_type_flags = g_quark_from_static_string ("GTypeFlags");
2447 /* type qname hash table */
2448 static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
2450 /* invalid type G_TYPE_INVALID (0)
2452 static_last_fundamental_id = 1;
2453 static_type_nodes = g_renew (TypeNode**, static_type_nodes, static_last_fundamental_id);
2454 static_type_nodes[0] = &type0_node;
2455 static_branch_seqnos = g_renew (GType, static_branch_seqnos, static_last_fundamental_id);
2456 static_branch_seqnos[0] = 1;
2458 /* void type G_TYPE_NONE
2460 node = type_node_fundamental_new_W (G_TYPE_NONE, "void", 0);
2461 type = NODE_TYPE (node);
2462 g_assert (type == G_TYPE_NONE);
2464 /* interface fundamental type G_TYPE_INTERFACE (!classed)
2466 memset (&info, 0, sizeof (info));
2467 node = type_node_fundamental_new_W (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
2468 type = NODE_TYPE (node);
2469 type_data_make_W (node, &info, NULL);
2470 g_assert (type == G_TYPE_INTERFACE);
2472 G_WRITE_UNLOCK (&type_rw_lock);
2474 /* G_TYPE_TYPE_PLUGIN
2476 g_type_plugin_get_type ();
2478 /* G_TYPE_* value types
2480 g_value_types_init ();
2482 /* G_TYPE_ENUM & G_TYPE_FLAGS
2484 g_enum_types_init ();
2488 g_param_type_init ();
2492 g_boxed_type_init ();
2496 g_object_type_init ();
2498 /* G_TYPE_PARAM_* pspec types
2500 g_param_spec_types_init ();
2506 G_UNLOCK (type_init_lock);