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.
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 * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
35 * not ->supers[]), as all those memory portions can get realloc()ed during
36 * callback invocation.
39 * - g_type_from_name() should do an ordered array lookup after fetching the
40 * the quark, instead of a second hashtable lookup.
41 * - speedup checks for virtual types, steal a bit somewhere
44 * - force interface initialization for already existing classes
47 * lock handling issues when calling static functions are indicated by
48 * uppercase letter postfixes, all static functions have to have
49 * one of the below postfixes:
50 * - _I: [Indifferent about locking]
51 * function doesn't care about locks at all
52 * - _U: [Unlocked invocation]
53 * no read or write lock has to be held across function invocation
54 * (locks may be acquired and released during invocation though)
55 * - _L: [Locked invocation]
56 * a write lock or more than 0 read locks have to be held across
58 * - _W: [Write-locked invocation]
59 * a write lock has to be held across function invokation
60 * - _Wm: [Write-locked invocation, mutatable]
61 * like _W, but the write lock might be released and reacquired
62 * during invocation, watch your pointers
65 static GStaticRWLock type_rw_lock = G_STATIC_RW_LOCK_INIT;
66 #define G_READ_LOCK(rw_lock) g_static_rw_lock_reader_lock (rw_lock)
67 #define G_READ_UNLOCK(rw_lock) g_static_rw_lock_reader_unlock (rw_lock)
68 #define G_WRITE_LOCK(rw_lock) g_static_rw_lock_writer_lock (rw_lock)
69 #define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
70 #define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
71 static const gchar *_action = " invalidly modified type "; \
72 gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
74 g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
76 g_error ("%s()%s`%s'", _fname, _action, _tname); \
78 #define g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{ \
81 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
82 "%s: initialization assertion failed, use %s() prior to this function", \
83 G_STRLOC, G_STRINGIFY (init_function)); \
84 return (return_value); \
89 #define DEBUG_CODE(debug_type, code_block) G_STMT_START { \
90 if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
93 #else /* !G_ENABLE_DEBUG */
94 #define DEBUG_CODE(debug_type, code_block) /* code_block */
95 #endif /* G_ENABLE_DEBUG */
97 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
98 G_TYPE_FLAG_INSTANTIATABLE | \
99 G_TYPE_FLAG_DERIVABLE | \
100 G_TYPE_FLAG_DEEP_DERIVABLE)
101 #define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
104 /* --- typedefs --- */
105 typedef struct _TypeNode TypeNode;
106 typedef struct _CommonData CommonData;
107 typedef struct _IFaceData IFaceData;
108 typedef struct _ClassData ClassData;
109 typedef struct _InstanceData InstanceData;
110 typedef union _TypeData TypeData;
111 typedef struct _IFaceEntry IFaceEntry;
112 typedef struct _IFaceHolder IFaceHolder;
115 /* --- prototypes --- */
116 static inline GTypeFundamentalInfo* type_node_fundamental_info_L (TypeNode *node);
117 static void type_add_flags_W (TypeNode *node,
119 static void type_data_make_W (TypeNode *node,
120 const GTypeInfo *info,
121 const GTypeValueTable *value_table);
122 static inline void type_data_ref_Wm (TypeNode *node);
123 static inline void type_data_unref_Wm (TypeNode *node,
125 static void type_data_last_unref_Wm (GType type,
127 static inline gpointer type_get_qdata_L (TypeNode *node,
129 static inline void type_set_qdata_W (TypeNode *node,
134 /* --- structures --- */
135 struct _GValue /* kludge, keep in sync with gvalue.h */
142 guint n_children : 12;
144 guint _prot_n_ifaces_prerequisites : 9;
145 guint is_classed : 1;
146 guint is_instantiatable : 1;
153 IFaceEntry *iface_entries; /* for !iface types */
154 GType *prerequisistes;
156 GType supers[1]; /* flexible array */
158 #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
159 #define MAX_N_SUPERS (255)
160 #define MAX_N_CHILDREN (4095)
161 #define MAX_N_IFACES (511)
162 #define MAX_N_PREREQUISITES (MAX_N_IFACES)
163 #define NODE_TYPE(node) (node->supers[0])
164 #define NODE_PARENT_TYPE(node) (node->supers[1])
165 #define NODE_NAME(node) (g_quark_to_string (node->qname))
166 #define NODE_IS_IFACE(node) (G_TYPE_IS_INTERFACE (NODE_TYPE (node)))
167 #define CLASSED_NODE_N_IFACES(node) ((node)->_prot_n_ifaces_prerequisites)
168 #define CLASSED_NODE_IFACES_ENTRIES(node) ((node)->_prot.iface_entries)
169 #define IFACE_NODE_N_PREREQUISITES(node) ((node)->_prot_n_ifaces_prerequisites)
170 #define IFACE_NODE_PREREQUISITES(node) ((node)->_prot.prerequisistes)
171 #define iface_node_get_holders_L(node) ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
172 #define iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
173 #define iface_node_get_dependants_array_L(n) ((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
174 #define iface_node_set_dependants_array_W(n,d) (type_set_qdata_W ((n), static_quark_dependants_array, (d)))
179 GInterfaceInfo *info;
186 GTypeInterface *vtable;
191 GTypeValueTable *value_table;
197 GBaseInitFunc vtable_init_base;
198 GBaseFinalizeFunc vtable_finalize_base;
204 GBaseInitFunc class_init_base;
205 GBaseFinalizeFunc class_finalize_base;
206 GClassInitFunc class_init;
207 GClassFinalizeFunc class_finalize;
208 gconstpointer class_data;
215 GBaseInitFunc class_init_base;
216 GBaseFinalizeFunc class_finalize_base;
217 GClassInitFunc class_init;
218 GClassFinalizeFunc class_finalize;
219 gconstpointer class_data;
221 guint16 instance_size;
223 GInstanceInitFunc instance_init;
224 GMemChunk *mem_chunk;
231 InstanceData instance;
235 GTypeClassCacheFunc cache_func;
239 /* --- variables --- */
240 static guint static_n_class_cache_funcs = 0;
241 static ClassCacheFunc *static_class_cache_funcs = NULL;
242 static GType static_last_fundamental_id = 0;
243 static GQuark static_quark_type_flags = 0;
244 static GQuark static_quark_iface_holder = 0;
245 static GQuark static_quark_dependants_array = 0;
246 GTypeDebugFlags _g_type_debug_flags = 0;
249 /* --- externs --- */
250 const char *g_log_domain_gruntime = "GRuntime";
253 /* --- type nodes --- */
254 static GHashTable *static_type_nodes_ht = NULL;
255 static GType *static_branch_seqnos = NULL;
256 static TypeNode ***static_type_nodes = NULL;
258 static inline TypeNode*
259 lookup_type_node_L (register GType utype)
261 register GType ftype = G_TYPE_FUNDAMENTAL (utype);
262 register GType b_seqno = G_TYPE_BRANCH_SEQNO (utype);
264 if (ftype < static_last_fundamental_id && b_seqno < static_branch_seqnos[ftype])
265 return static_type_nodes[ftype][b_seqno];
271 type_node_any_new_W (TypeNode *pnode,
275 GTypeFundamentalFlags type_flags)
277 guint branch_last, n_supers;
280 guint i, node_size = 0;
282 n_supers = pnode ? pnode->n_supers + 1 : 0;
283 branch_last = static_branch_seqnos[ftype]++;
284 type = G_TYPE_DERIVE_ID (ftype, branch_last);
285 g_assert ((type & G_TYPE_FLAG_RESERVED_ID_BIT) == 0);
286 if (!branch_last || g_bit_storage (branch_last - 1) < g_bit_storage (static_branch_seqnos[ftype] - 1))
287 static_type_nodes[ftype] = g_renew (TypeNode*, static_type_nodes[ftype], 1 << g_bit_storage (static_branch_seqnos[ftype] - 1));
290 node_size += sizeof (GTypeFundamentalInfo); /* fundamental type info */
291 node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
292 node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + 0 for ->supers[] */
293 node = g_malloc0 (node_size);
294 if (!pnode) /* offset fundamental types */
295 node = G_STRUCT_MEMBER_P (node, sizeof (GTypeFundamentalInfo));
296 static_type_nodes[ftype][branch_last] = node;
298 node->n_supers = n_supers;
301 node->supers[0] = type;
304 node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
305 node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
307 if (NODE_IS_IFACE (node))
309 IFACE_NODE_N_PREREQUISITES (node) = 0;
310 IFACE_NODE_PREREQUISITES (node) = NULL;
314 CLASSED_NODE_N_IFACES (node) = 0;
315 CLASSED_NODE_IFACES_ENTRIES (node) = NULL;
320 node->supers[0] = type;
321 memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
323 node->is_classed = pnode->is_classed;
324 node->is_instantiatable = pnode->is_instantiatable;
326 if (NODE_IS_IFACE (node))
328 IFACE_NODE_N_PREREQUISITES (node) = 0;
329 IFACE_NODE_PREREQUISITES (node) = NULL;
333 CLASSED_NODE_N_IFACES (node) = CLASSED_NODE_N_IFACES (pnode);
334 CLASSED_NODE_IFACES_ENTRIES (node) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode),
335 sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode)[0]) *
336 CLASSED_NODE_N_IFACES (node));
339 i = pnode->n_children++;
340 pnode->children = g_renew (GType, pnode->children, pnode->n_children);
341 pnode->children[i] = type;
344 node->plugin = plugin;
345 node->n_children = 0;
346 node->children = NULL;
348 node->qname = g_quark_from_string (name);
349 node->global_gdata = NULL;
351 g_hash_table_insert (static_type_nodes_ht,
352 GUINT_TO_POINTER (node->qname),
353 GUINT_TO_POINTER (type));
357 static inline GTypeFundamentalInfo*
358 type_node_fundamental_info_L (TypeNode *node)
360 GType ftype = G_TYPE_FUNDAMENTAL (NODE_TYPE (node));
362 if (ftype != NODE_TYPE (node))
363 node = lookup_type_node_L (ftype);
365 return node ? G_STRUCT_MEMBER_P (node, - (gssize) sizeof (GTypeFundamentalInfo)) : NULL;
369 type_node_fundamental_new_W (GType ftype,
371 GTypeFundamentalFlags type_flags)
373 GTypeFundamentalInfo *finfo;
377 flast = static_last_fundamental_id;
379 g_assert (ftype == G_TYPE_FUNDAMENTAL (ftype));
381 type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
383 static_last_fundamental_id = MAX (static_last_fundamental_id, ftype + 1);
384 if (static_last_fundamental_id > flast)
386 static_type_nodes = g_renew (TypeNode**, static_type_nodes, static_last_fundamental_id);
387 static_branch_seqnos = g_renew (GType, static_branch_seqnos, static_last_fundamental_id);
388 for (i = flast; i < static_last_fundamental_id; i++)
390 static_type_nodes[i] = NULL;
391 static_branch_seqnos[i] = 0;
394 g_assert (static_branch_seqnos[ftype] == 0);
396 node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
398 finfo = type_node_fundamental_info_L (node);
399 finfo->type_flags = type_flags;
405 type_node_new_W (TypeNode *pnode,
411 g_assert (pnode->n_supers < MAX_N_SUPERS);
412 g_assert (pnode->n_children < MAX_N_CHILDREN);
414 return type_node_any_new_W (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (pnode)), name, plugin, 0);
417 static inline IFaceEntry*
418 type_lookup_iface_entry_L (TypeNode *node,
419 TypeNode *iface_node)
421 if (NODE_IS_IFACE (iface_node) && CLASSED_NODE_N_IFACES (node))
423 IFaceEntry *ifaces = CLASSED_NODE_IFACES_ENTRIES (node) - 1;
424 guint n_ifaces = CLASSED_NODE_N_IFACES (node);
425 GType iface_type = NODE_TYPE (iface_node);
432 i = (n_ifaces + 1) >> 1;
434 if (iface_type == check->iface_type)
436 else if (iface_type > check->iface_type)
441 else /* if (iface_type < check->iface_type) */
450 static inline gboolean
451 type_lookup_prerequisite (TypeNode *iface,
452 GType prerequisite_type)
454 if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface))
456 GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1;
457 guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface);
464 i = (n_prerequisites + 1) >> 1;
465 check = prerequisites + i;
466 if (prerequisite_type == *check)
468 else if (prerequisite_type > *check)
470 n_prerequisites -= i;
471 prerequisites = check;
473 else /* if (prerequisite_type < *check) */
474 n_prerequisites = i - 1;
476 while (n_prerequisites);
482 type_descriptive_name_L (GType type)
486 TypeNode *node = lookup_type_node_L (type);
488 return node ? NODE_NAME (node) : "<unknown>";
495 type_descriptive_name_U (GType type)
499 G_READ_LOCK (&type_rw_lock);
500 name = type_descriptive_name_L (type);
501 G_READ_UNLOCK (&type_rw_lock);
503 return (gchar *)name;
507 /* --- type consistency checks --- */
509 check_plugin_U (GTypePlugin *plugin,
510 gboolean need_complete_type_info,
511 gboolean need_complete_interface_info,
512 const gchar *type_name)
514 /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U
518 g_warning ("plugin handle for type `%s' is NULL",
522 if (!G_IS_TYPE_PLUGIN (plugin))
524 g_warning ("plugin pointer (%p) for type `%s' is invalid",
528 if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
530 g_warning ("plugin for type `%s' has no complete_type_info() implementation",
534 if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
536 g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
544 check_type_name_U (const gchar *type_name)
546 static const gchar *extra_chars = "-_+";
547 const gchar *p = type_name;
550 if (!type_name[0] || !type_name[1] || !type_name[2])
552 g_warning ("type name `%s' is too short", type_name);
555 /* check the first letter */
556 name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
557 for (p = type_name + 1; *p; p++)
558 name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
559 (p[0] >= 'a' && p[0] <= 'z') ||
560 (p[0] >= '0' && p[0] <= '9') ||
561 strchr (extra_chars, p[0]));
564 g_warning ("type name `%s' contains invalid characters", type_name);
567 if (g_type_from_name (type_name))
569 g_warning ("cannot register existing type `%s'", type_name);
577 check_derivation_U (GType parent_type,
578 const gchar *type_name)
581 GTypeFundamentalInfo* finfo;
583 G_READ_LOCK (&type_rw_lock);
584 pnode = lookup_type_node_L (parent_type);
587 G_READ_UNLOCK (&type_rw_lock);
588 g_warning ("cannot derive type `%s' from invalid parent type `%s'",
590 type_descriptive_name_U (parent_type));
593 finfo = type_node_fundamental_info_L (pnode);
594 /* ensure flat derivability */
595 if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
597 G_READ_UNLOCK (&type_rw_lock);
598 g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
603 /* ensure deep derivability */
604 if (parent_type != G_TYPE_FUNDAMENTAL (parent_type) &&
605 !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
607 G_READ_UNLOCK (&type_rw_lock);
608 g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
613 G_READ_UNLOCK (&type_rw_lock);
619 check_collect_format_I (const gchar *collect_format)
621 const gchar *p = collect_format;
622 gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
623 G_VALUE_COLLECT_DOUBLE, G_VALUE_COLLECT_POINTER,
627 if (!strchr (valid_format, *p++))
629 return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
633 check_value_table_I (const gchar *type_name,
634 const GTypeValueTable *value_table)
638 else if (value_table->value_init == NULL)
640 if (value_table->value_free || value_table->value_copy ||
641 value_table->value_peek_pointer ||
642 value_table->collect_format || value_table->collect_value ||
643 value_table->lcopy_format || value_table->lcopy_value)
644 g_warning ("cannot handle uninitializable values of type `%s'",
648 else /* value_table->value_init != NULL */
650 if (!value_table->value_free)
653 * g_warning ("missing `value_free()' for type `%s'", type_name);
657 if (!value_table->value_copy)
659 g_warning ("missing `value_copy()' for type `%s'", type_name);
662 if ((value_table->collect_format || value_table->collect_value) &&
663 (!value_table->collect_format || !value_table->collect_value))
665 g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
669 if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
671 g_warning ("the `%s' specification for type `%s' is too long or invalid",
676 if ((value_table->lcopy_format || value_table->lcopy_value) &&
677 (!value_table->lcopy_format || !value_table->lcopy_value))
679 g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
683 if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
685 g_warning ("the `%s' specification for type `%s' is too long or invalid",
695 check_type_info_L (TypeNode *pnode,
697 const gchar *type_name,
698 const GTypeInfo *info)
700 GTypeFundamentalInfo *finfo = type_node_fundamental_info_L (lookup_type_node_L (ftype));
701 gboolean is_interface = G_TYPE_IS_INTERFACE (ftype);
703 /* check instance members */
704 if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
705 (info->instance_size || info->n_preallocs || info->instance_init))
708 g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
712 g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
716 /* check class & interface members */
717 if (!(finfo->type_flags & G_TYPE_FLAG_CLASSED) &&
718 (info->class_init || info->class_finalize || info->class_data ||
719 (!is_interface && (info->class_size || info->base_init || info->base_finalize))))
722 g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
726 g_warning ("cannot create class for `%s' as non-classed fundamental",
730 /* check interface size */
731 if (is_interface && info->class_size < sizeof (GTypeInterface))
733 g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
737 /* check class size */
738 if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
740 if (info->class_size < sizeof (GTypeClass))
742 g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
746 if (pnode && info->class_size < pnode->data->class.class_size)
748 g_warning ("specified class size for type `%s' is smaller "
749 "than the parent type's `%s' class size",
755 /* check instance size */
756 if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
758 if (info->instance_size < sizeof (GTypeInstance))
760 g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
764 if (pnode && info->instance_size < pnode->data->instance.instance_size)
766 g_warning ("specified instance size for type `%s' is smaller "
767 "than the parent type's `%s' instance size",
778 find_conforming_type_L (TypeNode *pnode,
781 TypeNode *node = NULL;
784 if (type_lookup_iface_entry_L (pnode, iface))
787 for (i = 0; i < pnode->n_children && !node; i++)
788 node = find_conforming_type_L (lookup_type_node_L (pnode->children[i]), iface);
794 check_add_interface_L (GType instance_type,
797 TypeNode *node = lookup_type_node_L (instance_type);
798 TypeNode *iface = lookup_type_node_L (iface_type);
801 if (!node || !node->is_instantiatable)
803 g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
804 type_descriptive_name_L (instance_type));
807 if (!iface || !NODE_IS_IFACE (iface))
809 g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
810 type_descriptive_name_L (iface_type),
814 tnode = lookup_type_node_L (NODE_PARENT_TYPE (iface));
815 if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
817 g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
823 tnode = find_conforming_type_L (node, iface);
826 g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
836 check_interface_info_L (TypeNode *iface,
838 const GInterfaceInfo *info)
840 if ((info->interface_finalize || info->interface_data) && !info->interface_init)
842 g_warning ("interface type `%s' for type `%s' comes without initializer",
844 type_descriptive_name_L (instance_type));
851 /* --- type info (type node data) --- */
853 type_data_make_W (TypeNode *node,
854 const GTypeInfo *info,
855 const GTypeValueTable *value_table)
858 GTypeValueTable *vtable = NULL;
859 guint vtable_size = 0;
861 g_assert (node->data == NULL && info != NULL);
865 TypeNode *pnode = lookup_type_node_L (NODE_PARENT_TYPE (node));
868 vtable = pnode->data->common.value_table;
871 static const GTypeValueTable zero_vtable = { NULL, };
873 value_table = &zero_vtable;
878 /* need to setup vtable_size since we have to allocate it with data in one chunk */
879 vtable_size = sizeof (GTypeValueTable);
880 if (value_table->collect_format)
881 vtable_size += strlen (value_table->collect_format);
882 if (value_table->lcopy_format)
883 vtable_size += strlen (value_table->lcopy_format);
887 if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */
889 data = g_malloc0 (sizeof (InstanceData) + vtable_size);
891 vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
892 data->instance.class_size = info->class_size;
893 data->instance.class_init_base = info->base_init;
894 data->instance.class_finalize_base = info->base_finalize;
895 data->instance.class_init = info->class_init;
896 data->instance.class_finalize = info->class_finalize;
897 data->instance.class_data = info->class_data;
898 data->instance.class = NULL;
899 data->instance.instance_size = info->instance_size;
900 #ifdef DISABLE_MEM_POOLS
901 data->instance.n_preallocs = 0;
902 #else /* !DISABLE_MEM_POOLS */
903 data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
904 #endif /* !DISABLE_MEM_POOLS */
905 data->instance.instance_init = info->instance_init;
906 data->instance.mem_chunk = NULL;
908 else if (node->is_classed) /* only classed */
910 data = g_malloc0 (sizeof (ClassData) + vtable_size);
912 vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
913 data->class.class_size = info->class_size;
914 data->class.class_init_base = info->base_init;
915 data->class.class_finalize_base = info->base_finalize;
916 data->class.class_init = info->class_init;
917 data->class.class_finalize = info->class_finalize;
918 data->class.class_data = info->class_data;
919 data->class.class = NULL;
921 else if (NODE_IS_IFACE (node))
923 data = g_malloc0 (sizeof (IFaceData) + vtable_size);
925 vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
926 data->iface.vtable_size = info->class_size;
927 data->iface.vtable_init_base = info->base_init;
928 data->iface.vtable_finalize_base = info->base_finalize;
932 data = g_malloc0 (sizeof (CommonData) + vtable_size);
934 vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
938 node->data->common.ref_count = 1;
944 /* we allocate the vtable and its strings together with the type data, so
945 * children can take over their parent's vtable pointer, and we don't
946 * need to worry freeing it or not when the child data is destroyed
948 *vtable = *value_table;
949 p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable));
951 vtable->collect_format = p;
952 if (value_table->collect_format)
954 strcat (p, value_table->collect_format);
955 p += strlen (value_table->collect_format);
959 vtable->lcopy_format = p;
960 if (value_table->lcopy_format)
961 strcat (p, value_table->lcopy_format);
963 node->data->common.value_table = vtable;
965 g_assert (node->data->common.value_table != NULL); /* paranoid */
969 type_data_ref_Wm (TypeNode *node)
973 TypeNode *pnode = lookup_type_node_L (NODE_PARENT_TYPE (node));
975 GTypeValueTable tmp_value_table;
977 g_assert (node->plugin != NULL);
981 type_data_ref_Wm (pnode);
983 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
986 memset (&tmp_info, 0, sizeof (tmp_info));
987 memset (&tmp_value_table, 0, sizeof (tmp_value_table));
989 G_WRITE_UNLOCK (&type_rw_lock);
990 g_type_plugin_use (node->plugin);
991 g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
992 G_WRITE_LOCK (&type_rw_lock);
994 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
996 check_type_info_L (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmp_info);
997 type_data_make_W (node, &tmp_info,
998 check_value_table_I (NODE_NAME (node),
999 &tmp_value_table) ? &tmp_value_table : NULL);
1003 g_assert (node->data->common.ref_count > 0);
1005 node->data->common.ref_count += 1;
1010 type_data_unref_Wm (TypeNode *node,
1013 g_assert (node->data && node->data->common.ref_count);
1015 if (node->data->common.ref_count > 1)
1016 node->data->common.ref_count -= 1;
1021 g_warning ("static type `%s' unreferenced too often",
1026 type_data_last_unref_Wm (NODE_TYPE (node), uncached);
1031 type_node_add_iface_entry_W (TypeNode *node,
1034 IFaceEntry *entries;
1037 g_assert (node->is_instantiatable && CLASSED_NODE_N_IFACES (node) < MAX_N_IFACES);
1039 entries = CLASSED_NODE_IFACES_ENTRIES (node);
1040 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1041 if (entries[i].iface_type == iface_type)
1043 g_warning ("failed to add interface, type `%s' already conforms to interface type `%s'",
1044 type_descriptive_name_L (NODE_TYPE (node)),
1045 type_descriptive_name_L (iface_type));
1048 else if (entries[i].iface_type > iface_type)
1050 CLASSED_NODE_N_IFACES (node) += 1;
1051 CLASSED_NODE_IFACES_ENTRIES (node) = g_renew (IFaceEntry,
1052 CLASSED_NODE_IFACES_ENTRIES (node),
1053 CLASSED_NODE_N_IFACES (node));
1054 entries = CLASSED_NODE_IFACES_ENTRIES (node);
1055 g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (CLASSED_NODE_N_IFACES (node) - i - 1));
1056 entries[i].iface_type = iface_type;
1057 entries[i].vtable = NULL;
1059 for (i = 0; i < node->n_children; i++)
1060 type_node_add_iface_entry_W (lookup_type_node_L (node->children[i]), iface_type);
1064 type_add_interface_W (TypeNode *node,
1066 const GInterfaceInfo *info,
1067 GTypePlugin *plugin)
1069 IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
1071 /* we must not call any functions of GInterfaceInfo from within here, since
1072 * we got most probably called from _within_ a type registration function
1074 g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin)));
1076 iholder->next = iface_node_get_holders_L (iface);
1077 iface_node_set_holders_W (iface, iholder);
1078 iholder->instance_type = NODE_TYPE (node);
1079 iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
1080 iholder->plugin = plugin;
1082 type_node_add_iface_entry_W (node, NODE_TYPE (iface));
1086 type_iface_add_prerequisite_W (TypeNode *iface,
1087 TypeNode *prerequisite_node)
1089 GType prerequisite_type = NODE_TYPE (prerequisite_node);
1090 GType *prerequisites, *dependants;
1091 guint n_dependants, i;
1093 g_assert (NODE_IS_IFACE (iface) &&
1094 IFACE_NODE_N_PREREQUISITES (iface) < MAX_N_PREREQUISITES &&
1095 (prerequisite_node->is_instantiatable || NODE_IS_IFACE (prerequisite_node)));
1097 prerequisites = IFACE_NODE_PREREQUISITES (iface);
1098 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1099 if (prerequisites[i] == prerequisite_type)
1100 return; /* we already have that prerequisiste */
1101 else if (prerequisites[i] > prerequisite_type)
1103 IFACE_NODE_N_PREREQUISITES (iface) += 1;
1104 IFACE_NODE_PREREQUISITES (iface) = g_renew (GType,
1105 IFACE_NODE_PREREQUISITES (iface),
1106 IFACE_NODE_N_PREREQUISITES (iface));
1107 prerequisites = IFACE_NODE_PREREQUISITES (iface);
1108 g_memmove (prerequisites + i + 1, prerequisites + i,
1109 sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1));
1110 prerequisites[i] = prerequisite_type;
1112 /* we want to get notified when prerequisites get added to prerequisite_node */
1113 if (NODE_IS_IFACE (prerequisite_node))
1115 dependants = iface_node_get_dependants_array_L (prerequisite_node);
1116 n_dependants = dependants ? dependants[0] : 0;
1118 dependants = g_renew (GType, dependants, n_dependants + 1);
1119 dependants[n_dependants] = NODE_TYPE (iface);
1120 dependants[0] = n_dependants;
1121 iface_node_set_dependants_array_W (prerequisite_node, dependants);
1124 /* we need to notify all dependants */
1125 dependants = iface_node_get_dependants_array_L (iface);
1126 n_dependants = dependants ? dependants[0] : 0;
1127 for (i = 1; i <= n_dependants; i++)
1128 type_iface_add_prerequisite_W (lookup_type_node_L (dependants[i]), prerequisite_node);
1132 g_type_interface_add_prerequisite (GType interface_type,
1133 GType prerequisite_type)
1135 TypeNode *iface, *prerequisite_node;
1136 IFaceHolder *holders;
1138 g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type));
1139 g_return_if_fail (!g_type_is_a (interface_type, prerequisite_type));
1140 g_return_if_fail (!g_type_is_a (prerequisite_type, interface_type));
1142 G_WRITE_LOCK (&type_rw_lock);
1143 iface = lookup_type_node_L (interface_type);
1144 prerequisite_node = lookup_type_node_L (prerequisite_type);
1145 if (!iface || !prerequisite_node || !NODE_IS_IFACE (iface))
1147 g_warning ("interface type `%s' or prerequisite type `%s' invalid",
1148 type_descriptive_name_L (interface_type),
1149 type_descriptive_name_L (prerequisite_type));
1150 G_WRITE_UNLOCK (&type_rw_lock);
1153 holders = iface_node_get_holders_L (iface);
1156 g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'",
1157 type_descriptive_name_L (prerequisite_type),
1158 type_descriptive_name_L (interface_type),
1159 type_descriptive_name_L (holders->instance_type));
1160 G_WRITE_UNLOCK (&type_rw_lock);
1163 if (prerequisite_node->is_instantiatable)
1167 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1169 TypeNode *prnode = lookup_type_node_L (IFACE_NODE_PREREQUISITES (iface)[i]);
1171 if (prnode->is_instantiatable)
1173 g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
1174 type_descriptive_name_L (prerequisite_type),
1175 type_descriptive_name_L (interface_type),
1176 type_descriptive_name_L (NODE_TYPE (prnode)));
1177 G_WRITE_UNLOCK (&type_rw_lock);
1182 for (i = 0; i < prerequisite_node->n_supers + 1; i++)
1183 type_iface_add_prerequisite_W (iface, lookup_type_node_L (prerequisite_node->supers[i]));
1185 else if (NODE_IS_IFACE (prerequisite_node))
1188 guint n_dependants, i;
1190 dependants = iface_node_get_dependants_array_L (prerequisite_node);
1191 n_dependants = dependants ? dependants[0] : 0;
1192 for (i = 1; i <= n_dependants; i++)
1193 type_iface_add_prerequisite_W (iface, lookup_type_node_L (dependants[i]));
1194 type_iface_add_prerequisite_W (iface, prerequisite_node);
1197 g_warning ("prerequisite `%s' for interface `%s' is not instantiatable or interface",
1198 type_descriptive_name_L (prerequisite_type),
1199 type_descriptive_name_L (interface_type));
1200 G_WRITE_UNLOCK (&type_rw_lock);
1204 type_iface_retrive_holder_info_Wm (TypeNode *iface,
1205 GType instance_type)
1207 IFaceHolder *iholder = iface_node_get_holders_L (iface);
1209 g_assert (NODE_IS_IFACE (iface));
1211 while (iholder->instance_type != instance_type)
1212 iholder = iholder->next;
1216 GInterfaceInfo tmp_info;
1218 g_assert (iholder->plugin != NULL);
1220 type_data_ref_Wm (iface);
1222 INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface));
1224 memset (&tmp_info, 0, sizeof (tmp_info));
1226 G_WRITE_UNLOCK (&type_rw_lock);
1227 g_type_plugin_use (iholder->plugin);
1228 g_type_plugin_complete_interface_info (iholder->plugin, instance_type, NODE_TYPE (iface), &tmp_info);
1229 G_WRITE_LOCK (&type_rw_lock);
1231 INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
1233 check_interface_info_L (iface, instance_type, &tmp_info);
1234 iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
1241 type_iface_blow_holder_info_Wm (TypeNode *iface,
1242 GType instance_type)
1244 IFaceHolder *iholder = iface_node_get_holders_L (iface);
1246 g_assert (NODE_IS_IFACE (iface));
1248 while (iholder->instance_type != instance_type)
1249 iholder = iholder->next;
1251 if (iholder->info && iholder->plugin)
1253 g_free (iholder->info);
1254 iholder->info = NULL;
1256 G_WRITE_UNLOCK (&type_rw_lock);
1257 g_type_plugin_unuse (iholder->plugin);
1258 G_WRITE_LOCK (&type_rw_lock);
1260 type_data_unref_Wm (iface, FALSE);
1265 /* --- type structure creation/destruction --- */
1267 g_type_create_instance (GType type)
1270 GTypeInstance *instance;
1274 G_READ_LOCK (&type_rw_lock);
1275 node = lookup_type_node_L (type);
1276 G_READ_UNLOCK (&type_rw_lock);
1277 if (!node || !node->is_instantiatable)
1279 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1280 type_descriptive_name_U (type));
1283 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1284 if (G_TYPE_IS_ABSTRACT (type))
1286 g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1287 type_descriptive_name_U (type));
1291 class = g_type_class_ref (type);
1293 if (node->data->instance.n_preallocs)
1295 G_WRITE_LOCK (&type_rw_lock);
1296 if (!node->data->instance.mem_chunk)
1297 node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
1298 node->data->instance.instance_size,
1299 (node->data->instance.instance_size *
1300 node->data->instance.n_preallocs),
1302 instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
1303 G_WRITE_UNLOCK (&type_rw_lock);
1306 instance = g_malloc0 (node->data->instance.instance_size); /* fine without read lock */
1307 for (i = node->n_supers; i > 0; i--)
1311 G_READ_LOCK (&type_rw_lock);
1312 pnode = lookup_type_node_L (node->supers[i]);
1313 G_READ_UNLOCK (&type_rw_lock);
1315 if (pnode->data->instance.instance_init)
1317 instance->g_class = pnode->data->instance.class;
1318 pnode->data->instance.instance_init (instance, class);
1321 instance->g_class = class;
1323 if (node->data->instance.instance_init)
1324 node->data->instance.instance_init (instance, class);
1330 g_type_free_instance (GTypeInstance *instance)
1335 g_return_if_fail (instance != NULL && instance->g_class != NULL);
1337 G_READ_LOCK (&type_rw_lock);
1338 class = instance->g_class;
1339 node = lookup_type_node_L (class->g_type);
1340 if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
1342 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1343 type_descriptive_name_L (class->g_type));
1344 G_READ_UNLOCK (&type_rw_lock);
1347 G_READ_UNLOCK (&type_rw_lock);
1348 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1349 if (G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
1351 g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1356 instance->g_class = NULL;
1357 memset (instance, 0xaa, node->data->instance.instance_size); /* FIXME: debugging hack */
1358 if (node->data->instance.n_preallocs)
1360 G_WRITE_LOCK (&type_rw_lock);
1361 g_chunk_free (instance, node->data->instance.mem_chunk);
1362 G_WRITE_UNLOCK (&type_rw_lock);
1367 g_type_class_unref (class);
1371 type_propagate_iface_vtable_W (TypeNode *pnode,
1373 GTypeInterface *vtable)
1375 IFaceEntry *entry = type_lookup_iface_entry_L (pnode, iface);
1378 entry->vtable = vtable;
1379 for (i = 0; i < pnode->n_children; i++)
1381 TypeNode *node = lookup_type_node_L (pnode->children[i]);
1383 type_propagate_iface_vtable_W (node, iface, vtable);
1388 type_iface_vtable_init_Wm (TypeNode *iface,
1391 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1392 IFaceHolder *iholder = type_iface_retrive_holder_info_Wm (iface, NODE_TYPE (node));
1393 GTypeInterface *vtable;
1395 g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
1397 vtable = g_malloc0 (iface->data->iface.vtable_size);
1398 type_propagate_iface_vtable_W (node, iface, vtable);
1399 vtable->g_type = NODE_TYPE (iface);
1400 vtable->g_instance_type = NODE_TYPE (node);
1402 if (iface->data->iface.vtable_init_base || iholder->info->interface_init)
1404 G_WRITE_UNLOCK (&type_rw_lock);
1405 if (iface->data->iface.vtable_init_base)
1406 iface->data->iface.vtable_init_base (vtable);
1407 if (iholder->info->interface_init)
1408 iholder->info->interface_init (vtable, iholder->info->interface_data);
1409 G_WRITE_LOCK (&type_rw_lock);
1414 type_iface_vtable_finalize_Wm (TypeNode *iface,
1416 GTypeInterface *vtable)
1418 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
1419 IFaceHolder *iholder = iface_node_get_holders_L (iface);
1421 g_assert (entry && entry->vtable == vtable);
1423 while (iholder->instance_type != NODE_TYPE (node))
1424 iholder = iholder->next;
1425 g_assert (iholder && iholder->info);
1427 type_propagate_iface_vtable_W (node, iface, NULL);
1428 if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
1430 G_WRITE_UNLOCK (&type_rw_lock);
1431 if (iholder->info->interface_finalize)
1432 iholder->info->interface_finalize (vtable, iholder->info->interface_data);
1433 if (iface->data->iface.vtable_finalize_base)
1434 iface->data->iface.vtable_finalize_base (vtable);
1435 G_WRITE_LOCK (&type_rw_lock);
1438 vtable->g_instance_type = 0;
1441 type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
1445 type_class_init_Wm (TypeNode *node,
1448 GSList *slist, *init_slist = NULL;
1454 g_assert (node->is_classed && node->data &&
1455 node->data->class.class_size &&
1456 !node->data->class.class);
1458 class = g_malloc0 (node->data->class.class_size);
1459 node->data->class.class = class;
1463 TypeNode *pnode = lookup_type_node_L (pclass->g_type);
1465 memcpy (class, pclass, pnode->data->class.class_size);
1467 class->g_type = NODE_TYPE (node);
1469 G_WRITE_UNLOCK (&type_rw_lock);
1471 /* stack all base class initialization functions, so we
1472 * call them in ascending order.
1474 G_READ_LOCK (&type_rw_lock);
1475 for (bnode = node; bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
1476 if (bnode->data->class.class_init_base)
1477 init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
1478 G_READ_UNLOCK (&type_rw_lock);
1479 for (slist = init_slist; slist; slist = slist->next)
1481 GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
1483 class_init_base (class);
1485 g_slist_free (init_slist);
1487 if (node->data->class.class_init)
1488 node->data->class.class_init (class, (gpointer) node->data->class.class_data);
1490 G_WRITE_LOCK (&type_rw_lock);
1492 /* ok, we got the class done, now initialize all interfaces */
1493 for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1494 if (!CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable)
1495 entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1498 type_iface_vtable_init_Wm (lookup_type_node_L (entry->iface_type), node);
1500 for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1501 if (!CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable)
1502 entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1507 type_data_finalize_class_ifaces_Wm (TypeNode *node)
1512 g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
1514 g_message ("finalizing interfaces for %sClass `%s'",
1515 type_descriptive_name_L (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
1516 type_descriptive_name_L (NODE_TYPE (node)));
1518 for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1519 if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable &&
1520 CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node))
1521 entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1524 type_iface_vtable_finalize_Wm (lookup_type_node_L (entry->iface_type), node, entry->vtable);
1526 for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
1527 if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable &&
1528 CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node))
1529 entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
1534 type_data_finalize_class_U (TypeNode *node,
1537 GTypeClass *class = cdata->class;
1540 g_assert (cdata->class && cdata->common.ref_count == 0);
1542 if (cdata->class_finalize)
1543 cdata->class_finalize (class, (gpointer) cdata->class_data);
1545 /* call all base class destruction functions in descending order
1547 if (cdata->class_finalize_base)
1548 cdata->class_finalize_base (class);
1549 G_READ_LOCK (&type_rw_lock);
1550 for (bnode = lookup_type_node_L (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
1551 if (bnode->data->class.class_finalize_base)
1553 G_READ_UNLOCK (&type_rw_lock);
1554 bnode->data->class.class_finalize_base (class);
1555 G_READ_LOCK (&type_rw_lock);
1557 G_READ_UNLOCK (&type_rw_lock);
1560 g_free (cdata->class);
1564 type_data_last_unref_Wm (GType type,
1567 TypeNode *node = lookup_type_node_L (type);
1569 g_return_if_fail (node != NULL && node->plugin != NULL);
1571 if (!node->data || node->data->common.ref_count == 0)
1573 g_warning ("cannot drop last reference to unreferenced type `%s'",
1574 type_descriptive_name_U (type));
1578 if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs)
1582 G_WRITE_UNLOCK (&type_rw_lock);
1583 G_READ_LOCK (&type_rw_lock);
1584 for (i = 0; i < static_n_class_cache_funcs; i++)
1586 GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func;
1587 gpointer cache_data = static_class_cache_funcs[i].cache_data;
1588 gboolean need_break;
1590 G_READ_UNLOCK (&type_rw_lock);
1591 need_break = cache_func (cache_data, node->data->class.class);
1592 G_READ_LOCK (&type_rw_lock);
1593 if (!node->data || node->data->common.ref_count == 0)
1594 INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
1598 G_READ_UNLOCK (&type_rw_lock);
1599 G_WRITE_LOCK (&type_rw_lock);
1602 if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */
1603 node->data->common.ref_count -= 1;
1606 GType ptype = NODE_PARENT_TYPE (node);
1609 node->data->common.ref_count = 0;
1611 if (node->is_instantiatable && node->data->instance.mem_chunk)
1613 g_mem_chunk_destroy (node->data->instance.mem_chunk);
1614 node->data->instance.mem_chunk = NULL;
1618 if (node->is_classed && tdata->class.class)
1620 if (CLASSED_NODE_N_IFACES (node))
1621 type_data_finalize_class_ifaces_Wm (node);
1623 G_WRITE_UNLOCK (&type_rw_lock);
1624 type_data_finalize_class_U (node, &tdata->class);
1625 G_WRITE_LOCK (&type_rw_lock);
1630 /* freeing tdata->common.value_table and its contents is taking care of
1631 * by allocating it in one chunk with tdata
1636 type_data_unref_Wm (lookup_type_node_L (ptype), FALSE);
1637 G_WRITE_UNLOCK (&type_rw_lock);
1638 g_type_plugin_unuse (node->plugin);
1639 G_WRITE_LOCK (&type_rw_lock);
1644 g_type_add_class_cache_func (gpointer cache_data,
1645 GTypeClassCacheFunc cache_func)
1649 g_return_if_fail (cache_func != NULL);
1651 G_WRITE_LOCK (&type_rw_lock);
1652 i = static_n_class_cache_funcs++;
1653 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
1654 static_class_cache_funcs[i].cache_data = cache_data;
1655 static_class_cache_funcs[i].cache_func = cache_func;
1656 G_WRITE_UNLOCK (&type_rw_lock);
1660 g_type_remove_class_cache_func (gpointer cache_data,
1661 GTypeClassCacheFunc cache_func)
1663 gboolean found_it = FALSE;
1666 g_return_if_fail (cache_func != NULL);
1668 G_WRITE_LOCK (&type_rw_lock);
1669 for (i = 0; i < static_n_class_cache_funcs; i++)
1670 if (static_class_cache_funcs[i].cache_data == cache_data &&
1671 static_class_cache_funcs[i].cache_func == cache_func)
1673 static_n_class_cache_funcs--;
1674 g_memmove (static_class_cache_funcs + i,
1675 static_class_cache_funcs + i + 1,
1676 sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
1677 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
1681 G_WRITE_UNLOCK (&type_rw_lock);
1684 g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
1685 cache_func, cache_data);
1689 /* --- type registration --- */
1691 g_type_register_fundamental (GType type_id,
1692 const gchar *type_name,
1693 const GTypeInfo *info,
1694 const GTypeFundamentalInfo *finfo,
1697 GTypeFundamentalInfo *node_finfo;
1700 g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, 0);
1701 g_return_val_if_fail (type_id > 0, 0);
1702 g_return_val_if_fail (type_name != NULL, 0);
1703 g_return_val_if_fail (info != NULL, 0);
1704 g_return_val_if_fail (finfo != NULL, 0);
1706 if (!check_type_name_U (type_name))
1708 if (G_TYPE_FUNDAMENTAL (type_id) != type_id)
1710 g_warning ("cannot register fundamental type `%s' with non-fundamental id (%u)",
1715 if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
1716 !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
1718 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1722 G_WRITE_LOCK (&type_rw_lock);
1723 if (lookup_type_node_L (type_id))
1725 G_WRITE_UNLOCK (&type_rw_lock);
1726 g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1727 type_descriptive_name_U (type_id),
1732 node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
1733 node_finfo = type_node_fundamental_info_L (node);
1734 type_add_flags_W (node, flags);
1736 if (check_type_info_L (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
1737 type_data_make_W (node, info,
1738 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
1739 G_WRITE_UNLOCK (&type_rw_lock);
1741 return NODE_TYPE (node);
1745 g_type_register_static (GType parent_type,
1746 const gchar *type_name,
1747 const GTypeInfo *info,
1750 TypeNode *pnode, *node;
1753 g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, 0);
1754 g_return_val_if_fail (parent_type > 0, 0);
1755 g_return_val_if_fail (type_name != NULL, 0);
1756 g_return_val_if_fail (info != NULL, 0);
1758 if (!check_type_name_U (type_name) ||
1759 !check_derivation_U (parent_type, type_name))
1761 if (info->class_finalize)
1763 g_warning ("class finalizer specified for static type `%s'",
1768 G_WRITE_LOCK (&type_rw_lock);
1769 pnode = lookup_type_node_L (parent_type);
1770 type_data_ref_Wm (pnode);
1771 if (check_type_info_L (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
1773 node = type_node_new_W (pnode, type_name, NULL);
1774 type_add_flags_W (node, flags);
1775 type = NODE_TYPE (node);
1776 type_data_make_W (node, info,
1777 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
1779 G_WRITE_UNLOCK (&type_rw_lock);
1785 g_type_register_dynamic (GType parent_type,
1786 const gchar *type_name,
1787 GTypePlugin *plugin,
1790 TypeNode *pnode, *node;
1793 g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, 0);
1794 g_return_val_if_fail (parent_type > 0, 0);
1795 g_return_val_if_fail (type_name != NULL, 0);
1796 g_return_val_if_fail (plugin != NULL, 0);
1798 if (!check_type_name_U (type_name) ||
1799 !check_derivation_U (parent_type, type_name) ||
1800 !check_plugin_U (plugin, TRUE, FALSE, type_name))
1803 G_WRITE_LOCK (&type_rw_lock);
1804 pnode = lookup_type_node_L (parent_type);
1805 node = type_node_new_W (pnode, type_name, plugin);
1806 type_add_flags_W (node, flags);
1807 type = NODE_TYPE (node);
1808 G_WRITE_UNLOCK (&type_rw_lock);
1814 g_type_add_interface_static (GType instance_type,
1815 GType interface_type,
1816 const GInterfaceInfo *info)
1818 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1819 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1820 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1822 G_WRITE_LOCK (&type_rw_lock);
1823 if (check_add_interface_L (instance_type, interface_type))
1825 TypeNode *node = lookup_type_node_L (instance_type);
1826 TypeNode *iface = lookup_type_node_L (interface_type);
1828 if (check_interface_info_L (iface, NODE_TYPE (node), info))
1829 type_add_interface_W (node, iface, info, NULL);
1831 G_WRITE_UNLOCK (&type_rw_lock);
1835 g_type_add_interface_dynamic (GType instance_type,
1836 GType interface_type,
1837 GTypePlugin *plugin)
1841 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1842 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
1843 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
1845 G_READ_LOCK (&type_rw_lock);
1846 node = lookup_type_node_L (instance_type);
1847 G_READ_UNLOCK (&type_rw_lock);
1848 if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
1851 G_WRITE_LOCK (&type_rw_lock);
1852 if (check_add_interface_L (instance_type, interface_type))
1854 TypeNode *iface = lookup_type_node_L (interface_type);
1856 type_add_interface_W (node, iface, NULL, plugin);
1858 G_WRITE_UNLOCK (&type_rw_lock);
1862 /* --- public API functions --- */
1864 g_type_class_ref (GType type)
1868 /* optimize for common code path
1870 G_WRITE_LOCK (&type_rw_lock);
1871 node = lookup_type_node_L (type);
1872 if (node && node->is_classed && node->data &&
1873 node->data->class.class && node->data->common.ref_count > 0)
1875 type_data_ref_Wm (node);
1876 G_WRITE_UNLOCK (&type_rw_lock);
1878 return node->data->class.class;
1881 if (!node || !node->is_classed ||
1882 (node->data && node->data->common.ref_count < 1))
1884 G_WRITE_UNLOCK (&type_rw_lock);
1885 g_warning ("cannot retrive class for invalid (unclassed) type `%s'",
1886 type_descriptive_name_U (type));
1890 type_data_ref_Wm (node);
1892 if (!node->data->class.class)
1894 GType ptype = NODE_PARENT_TYPE (node);
1895 GTypeClass *pclass = NULL;
1899 G_WRITE_UNLOCK (&type_rw_lock);
1900 pclass = g_type_class_ref (ptype);
1901 if (node->data->class.class)
1902 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1903 G_WRITE_LOCK (&type_rw_lock);
1906 type_class_init_Wm (node, pclass);
1908 G_WRITE_UNLOCK (&type_rw_lock);
1910 return node->data->class.class;
1914 g_type_class_unref (gpointer g_class)
1917 GTypeClass *class = g_class;
1919 g_return_if_fail (g_class != NULL);
1921 G_WRITE_LOCK (&type_rw_lock);
1922 node = lookup_type_node_L (class->g_type);
1923 if (node && node->is_classed && node->data &&
1924 node->data->class.class == class && node->data->common.ref_count > 0)
1925 type_data_unref_Wm (node, FALSE);
1927 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1928 type_descriptive_name_L (class->g_type));
1929 G_WRITE_UNLOCK (&type_rw_lock);
1933 g_type_class_unref_uncached (gpointer g_class)
1936 GTypeClass *class = g_class;
1938 g_return_if_fail (g_class != NULL);
1940 G_WRITE_LOCK (&type_rw_lock);
1941 node = lookup_type_node_L (class->g_type);
1942 if (node && node->is_classed && node->data &&
1943 node->data->class.class == class && node->data->common.ref_count > 0)
1944 type_data_unref_Wm (node, TRUE);
1946 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1947 type_descriptive_name_L (class->g_type));
1948 G_WRITE_UNLOCK (&type_rw_lock);
1952 g_type_class_peek (GType type)
1957 G_READ_LOCK (&type_rw_lock);
1958 node = lookup_type_node_L (type);
1959 if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
1960 class = node->data->class.class;
1963 G_READ_UNLOCK (&type_rw_lock);
1969 g_type_class_peek_parent (gpointer g_class)
1974 g_return_val_if_fail (g_class != NULL, NULL);
1976 G_READ_LOCK (&type_rw_lock);
1977 node = lookup_type_node_L (G_TYPE_FROM_CLASS (g_class));
1978 if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
1980 node = lookup_type_node_L (NODE_PARENT_TYPE (node));
1981 class = node->data->class.class;
1985 G_READ_UNLOCK (&type_rw_lock);
1991 g_type_interface_peek (gpointer instance_class,
1996 gpointer vtable = NULL;
1997 GTypeClass *class = instance_class;
1999 g_return_val_if_fail (instance_class != NULL, NULL);
2001 G_READ_LOCK (&type_rw_lock);
2002 node = lookup_type_node_L (class->g_type);
2003 iface = lookup_type_node_L (iface_type);
2004 if (node && node->is_instantiatable && iface)
2006 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
2008 if (entry && entry->vtable)
2009 vtable = entry->vtable;
2011 G_READ_UNLOCK (&type_rw_lock);
2016 G_CONST_RETURN gchar*
2017 g_type_name (GType type)
2021 g_return_val_if_uninitialized (static_last_fundamental_id, g_type_init, NULL);
2023 G_READ_LOCK (&type_rw_lock);
2024 node = lookup_type_node_L (type);
2025 G_READ_UNLOCK (&type_rw_lock);
2027 return node ? NODE_NAME (node) : NULL;
2031 g_type_qname (GType type)
2035 G_READ_LOCK (&type_rw_lock);
2036 node = lookup_type_node_L (type);
2037 G_READ_UNLOCK (&type_rw_lock);
2039 return node ? node->qname : 0;
2043 g_type_from_name (const gchar *name)
2048 g_return_val_if_fail (name != NULL, 0);
2050 quark = g_quark_try_string (name);
2053 G_READ_LOCK (&type_rw_lock);
2054 type = GPOINTER_TO_UINT (g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark)));
2055 G_READ_UNLOCK (&type_rw_lock);
2062 g_type_parent (GType type)
2066 G_READ_LOCK (&type_rw_lock);
2067 node = lookup_type_node_L (type);
2068 G_READ_UNLOCK (&type_rw_lock);
2070 return node ? NODE_PARENT_TYPE (node) : 0;
2074 g_type_next_base (GType type,
2080 G_READ_LOCK (&type_rw_lock);
2081 node = lookup_type_node_L (type);
2084 TypeNode *base_node = lookup_type_node_L (base_type);
2086 if (base_node && base_node->n_supers < node->n_supers)
2088 guint n = node->n_supers - base_node->n_supers;
2090 if (node->supers[n] == base_type)
2091 atype = node->supers[n - 1];
2094 G_READ_UNLOCK (&type_rw_lock);
2099 static inline gboolean
2100 type_node_is_a_L (TypeNode *node,
2101 TypeNode *iface_node,
2102 /* support_inheritance */
2103 gboolean support_interfaces,
2104 gboolean support_prerequisites)
2106 if (support_interfaces &&
2107 node->is_instantiatable && NODE_IS_IFACE (iface_node) &&
2108 type_lookup_iface_entry_L (node, iface_node) != NULL)
2110 else if (/* support_inheritance && */
2111 iface_node->n_supers <= node->n_supers &&
2112 node->supers[node->n_supers - iface_node->n_supers] == NODE_TYPE (iface_node))
2114 else if (support_prerequisites &&
2115 NODE_IS_IFACE (node) &&
2116 type_lookup_prerequisite (node, NODE_TYPE (iface_node)))
2123 g_type_is_a (GType type,
2126 TypeNode *node, *iface_node;
2129 G_READ_LOCK (&type_rw_lock);
2130 node = lookup_type_node_L (type);
2131 iface_node = lookup_type_node_L (iface_type);
2132 is_a = node && iface_node && type_node_is_a_L (node, iface_node, TRUE, TRUE);
2133 G_READ_UNLOCK (&type_rw_lock);
2139 g_type_fundamental_branch_last (GType type)
2141 GType ftype = G_TYPE_FUNDAMENTAL (type);
2144 G_READ_LOCK (&type_rw_lock);
2145 last_type = ftype < static_last_fundamental_id ? static_branch_seqnos[ftype] : 0;
2146 G_READ_UNLOCK (&type_rw_lock);
2151 GType* /* free result */
2152 g_type_children (GType type,
2157 G_READ_LOCK (&type_rw_lock);
2158 node = lookup_type_node_L (type);
2161 GType *children = g_new (GType, node->n_children + 1);
2163 memcpy (children, node->children, sizeof (GType) * node->n_children);
2164 children[node->n_children] = 0;
2167 *n_children = node->n_children;
2168 G_READ_UNLOCK (&type_rw_lock);
2174 G_READ_UNLOCK (&type_rw_lock);
2182 GType* /* free result */
2183 g_type_interfaces (GType type,
2184 guint *n_interfaces)
2188 G_READ_LOCK (&type_rw_lock);
2189 node = lookup_type_node_L (type);
2190 if (node && node->is_instantiatable)
2192 GType *ifaces = g_new (GType, CLASSED_NODE_N_IFACES (node) + 1);
2195 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
2196 ifaces[i] = CLASSED_NODE_IFACES_ENTRIES (node)[i].iface_type;
2200 *n_interfaces = CLASSED_NODE_N_IFACES (node);
2201 G_READ_UNLOCK (&type_rw_lock);
2207 G_READ_UNLOCK (&type_rw_lock);
2215 typedef struct _QData QData;
2227 static inline gpointer
2228 type_get_qdata_L (TypeNode *node,
2231 GData *gdata = node->global_gdata;
2233 if (quark && gdata && gdata->n_qdatas)
2235 QData *qdatas = gdata->qdatas - 1;
2236 guint n_qdatas = gdata->n_qdatas;
2243 i = (n_qdatas + 1) / 2;
2245 if (quark == check->quark)
2247 else if (quark > check->quark)
2252 else /* if (quark < check->quark) */
2261 g_type_get_qdata (GType type,
2267 G_READ_LOCK (&type_rw_lock);
2268 node = lookup_type_node_L (type);
2271 data = type_get_qdata_L (node, quark);
2272 G_READ_UNLOCK (&type_rw_lock);
2276 G_READ_UNLOCK (&type_rw_lock);
2277 g_return_val_if_fail (node != NULL, NULL);
2284 type_set_qdata_W (TypeNode *node,
2292 /* setup qdata list if necessary */
2293 if (!node->global_gdata)
2294 node->global_gdata = g_new0 (GData, 1);
2295 gdata = node->global_gdata;
2297 /* try resetting old data */
2298 qdata = gdata->qdatas;
2299 for (i = 0; i < gdata->n_qdatas; i++)
2300 if (qdata[i].quark == quark)
2302 qdata[i].data = data;
2308 gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
2309 qdata = gdata->qdatas;
2310 for (i = 0; i < gdata->n_qdatas - 1; i++)
2311 if (qdata[i].quark > quark)
2313 g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
2314 qdata[i].quark = quark;
2315 qdata[i].data = data;
2319 g_type_set_qdata (GType type,
2325 g_return_if_fail (quark != 0);
2327 G_WRITE_LOCK (&type_rw_lock);
2328 node = lookup_type_node_L (type);
2331 type_set_qdata_W (node, quark, data);
2332 G_WRITE_UNLOCK (&type_rw_lock);
2336 G_WRITE_UNLOCK (&type_rw_lock);
2337 g_return_if_fail (node != NULL);
2342 type_add_flags_W (TypeNode *node,
2347 g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
2348 g_return_if_fail (node != NULL);
2350 if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class)
2351 g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
2352 dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
2354 type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
2358 g_type_query (GType type,
2363 g_return_if_fail (query != NULL);
2365 G_READ_LOCK (&type_rw_lock);
2366 node = lookup_type_node_L (type);
2367 if (node && node->is_classed && !node->plugin && node->data)
2369 /* type is classed and static, probably even instantiatable */
2371 query->type = NODE_TYPE (node);
2372 query->type_name = NODE_NAME (node);
2373 query->class_size = node->data->class.class_size;
2374 query->instance_size = node->is_instantiatable ? node->data->instance.instance_size : 0;
2378 /* node is not static and classed, won't allow query */
2381 G_READ_UNLOCK (&type_rw_lock);
2385 /* --- implementation details --- */
2387 g_type_check_flags (GType type,
2391 gboolean result = FALSE;
2393 G_READ_LOCK (&type_rw_lock);
2394 node = lookup_type_node_L (type);
2397 guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
2398 guint tflags = flags & TYPE_FLAG_MASK;
2402 GTypeFundamentalInfo *finfo = type_node_fundamental_info_L (node);
2404 fflags = (finfo->type_flags & fflags) == fflags;
2410 tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
2414 result = tflags && fflags;
2416 G_READ_UNLOCK (&type_rw_lock);
2422 g_type_get_plugin (GType type)
2426 G_READ_LOCK (&type_rw_lock);
2427 node = lookup_type_node_L (type);
2428 G_READ_UNLOCK (&type_rw_lock);
2430 return node ? node->plugin : NULL;
2434 g_type_interface_get_plugin (GType instance_type,
2435 GType interface_type)
2440 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
2442 G_READ_LOCK (&type_rw_lock);
2443 node = lookup_type_node_L (instance_type);
2444 iface = lookup_type_node_L (interface_type);
2447 IFaceHolder *iholder = iface_node_get_holders_L (iface);
2449 while (iholder && iholder->instance_type != instance_type)
2450 iholder = iholder->next;
2451 G_READ_UNLOCK (&type_rw_lock);
2454 return iholder->plugin;
2457 G_READ_UNLOCK (&type_rw_lock);
2459 g_return_val_if_fail (node == NULL, NULL);
2460 g_return_val_if_fail (iface == NULL, NULL);
2462 g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
2468 g_type_fundamental_last (void)
2472 G_READ_LOCK (&type_rw_lock);
2473 type = static_last_fundamental_id;
2474 G_READ_UNLOCK (&type_rw_lock);
2480 g_type_instance_is_a (GTypeInstance *type_instance,
2483 TypeNode *node, *iface;
2486 if (!type_instance || !type_instance->g_class)
2489 G_READ_LOCK (&type_rw_lock);
2490 node = lookup_type_node_L (type_instance->g_class->g_type);
2491 iface = lookup_type_node_L (iface_type);
2492 check = node && node->is_instantiatable && iface && type_node_is_a_L (node, iface, TRUE, FALSE);
2493 G_READ_UNLOCK (&type_rw_lock);
2499 g_type_class_is_a (GTypeClass *type_class,
2502 TypeNode *node, *iface;
2508 G_READ_LOCK (&type_rw_lock);
2509 node = lookup_type_node_L (type_class->g_type);
2510 iface = lookup_type_node_L (is_a_type);
2511 check = node && node->is_classed && iface && type_node_is_a_L (node, iface, FALSE, FALSE);
2512 G_READ_UNLOCK (&type_rw_lock);
2518 g_type_check_instance_cast (GTypeInstance *type_instance,
2523 if (type_instance->g_class)
2525 TypeNode *node, *iface;
2526 gboolean is_instantiatable, check;
2528 G_READ_LOCK (&type_rw_lock);
2529 node = lookup_type_node_L (type_instance->g_class->g_type);
2530 is_instantiatable = node && node->is_instantiatable;
2531 iface = lookup_type_node_L (iface_type);
2532 check = is_instantiatable && iface && type_node_is_a_L (node, iface, TRUE, FALSE);
2533 G_READ_UNLOCK (&type_rw_lock);
2535 return type_instance;
2537 if (is_instantiatable)
2538 g_warning ("invalid cast from `%s' to `%s'",
2539 type_descriptive_name_U (type_instance->g_class->g_type),
2540 type_descriptive_name_U (iface_type));
2542 g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
2543 type_descriptive_name_U (type_instance->g_class->g_type),
2544 type_descriptive_name_U (iface_type));
2547 g_warning ("invalid unclassed pointer in cast to `%s'",
2548 type_descriptive_name_U (iface_type));
2551 g_warning ("invalid cast from (NULL) pointer to `%s'",
2552 type_descriptive_name_U (iface_type));
2554 return type_instance;
2558 g_type_check_class_cast (GTypeClass *type_class,
2563 TypeNode *node, *iface;
2564 gboolean is_classed, check;
2566 G_READ_LOCK (&type_rw_lock);
2567 node = lookup_type_node_L (type_class->g_type);
2568 is_classed = node && node->is_classed;
2569 iface = lookup_type_node_L (is_a_type);
2570 check = is_classed && iface && type_node_is_a_L (node, iface, FALSE, FALSE);
2571 G_READ_UNLOCK (&type_rw_lock);
2576 g_warning ("invalid class cast from `%s' to `%s'",
2577 type_descriptive_name_U (type_class->g_type),
2578 type_descriptive_name_U (is_a_type));
2580 g_warning ("invalid unclassed type `%s' in class cast to `%s'",
2581 type_descriptive_name_U (type_class->g_type),
2582 type_descriptive_name_U (is_a_type));
2585 g_warning ("invalid class cast from (NULL) pointer to `%s'",
2586 type_descriptive_name_U (is_a_type));
2591 g_type_check_instance (GTypeInstance *type_instance)
2593 /* this function is just here to make the signal system
2594 * conveniently elaborated on instance checks
2598 if (type_instance->g_class)
2601 gboolean is_instantiatable;
2603 G_READ_LOCK (&type_rw_lock);
2604 node = lookup_type_node_L (type_instance->g_class->g_type);
2605 is_instantiatable = node && node->is_instantiatable;
2606 G_READ_UNLOCK (&type_rw_lock);
2607 if (is_instantiatable)
2610 g_warning ("instance of invalid non-instantiatable type `%s'",
2611 type_descriptive_name_U (type_instance->g_class->g_type));
2614 g_warning ("instance with invalid (NULL) class pointer");
2617 g_warning ("invalid (NULL) pointer instance");
2622 static inline gboolean
2623 type_check_is_value_type_U (GType type)
2625 GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT;
2628 G_READ_LOCK (&type_rw_lock);
2630 node = lookup_type_node_L (type);
2633 if (node->data && node->data->common.ref_count > 0 &&
2634 node->data->common.value_table->value_init)
2635 tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
2636 else if (NODE_IS_IFACE (node))
2640 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
2642 GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
2643 TypeNode *prnode = lookup_type_node_L (prtype);
2645 if (prnode->is_instantiatable)
2653 G_READ_UNLOCK (&type_rw_lock);
2655 return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT);
2659 g_type_check_is_value_type (GType type)
2661 return type_check_is_value_type_U (type);
2665 g_type_check_value (GValue *value)
2667 return value && type_check_is_value_type_U (value->g_type);
2671 g_type_check_value_holds (GValue *value,
2674 return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type);
2678 g_type_value_table_peek (GType type)
2681 GTypeValueTable *vtable;
2683 G_READ_LOCK (&type_rw_lock);
2685 node = lookup_type_node_L (type);
2688 g_warning ("type id `%u' is invalid", type);
2689 G_READ_UNLOCK (&type_rw_lock);
2692 if (!node->data || node->data->common.ref_count < 1)
2694 g_warning ("can't peek value table for type `%s' which is not currently referenced",
2695 type_descriptive_name_L (type));
2696 G_READ_UNLOCK (&type_rw_lock);
2699 if (node->data->common.value_table->value_init)
2700 vtable = node->data->common.value_table;
2701 else if (NODE_IS_IFACE (node))
2705 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
2707 GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
2708 TypeNode *prnode = lookup_type_node_L (prtype);
2710 if (prnode->is_instantiatable)
2713 goto restart_table_peek;
2720 G_READ_UNLOCK (&type_rw_lock);
2726 /* --- foreign prototypes --- */
2727 extern void g_value_types_init (void); /* sync with gvaluetypes.c */
2728 extern void g_enum_types_init (void); /* sync with genums.c */
2729 extern void g_param_type_init (void); /* sync with gparam.c */
2730 extern void g_boxed_type_init (void); /* sync with gboxed.c */
2731 extern void g_object_type_init (void); /* sync with gobject.c */
2732 extern void g_param_spec_types_init (void); /* sync with gparamspecs.c */
2733 extern void g_value_transforms_init (void); /* sync with gvaluetransform.c */
2734 extern void g_signal_init (void); /* sync with gsignal.c */
2737 /* --- initialization --- */
2739 g_type_init (GTypeDebugFlags debug_flags)
2741 G_LOCK_DEFINE_STATIC (type_init_lock);
2742 static TypeNode *type0_node = NULL;
2743 const gchar *env_string;
2748 G_LOCK (type_init_lock);
2750 G_WRITE_LOCK (&type_rw_lock);
2752 if (static_last_fundamental_id)
2754 G_WRITE_UNLOCK (&type_rw_lock);
2755 G_UNLOCK (type_init_lock);
2759 /* setup GRuntime wide debugging flags */
2760 _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
2761 env_string = g_getenv ("GRUNTIME_DEBUG");
2762 if (env_string != NULL)
2764 static GDebugKey debug_keys[] = {
2765 { "objects", G_TYPE_DEBUG_OBJECTS },
2766 { "signals", G_TYPE_DEBUG_SIGNALS },
2769 _g_type_debug_flags |= g_parse_debug_string (env_string,
2771 sizeof (debug_keys) / sizeof (debug_keys[0]));
2776 static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
2777 static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
2778 static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
2780 /* type qname hash table */
2781 static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
2783 /* invalid type G_TYPE_INVALID (0)
2785 static_last_fundamental_id = 1;
2786 static_type_nodes = g_renew (TypeNode**, static_type_nodes, static_last_fundamental_id);
2787 static_type_nodes[0] = &type0_node;
2788 static_branch_seqnos = g_renew (GType, static_branch_seqnos, static_last_fundamental_id);
2789 static_branch_seqnos[0] = 1;
2791 /* void type G_TYPE_NONE
2793 node = type_node_fundamental_new_W (G_TYPE_NONE, "void", 0);
2794 type = NODE_TYPE (node);
2795 g_assert (type == G_TYPE_NONE);
2797 /* interface fundamental type G_TYPE_INTERFACE (!classed)
2799 memset (&info, 0, sizeof (info));
2800 node = type_node_fundamental_new_W (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
2801 type = NODE_TYPE (node);
2802 type_data_make_W (node, &info, NULL);
2803 g_assert (type == G_TYPE_INTERFACE);
2805 G_WRITE_UNLOCK (&type_rw_lock);
2807 /* G_TYPE_TYPE_PLUGIN
2809 g_type_plugin_get_type ();
2811 /* G_TYPE_* value types
2813 g_value_types_init ();
2815 /* G_TYPE_ENUM & G_TYPE_FLAGS
2817 g_enum_types_init ();
2821 g_boxed_type_init ();
2825 g_param_type_init ();
2829 g_object_type_init ();
2831 /* G_TYPE_PARAM_* pspec types
2833 g_param_spec_types_init ();
2835 /* Value Transformations
2837 g_value_transforms_init ();
2843 G_UNLOCK (type_init_lock);