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.
43 * lock handling issues when calling static functions are indicated by
44 * uppercase letter postfixes, all static functions have to have
45 * one of the below postfixes:
46 * - _I: [Indifferent about locking]
47 * function doesn't care about locks at all
48 * - _U: [Unlocked invocation]
49 * no read or write lock has to be held across function invocation
50 * (locks may be acquired and released during invocation though)
51 * - _L: [Locked invocation]
52 * a write lock or more than 0 read locks have to be held across
54 * - _W: [Write-locked invocation]
55 * a write lock has to be held across function invokation
56 * - _Wm: [Write-locked invocation, mutatable]
57 * like _W, but the write lock might be released and reacquired
58 * during invocation, watch your pointers
61 static GStaticRWLock type_rw_lock
= G_STATIC_RW_LOCK_INIT
;
63 #define G_READ_LOCK(rw_lock) do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0)
64 #define G_READ_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0)
65 #define G_WRITE_LOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL++\n"); g_static_rw_lock_writer_lock (rw_lock); } while (0)
66 #define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_static_rw_lock_writer_unlock (rw_lock); } while (0)
68 #define G_READ_LOCK(rw_lock) g_static_rw_lock_reader_lock (rw_lock)
69 #define G_READ_UNLOCK(rw_lock) g_static_rw_lock_reader_unlock (rw_lock)
70 #define G_WRITE_LOCK(rw_lock) g_static_rw_lock_writer_lock (rw_lock)
71 #define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
73 #define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
74 static const gchar *_action = " invalidly modified type "; \
75 gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
77 g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
79 g_error ("%s()%s`%s'", _fname, _action, _tname); \
81 #define g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{ \
84 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
85 "%s: initialization assertion failed, use %s() prior to this function", \
86 G_STRLOC, G_STRINGIFY (init_function)); \
87 return (return_value); \
92 #define DEBUG_CODE(debug_type, code_block) G_STMT_START { \
93 if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
96 #else /* !G_ENABLE_DEBUG */
97 #define DEBUG_CODE(debug_type, code_block) /* code_block */
98 #endif /* G_ENABLE_DEBUG */
100 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
101 G_TYPE_FLAG_INSTANTIATABLE | \
102 G_TYPE_FLAG_DERIVABLE | \
103 G_TYPE_FLAG_DEEP_DERIVABLE)
104 #define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
105 #define SIZEOF_FUNDAMENTAL_INFO ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
106 sizeof (gpointer)), \
110 /* --- typedefs --- */
111 typedef struct _TypeNode TypeNode
;
112 typedef struct _CommonData CommonData
;
113 typedef struct _IFaceData IFaceData
;
114 typedef struct _ClassData ClassData
;
115 typedef struct _InstanceData InstanceData
;
116 typedef union _TypeData TypeData
;
117 typedef struct _IFaceEntry IFaceEntry
;
118 typedef struct _IFaceHolder IFaceHolder
;
121 /* --- prototypes --- */
122 static inline GTypeFundamentalInfo
* type_node_fundamental_info_I (TypeNode
*node
);
123 static void type_add_flags_W (TypeNode
*node
,
125 static void type_data_make_W (TypeNode
*node
,
126 const GTypeInfo
*info
,
127 const GTypeValueTable
*value_table
);
128 static inline void type_data_ref_Wm (TypeNode
*node
);
129 static inline void type_data_unref_Wm (TypeNode
*node
,
131 static void type_data_last_unref_Wm (GType type
,
133 static inline gpointer
type_get_qdata_L (TypeNode
*node
,
135 static inline void type_set_qdata_W (TypeNode
*node
,
138 static IFaceHolder
* type_iface_peek_holder_L (TypeNode
*iface
,
139 GType instance_type
);
140 static gboolean
type_node_is_a_L (TypeNode
*node
,
141 TypeNode
*iface_node
);
144 /* --- structures --- */
148 guint n_children
: 12;
150 guint _prot_n_ifaces_prerequisites
: 9;
151 guint is_classed
: 1;
152 guint is_instantiatable
: 1;
153 guint mutatable_check_cache
: 1; /* combines some common path checks */
155 TypeData
* volatile data
;
159 IFaceEntry
*iface_entries
; /* for !iface types */
160 GType
*prerequisistes
;
162 GType supers
[1]; /* flexible array */
164 #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
165 #define MAX_N_SUPERS (255)
166 #define MAX_N_CHILDREN (4095)
167 #define MAX_N_IFACES (511)
168 #define MAX_N_PREREQUISITES (MAX_N_IFACES)
169 #define NODE_TYPE(node) (node->supers[0])
170 #define NODE_PARENT_TYPE(node) (node->supers[1])
171 #define NODE_FUNDAMENTAL_TYPE(node) (node->supers[node->n_supers])
172 #define NODE_NAME(node) (g_quark_to_string (node->qname))
173 #define NODE_IS_IFACE(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
174 #define CLASSED_NODE_N_IFACES(node) ((node)->_prot_n_ifaces_prerequisites)
175 #define CLASSED_NODE_IFACES_ENTRIES(node) ((node)->_prot.iface_entries)
176 #define IFACE_NODE_N_PREREQUISITES(node) ((node)->_prot_n_ifaces_prerequisites)
177 #define IFACE_NODE_PREREQUISITES(node) ((node)->_prot.prerequisistes)
178 #define iface_node_get_holders_L(node) ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
179 #define iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
180 #define iface_node_get_dependants_array_L(n) ((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
181 #define iface_node_set_dependants_array_W(n,d) (type_set_qdata_W ((n), static_quark_dependants_array, (d)))
182 #define TYPE_ID_MASK ((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1))
188 GInterfaceInfo
*info
;
195 GTypeInterface
*vtable
;
200 GTypeValueTable
*value_table
;
206 GBaseInitFunc vtable_init_base
;
207 GBaseFinalizeFunc vtable_finalize_base
;
213 GBaseInitFunc class_init_base
;
214 GBaseFinalizeFunc class_finalize_base
;
215 GClassInitFunc class_init
;
216 GClassFinalizeFunc class_finalize
;
217 gconstpointer class_data
;
224 GBaseInitFunc class_init_base
;
225 GBaseFinalizeFunc class_finalize_base
;
226 GClassInitFunc class_init
;
227 GClassFinalizeFunc class_finalize
;
228 gconstpointer class_data
;
230 guint16 instance_size
;
232 GInstanceInitFunc instance_init
;
233 GMemChunk
*mem_chunk
;
240 InstanceData instance
;
244 GTypeClassCacheFunc cache_func
;
248 /* --- variables --- */
249 static guint static_n_class_cache_funcs
= 0;
250 static ClassCacheFunc
*static_class_cache_funcs
= NULL
;
251 static GQuark static_quark_type_flags
= 0;
252 static GQuark static_quark_iface_holder
= 0;
253 static GQuark static_quark_dependants_array
= 0;
254 GTypeDebugFlags _g_type_debug_flags
= 0;
257 /* --- type nodes --- */
258 static GHashTable
*static_type_nodes_ht
= NULL
;
259 static TypeNode
*static_fundamental_type_nodes
[(G_TYPE_FUNDAMENTAL_MAX
>> G_TYPE_FUNDAMENTAL_SHIFT
) + 1] = { 0, };
260 static GType static_fundamental_next
= G_TYPE_RESERVED_USER_FIRST
;
262 static inline TypeNode
*
263 lookup_type_node_I (register GType utype
)
265 if (utype
> G_TYPE_FUNDAMENTAL_MAX
)
266 return (TypeNode
*) (utype
& ~TYPE_ID_MASK
);
268 return static_fundamental_type_nodes
[utype
>> G_TYPE_FUNDAMENTAL_SHIFT
];
272 type_node_any_new_W (TypeNode
*pnode
,
276 GTypeFundamentalFlags type_flags
)
281 guint i
, node_size
= 0;
283 n_supers
= pnode
? pnode
->n_supers
+ 1 : 0;
286 node_size
+= SIZEOF_FUNDAMENTAL_INFO
; /* fundamental type info */
287 node_size
+= SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
288 node_size
+= (sizeof (GType
) * (1 + n_supers
+ 1)); /* self + ancestors + (0) for ->supers[] */
289 node
= g_malloc0 (node_size
);
290 if (!pnode
) /* offset fundamental types */
292 node
= G_STRUCT_MEMBER_P (node
, SIZEOF_FUNDAMENTAL_INFO
);
293 static_fundamental_type_nodes
[ftype
>> G_TYPE_FUNDAMENTAL_SHIFT
] = node
;
299 g_assert ((type
& TYPE_ID_MASK
) == 0);
301 node
->n_supers
= n_supers
;
304 node
->supers
[0] = type
;
307 node
->is_classed
= (type_flags
& G_TYPE_FLAG_CLASSED
) != 0;
308 node
->is_instantiatable
= (type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) != 0;
310 if (NODE_IS_IFACE (node
))
312 IFACE_NODE_N_PREREQUISITES (node
) = 0;
313 IFACE_NODE_PREREQUISITES (node
) = NULL
;
317 CLASSED_NODE_N_IFACES (node
) = 0;
318 CLASSED_NODE_IFACES_ENTRIES (node
) = NULL
;
323 node
->supers
[0] = type
;
324 memcpy (node
->supers
+ 1, pnode
->supers
, sizeof (GType
) * (1 + pnode
->n_supers
+ 1));
326 node
->is_classed
= pnode
->is_classed
;
327 node
->is_instantiatable
= pnode
->is_instantiatable
;
329 if (NODE_IS_IFACE (node
))
331 IFACE_NODE_N_PREREQUISITES (node
) = 0;
332 IFACE_NODE_PREREQUISITES (node
) = NULL
;
338 CLASSED_NODE_N_IFACES (node
) = CLASSED_NODE_N_IFACES (pnode
);
339 CLASSED_NODE_IFACES_ENTRIES (node
) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode
),
340 sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode
)[0]) *
341 CLASSED_NODE_N_IFACES (node
));
342 for (j
= 0; j
< CLASSED_NODE_N_IFACES (node
); j
++)
343 CLASSED_NODE_IFACES_ENTRIES (node
)[j
].vtable
= NULL
;
346 i
= pnode
->n_children
++;
347 pnode
->children
= g_renew (GType
, pnode
->children
, pnode
->n_children
);
348 pnode
->children
[i
] = type
;
351 node
->plugin
= plugin
;
352 node
->n_children
= 0;
353 node
->children
= NULL
;
355 node
->qname
= g_quark_from_string (name
);
356 node
->global_gdata
= NULL
;
358 g_hash_table_insert (static_type_nodes_ht
,
359 GUINT_TO_POINTER (node
->qname
),
364 static inline GTypeFundamentalInfo
*
365 type_node_fundamental_info_I (TypeNode
*node
)
367 GType ftype
= NODE_FUNDAMENTAL_TYPE (node
);
369 if (ftype
!= NODE_TYPE (node
))
370 node
= lookup_type_node_I (ftype
);
372 return node
? G_STRUCT_MEMBER_P (node
, -SIZEOF_FUNDAMENTAL_INFO
) : NULL
;
376 type_node_fundamental_new_W (GType ftype
,
378 GTypeFundamentalFlags type_flags
)
380 GTypeFundamentalInfo
*finfo
;
383 g_assert ((ftype
& TYPE_ID_MASK
) == 0);
384 g_assert (ftype
<= G_TYPE_FUNDAMENTAL_MAX
);
386 if (ftype
>> G_TYPE_FUNDAMENTAL_SHIFT
== static_fundamental_next
)
387 static_fundamental_next
++;
389 type_flags
&= TYPE_FUNDAMENTAL_FLAG_MASK
;
391 node
= type_node_any_new_W (NULL
, ftype
, name
, NULL
, type_flags
);
393 finfo
= type_node_fundamental_info_I (node
);
394 finfo
->type_flags
= type_flags
;
400 type_node_new_W (TypeNode
*pnode
,
406 g_assert (pnode
->n_supers
< MAX_N_SUPERS
);
407 g_assert (pnode
->n_children
< MAX_N_CHILDREN
);
409 return type_node_any_new_W (pnode
, NODE_FUNDAMENTAL_TYPE (pnode
), name
, plugin
, 0);
412 static inline IFaceEntry
*
413 type_lookup_iface_entry_L (TypeNode
*node
,
414 TypeNode
*iface_node
)
416 if (NODE_IS_IFACE (iface_node
) && CLASSED_NODE_N_IFACES (node
))
418 IFaceEntry
*ifaces
= CLASSED_NODE_IFACES_ENTRIES (node
) - 1;
419 guint n_ifaces
= CLASSED_NODE_N_IFACES (node
);
420 GType iface_type
= NODE_TYPE (iface_node
);
427 i
= (n_ifaces
+ 1) >> 1;
429 if (iface_type
== check
->iface_type
)
431 else if (iface_type
> check
->iface_type
)
436 else /* if (iface_type < check->iface_type) */
445 static inline gboolean
446 type_lookup_prerequisite_L (TypeNode
*iface
,
447 GType prerequisite_type
)
449 if (NODE_IS_IFACE (iface
) && IFACE_NODE_N_PREREQUISITES (iface
))
451 GType
*prerequisites
= IFACE_NODE_PREREQUISITES (iface
) - 1;
452 guint n_prerequisites
= IFACE_NODE_N_PREREQUISITES (iface
);
459 i
= (n_prerequisites
+ 1) >> 1;
460 check
= prerequisites
+ i
;
461 if (prerequisite_type
== *check
)
463 else if (prerequisite_type
> *check
)
465 n_prerequisites
-= i
;
466 prerequisites
= check
;
468 else /* if (prerequisite_type < *check) */
469 n_prerequisites
= i
- 1;
471 while (n_prerequisites
);
477 type_descriptive_name_I (GType type
)
481 TypeNode
*node
= lookup_type_node_I (type
);
483 return node
? NODE_NAME (node
) : "<unknown>";
490 /* --- type consistency checks --- */
492 check_plugin_U (GTypePlugin
*plugin
,
493 gboolean need_complete_type_info
,
494 gboolean need_complete_interface_info
,
495 const gchar
*type_name
)
497 /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U
501 g_warning ("plugin handle for type `%s' is NULL",
505 if (!G_IS_TYPE_PLUGIN (plugin
))
507 g_warning ("plugin pointer (%p) for type `%s' is invalid",
511 if (need_complete_type_info
&& !G_TYPE_PLUGIN_GET_CLASS (plugin
)->complete_type_info
)
513 g_warning ("plugin for type `%s' has no complete_type_info() implementation",
517 if (need_complete_interface_info
&& !G_TYPE_PLUGIN_GET_CLASS (plugin
)->complete_interface_info
)
519 g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
527 check_type_name_I (const gchar
*type_name
)
529 static const gchar
*extra_chars
= "-_+";
530 const gchar
*p
= type_name
;
533 if (!type_name
[0] || !type_name
[1] || !type_name
[2])
535 g_warning ("type name `%s' is too short", type_name
);
538 /* check the first letter */
539 name_valid
= (p
[0] >= 'A' && p
[0] <= 'Z') || (p
[0] >= 'a' && p
[0] <= 'z') || p
[0] == '_';
540 for (p
= type_name
+ 1; *p
; p
++)
541 name_valid
&= ((p
[0] >= 'A' && p
[0] <= 'Z') ||
542 (p
[0] >= 'a' && p
[0] <= 'z') ||
543 (p
[0] >= '0' && p
[0] <= '9') ||
544 strchr (extra_chars
, p
[0]));
547 g_warning ("type name `%s' contains invalid characters", type_name
);
550 if (g_type_from_name (type_name
))
552 g_warning ("cannot register existing type `%s'", type_name
);
560 check_derivation_I (GType parent_type
,
561 const gchar
*type_name
)
564 GTypeFundamentalInfo
* finfo
;
566 pnode
= lookup_type_node_I (parent_type
);
569 g_warning ("cannot derive type `%s' from invalid parent type `%s'",
571 type_descriptive_name_I (parent_type
));
574 finfo
= type_node_fundamental_info_I (pnode
);
575 /* ensure flat derivability */
576 if (!(finfo
->type_flags
& G_TYPE_FLAG_DERIVABLE
))
578 g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
583 /* ensure deep derivability */
584 if (parent_type
!= NODE_FUNDAMENTAL_TYPE (pnode
) &&
585 !(finfo
->type_flags
& G_TYPE_FLAG_DEEP_DERIVABLE
))
587 g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
597 check_collect_format_I (const gchar
*collect_format
)
599 const gchar
*p
= collect_format
;
600 gchar valid_format
[] = { G_VALUE_COLLECT_INT
, G_VALUE_COLLECT_LONG
,
601 G_VALUE_COLLECT_INT64
, G_VALUE_COLLECT_DOUBLE
,
602 G_VALUE_COLLECT_POINTER
, 0 };
605 if (!strchr (valid_format
, *p
++))
607 return p
- collect_format
<= G_VALUE_COLLECT_FORMAT_MAX_LENGTH
;
611 check_value_table_I (const gchar
*type_name
,
612 const GTypeValueTable
*value_table
)
616 else if (value_table
->value_init
== NULL
)
618 if (value_table
->value_free
|| value_table
->value_copy
||
619 value_table
->value_peek_pointer
||
620 value_table
->collect_format
|| value_table
->collect_value
||
621 value_table
->lcopy_format
|| value_table
->lcopy_value
)
622 g_warning ("cannot handle uninitializable values of type `%s'",
626 else /* value_table->value_init != NULL */
628 if (!value_table
->value_free
)
631 * g_warning ("missing `value_free()' for type `%s'", type_name);
635 if (!value_table
->value_copy
)
637 g_warning ("missing `value_copy()' for type `%s'", type_name
);
640 if ((value_table
->collect_format
|| value_table
->collect_value
) &&
641 (!value_table
->collect_format
|| !value_table
->collect_value
))
643 g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
647 if (value_table
->collect_format
&& !check_collect_format_I (value_table
->collect_format
))
649 g_warning ("the `%s' specification for type `%s' is too long or invalid",
654 if ((value_table
->lcopy_format
|| value_table
->lcopy_value
) &&
655 (!value_table
->lcopy_format
|| !value_table
->lcopy_value
))
657 g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
661 if (value_table
->lcopy_format
&& !check_collect_format_I (value_table
->lcopy_format
))
663 g_warning ("the `%s' specification for type `%s' is too long or invalid",
673 check_type_info_I (TypeNode
*pnode
,
675 const gchar
*type_name
,
676 const GTypeInfo
*info
)
678 GTypeFundamentalInfo
*finfo
= type_node_fundamental_info_I (lookup_type_node_I (ftype
));
679 gboolean is_interface
= ftype
== G_TYPE_INTERFACE
;
681 g_assert (ftype
<= G_TYPE_FUNDAMENTAL_MAX
&& !(ftype
& TYPE_ID_MASK
));
683 /* check instance members */
684 if (!(finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) &&
685 (info
->instance_size
|| info
->n_preallocs
|| info
->instance_init
))
688 g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
692 g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
696 /* check class & interface members */
697 if (!(finfo
->type_flags
& G_TYPE_FLAG_CLASSED
) &&
698 (info
->class_init
|| info
->class_finalize
|| info
->class_data
||
699 (!is_interface
&& (info
->class_size
|| info
->base_init
|| info
->base_finalize
))))
702 g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
706 g_warning ("cannot create class for `%s' as non-classed fundamental",
710 /* check interface size */
711 if (is_interface
&& info
->class_size
< sizeof (GTypeInterface
))
713 g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
717 /* check class size */
718 if (finfo
->type_flags
& G_TYPE_FLAG_CLASSED
)
720 if (info
->class_size
< sizeof (GTypeClass
))
722 g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
726 if (pnode
&& info
->class_size
< pnode
->data
->class.class_size
)
728 g_warning ("specified class size for type `%s' is smaller "
729 "than the parent type's `%s' class size",
735 /* check instance size */
736 if (finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
)
738 if (info
->instance_size
< sizeof (GTypeInstance
))
740 g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
744 if (pnode
&& info
->instance_size
< pnode
->data
->instance
.instance_size
)
746 g_warning ("specified instance size for type `%s' is smaller "
747 "than the parent type's `%s' instance size",
758 find_conforming_child_type_L (TypeNode
*pnode
,
761 TypeNode
*node
= NULL
;
764 if (type_lookup_iface_entry_L (pnode
, iface
))
767 for (i
= 0; i
< pnode
->n_children
&& !node
; i
++)
768 node
= find_conforming_child_type_L (lookup_type_node_I (pnode
->children
[i
]), iface
);
774 check_add_interface_L (GType instance_type
,
777 TypeNode
*node
= lookup_type_node_I (instance_type
);
778 TypeNode
*iface
= lookup_type_node_I (iface_type
);
781 GType
*prerequisites
;
785 if (!node
|| !node
->is_instantiatable
)
787 g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
788 type_descriptive_name_I (instance_type
));
791 if (!iface
|| !NODE_IS_IFACE (iface
))
793 g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
794 type_descriptive_name_I (iface_type
),
798 tnode
= lookup_type_node_I (NODE_PARENT_TYPE (iface
));
799 if (NODE_PARENT_TYPE (tnode
) && !type_lookup_iface_entry_L (node
, tnode
))
801 /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
802 g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
808 /* allow overriding of interface type introduced for parent type */
809 entry
= type_lookup_iface_entry_L (node
, iface
);
810 if (entry
&& entry
->vtable
== NULL
&& !type_iface_peek_holder_L (iface
, NODE_TYPE (node
)))
812 /* ok, we do conform to this interface already, but the interface vtable was not
813 * yet intialized, and we just conform to the interface because it got added to
814 * one of our parents. so we allow overriding of holder info here.
818 /* check whether one of our children already conforms (or whether the interface
819 * got added to this node already)
821 tnode
= find_conforming_child_type_L (node
, iface
); /* tnode is_a node */
824 g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
830 prerequisites
= IFACE_NODE_PREREQUISITES (iface
);
831 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
833 tnode
= lookup_type_node_I (prerequisites
[i
]);
834 if (!type_node_is_a_L (node
, tnode
))
836 g_warning ("cannot add interface type `%s' to type `%s' which does not conform to prerequisite `%s'",
847 check_interface_info_I (TypeNode
*iface
,
849 const GInterfaceInfo
*info
)
851 if ((info
->interface_finalize
|| info
->interface_data
) && !info
->interface_init
)
853 g_warning ("interface type `%s' for type `%s' comes without initializer",
855 type_descriptive_name_I (instance_type
));
862 /* --- type info (type node data) --- */
864 type_data_make_W (TypeNode
*node
,
865 const GTypeInfo
*info
,
866 const GTypeValueTable
*value_table
)
869 GTypeValueTable
*vtable
= NULL
;
870 guint vtable_size
= 0;
872 g_assert (node
->data
== NULL
&& info
!= NULL
);
876 TypeNode
*pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
879 vtable
= pnode
->data
->common
.value_table
;
882 static const GTypeValueTable zero_vtable
= { NULL
, };
884 value_table
= &zero_vtable
;
889 /* need to setup vtable_size since we have to allocate it with data in one chunk */
890 vtable_size
= sizeof (GTypeValueTable
);
891 if (value_table
->collect_format
)
892 vtable_size
+= strlen (value_table
->collect_format
);
893 if (value_table
->lcopy_format
)
894 vtable_size
+= strlen (value_table
->lcopy_format
);
898 if (node
->is_instantiatable
) /* carefull, is_instantiatable is also is_classed */
900 data
= g_malloc0 (sizeof (InstanceData
) + vtable_size
);
902 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (InstanceData
));
903 data
->instance
.class_size
= info
->class_size
;
904 data
->instance
.class_init_base
= info
->base_init
;
905 data
->instance
.class_finalize_base
= info
->base_finalize
;
906 data
->instance
.class_init
= info
->class_init
;
907 data
->instance
.class_finalize
= info
->class_finalize
;
908 data
->instance
.class_data
= info
->class_data
;
909 data
->instance
.class = NULL
;
910 data
->instance
.instance_size
= info
->instance_size
;
911 #ifdef DISABLE_MEM_POOLS
912 data
->instance
.n_preallocs
= 0;
913 #else /* !DISABLE_MEM_POOLS */
914 data
->instance
.n_preallocs
= MIN (info
->n_preallocs
, 1024);
915 #endif /* !DISABLE_MEM_POOLS */
916 data
->instance
.instance_init
= info
->instance_init
;
917 data
->instance
.mem_chunk
= NULL
;
919 else if (node
->is_classed
) /* only classed */
921 data
= g_malloc0 (sizeof (ClassData
) + vtable_size
);
923 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (ClassData
));
924 data
->class.class_size
= info
->class_size
;
925 data
->class.class_init_base
= info
->base_init
;
926 data
->class.class_finalize_base
= info
->base_finalize
;
927 data
->class.class_init
= info
->class_init
;
928 data
->class.class_finalize
= info
->class_finalize
;
929 data
->class.class_data
= info
->class_data
;
930 data
->class.class = NULL
;
932 else if (NODE_IS_IFACE (node
))
934 data
= g_malloc0 (sizeof (IFaceData
) + vtable_size
);
936 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (IFaceData
));
937 data
->iface
.vtable_size
= info
->class_size
;
938 data
->iface
.vtable_init_base
= info
->base_init
;
939 data
->iface
.vtable_finalize_base
= info
->base_finalize
;
943 data
= g_malloc0 (sizeof (CommonData
) + vtable_size
);
945 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (CommonData
));
949 node
->data
->common
.ref_count
= 1;
955 /* we allocate the vtable and its strings together with the type data, so
956 * children can take over their parent's vtable pointer, and we don't
957 * need to worry freeing it or not when the child data is destroyed
959 *vtable
= *value_table
;
960 p
= G_STRUCT_MEMBER_P (vtable
, sizeof (*vtable
));
962 vtable
->collect_format
= p
;
963 if (value_table
->collect_format
)
965 strcat (p
, value_table
->collect_format
);
966 p
+= strlen (value_table
->collect_format
);
970 vtable
->lcopy_format
= p
;
971 if (value_table
->lcopy_format
)
972 strcat (p
, value_table
->lcopy_format
);
974 node
->data
->common
.value_table
= vtable
;
975 node
->mutatable_check_cache
= (node
->data
->common
.value_table
->value_init
!= NULL
&&
976 !((G_TYPE_FLAG_VALUE_ABSTRACT
| G_TYPE_FLAG_ABSTRACT
) &
977 GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
))));
979 g_assert (node
->data
->common
.value_table
!= NULL
); /* paranoid */
983 type_data_ref_Wm (TypeNode
*node
)
987 TypeNode
*pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
989 GTypeValueTable tmp_value_table
;
991 g_assert (node
->plugin
!= NULL
);
995 type_data_ref_Wm (pnode
);
997 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
1000 memset (&tmp_info
, 0, sizeof (tmp_info
));
1001 memset (&tmp_value_table
, 0, sizeof (tmp_value_table
));
1003 G_WRITE_UNLOCK (&type_rw_lock
);
1004 g_type_plugin_use (node
->plugin
);
1005 g_type_plugin_complete_type_info (node
->plugin
, NODE_TYPE (node
), &tmp_info
, &tmp_value_table
);
1006 G_WRITE_LOCK (&type_rw_lock
);
1008 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
1010 check_type_info_I (pnode
, NODE_FUNDAMENTAL_TYPE (node
), NODE_NAME (node
), &tmp_info
);
1011 type_data_make_W (node
, &tmp_info
,
1012 check_value_table_I (NODE_NAME (node
),
1013 &tmp_value_table
) ? &tmp_value_table
: NULL
);
1017 g_assert (node
->data
->common
.ref_count
> 0);
1019 node
->data
->common
.ref_count
+= 1;
1024 type_data_unref_Wm (TypeNode
*node
,
1027 g_assert (node
->data
&& node
->data
->common
.ref_count
);
1029 if (node
->data
->common
.ref_count
> 1)
1030 node
->data
->common
.ref_count
-= 1;
1035 g_warning ("static type `%s' unreferenced too often",
1040 type_data_last_unref_Wm (NODE_TYPE (node
), uncached
);
1045 type_node_add_iface_entry_W (TypeNode
*node
,
1048 IFaceEntry
*entries
;
1051 g_assert (node
->is_instantiatable
&& CLASSED_NODE_N_IFACES (node
) < MAX_N_IFACES
);
1053 entries
= CLASSED_NODE_IFACES_ENTRIES (node
);
1054 for (i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1055 if (entries
[i
].iface_type
== iface_type
)
1057 /* this can (should) only happen if our parent type already conformed
1058 * to iface_type and node got it's own holder info. here, our
1059 * children should already have entries with NULL vtables, so
1060 * we're actually done.
1062 g_assert (entries
[i
].vtable
== NULL
);
1065 else if (entries
[i
].iface_type
> iface_type
)
1067 CLASSED_NODE_N_IFACES (node
) += 1;
1068 CLASSED_NODE_IFACES_ENTRIES (node
) = g_renew (IFaceEntry
,
1069 CLASSED_NODE_IFACES_ENTRIES (node
),
1070 CLASSED_NODE_N_IFACES (node
));
1071 entries
= CLASSED_NODE_IFACES_ENTRIES (node
);
1072 g_memmove (entries
+ i
+ 1, entries
+ i
, sizeof (entries
[0]) * (CLASSED_NODE_N_IFACES (node
) - i
- 1));
1073 entries
[i
].iface_type
= iface_type
;
1074 entries
[i
].vtable
= NULL
;
1076 for (i
= 0; i
< node
->n_children
; i
++)
1077 type_node_add_iface_entry_W (lookup_type_node_I (node
->children
[i
]), iface_type
);
1081 type_add_interface_W (TypeNode
*node
,
1083 const GInterfaceInfo
*info
,
1084 GTypePlugin
*plugin
)
1086 IFaceHolder
*iholder
= g_new0 (IFaceHolder
, 1);
1088 /* we must not call any functions of GInterfaceInfo from within here, since
1089 * we got most probably called from _within_ a type registration function
1091 g_assert (node
->is_instantiatable
&& NODE_IS_IFACE (iface
) && ((info
&& !plugin
) || (!info
&& plugin
)));
1093 iholder
->next
= iface_node_get_holders_L (iface
);
1094 iface_node_set_holders_W (iface
, iholder
);
1095 iholder
->instance_type
= NODE_TYPE (node
);
1096 iholder
->info
= info
? g_memdup (info
, sizeof (*info
)) : NULL
;
1097 iholder
->plugin
= plugin
;
1099 type_node_add_iface_entry_W (node
, NODE_TYPE (iface
));
1103 type_iface_add_prerequisite_W (TypeNode
*iface
,
1104 TypeNode
*prerequisite_node
)
1106 GType prerequisite_type
= NODE_TYPE (prerequisite_node
);
1107 GType
*prerequisites
, *dependants
;
1108 guint n_dependants
, i
;
1110 g_assert (NODE_IS_IFACE (iface
) &&
1111 IFACE_NODE_N_PREREQUISITES (iface
) < MAX_N_PREREQUISITES
&&
1112 (prerequisite_node
->is_instantiatable
|| NODE_IS_IFACE (prerequisite_node
)));
1114 prerequisites
= IFACE_NODE_PREREQUISITES (iface
);
1115 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
1116 if (prerequisites
[i
] == prerequisite_type
)
1117 return; /* we already have that prerequisiste */
1118 else if (prerequisites
[i
] > prerequisite_type
)
1120 IFACE_NODE_N_PREREQUISITES (iface
) += 1;
1121 IFACE_NODE_PREREQUISITES (iface
) = g_renew (GType
,
1122 IFACE_NODE_PREREQUISITES (iface
),
1123 IFACE_NODE_N_PREREQUISITES (iface
));
1124 prerequisites
= IFACE_NODE_PREREQUISITES (iface
);
1125 g_memmove (prerequisites
+ i
+ 1, prerequisites
+ i
,
1126 sizeof (prerequisites
[0]) * (IFACE_NODE_N_PREREQUISITES (iface
) - i
- 1));
1127 prerequisites
[i
] = prerequisite_type
;
1129 /* we want to get notified when prerequisites get added to prerequisite_node */
1130 if (NODE_IS_IFACE (prerequisite_node
))
1132 dependants
= iface_node_get_dependants_array_L (prerequisite_node
);
1133 n_dependants
= dependants
? dependants
[0] : 0;
1135 dependants
= g_renew (GType
, dependants
, n_dependants
+ 1);
1136 dependants
[n_dependants
] = NODE_TYPE (iface
);
1137 dependants
[0] = n_dependants
;
1138 iface_node_set_dependants_array_W (prerequisite_node
, dependants
);
1141 /* we need to notify all dependants */
1142 dependants
= iface_node_get_dependants_array_L (iface
);
1143 n_dependants
= dependants
? dependants
[0] : 0;
1144 for (i
= 1; i
<= n_dependants
; i
++)
1145 type_iface_add_prerequisite_W (lookup_type_node_I (dependants
[i
]), prerequisite_node
);
1149 g_type_interface_add_prerequisite (GType interface_type
,
1150 GType prerequisite_type
)
1152 TypeNode
*iface
, *prerequisite_node
;
1153 IFaceHolder
*holders
;
1155 g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type
)); /* G_TYPE_IS_INTERFACE() is an external call: _U */
1156 g_return_if_fail (!g_type_is_a (interface_type
, prerequisite_type
));
1157 g_return_if_fail (!g_type_is_a (prerequisite_type
, interface_type
));
1159 iface
= lookup_type_node_I (interface_type
);
1160 prerequisite_node
= lookup_type_node_I (prerequisite_type
);
1161 if (!iface
|| !prerequisite_node
|| !NODE_IS_IFACE (iface
))
1163 g_warning ("interface type `%s' or prerequisite type `%s' invalid",
1164 type_descriptive_name_I (interface_type
),
1165 type_descriptive_name_I (prerequisite_type
));
1168 G_WRITE_LOCK (&type_rw_lock
);
1169 holders
= iface_node_get_holders_L (iface
);
1172 G_WRITE_UNLOCK (&type_rw_lock
);
1173 g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'",
1174 type_descriptive_name_I (prerequisite_type
),
1175 type_descriptive_name_I (interface_type
),
1176 type_descriptive_name_I (holders
->instance_type
));
1179 if (prerequisite_node
->is_instantiatable
)
1183 /* can have at most one publically installable instantiatable prerequisite */
1184 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
1186 TypeNode
*prnode
= lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface
)[i
]);
1188 if (prnode
->is_instantiatable
)
1190 G_WRITE_UNLOCK (&type_rw_lock
);
1191 g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
1192 type_descriptive_name_I (prerequisite_type
),
1193 type_descriptive_name_I (interface_type
),
1194 type_descriptive_name_I (NODE_TYPE (prnode
)));
1199 for (i
= 0; i
< prerequisite_node
->n_supers
+ 1; i
++)
1200 type_iface_add_prerequisite_W (iface
, lookup_type_node_I (prerequisite_node
->supers
[i
]));
1201 G_WRITE_UNLOCK (&type_rw_lock
);
1203 else if (NODE_IS_IFACE (prerequisite_node
))
1205 GType
*prerequisites
;
1208 prerequisites
= IFACE_NODE_PREREQUISITES (prerequisite_node
);
1209 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (prerequisite_node
); i
++)
1210 type_iface_add_prerequisite_W (iface
, lookup_type_node_I (prerequisites
[i
]));
1211 type_iface_add_prerequisite_W (iface
, prerequisite_node
);
1212 G_WRITE_UNLOCK (&type_rw_lock
);
1216 G_WRITE_UNLOCK (&type_rw_lock
);
1217 g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface",
1218 type_descriptive_name_I (prerequisite_type
),
1219 type_descriptive_name_I (interface_type
));
1224 * g_type_interface_prerequisites:
1225 * @interface_type: an interface type
1226 * @n_prerequisites: location to return the number of prerequisites, or %NULL
1228 * Returns the prerequisites of an interfaces type.
1230 * Return value: a newly-allocated zero-terminated array of #GType containing
1231 * the prerequisites of @interface_type
1233 GType
* /* free result */
1234 g_type_interface_prerequisites (GType interface_type
,
1235 guint
*n_prerequisites
)
1239 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type
), NULL
);
1241 iface
= lookup_type_node_I (interface_type
);
1244 GType
*prerequisites
;
1247 G_READ_LOCK (&type_rw_lock
);
1248 prerequisites
= g_new (GType
, IFACE_NODE_N_PREREQUISITES (iface
) + 1);
1249 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
1250 prerequisites
[i
] = IFACE_NODE_PREREQUISITES (iface
)[i
];
1251 prerequisites
[i
] = 0;
1253 if (n_prerequisites
)
1254 *n_prerequisites
= IFACE_NODE_N_PREREQUISITES (iface
);
1255 G_READ_UNLOCK (&type_rw_lock
);
1257 return prerequisites
;
1261 if (n_prerequisites
)
1262 *n_prerequisites
= 0;
1270 type_iface_peek_holder_L (TypeNode
*iface
,
1271 GType instance_type
)
1273 IFaceHolder
*iholder
;
1275 g_assert (NODE_IS_IFACE (iface
));
1277 iholder
= iface_node_get_holders_L (iface
);
1278 while (iholder
&& iholder
->instance_type
!= instance_type
)
1279 iholder
= iholder
->next
;
1284 type_iface_retrieve_holder_info_Wm (TypeNode
*iface
,
1285 GType instance_type
,
1288 IFaceHolder
*iholder
= type_iface_peek_holder_L (iface
, instance_type
);
1290 if (iholder
&& !iholder
->info
&& need_info
)
1292 GInterfaceInfo tmp_info
;
1294 g_assert (iholder
->plugin
!= NULL
);
1296 type_data_ref_Wm (iface
);
1298 INVALID_RECURSION ("g_type_plugin_*", iface
->plugin
, NODE_NAME (iface
));
1300 memset (&tmp_info
, 0, sizeof (tmp_info
));
1302 G_WRITE_UNLOCK (&type_rw_lock
);
1303 g_type_plugin_use (iholder
->plugin
);
1304 g_type_plugin_complete_interface_info (iholder
->plugin
, instance_type
, NODE_TYPE (iface
), &tmp_info
);
1305 G_WRITE_LOCK (&type_rw_lock
);
1307 INVALID_RECURSION ("g_type_plugin_*", iholder
->plugin
, NODE_NAME (iface
));
1309 check_interface_info_I (iface
, instance_type
, &tmp_info
);
1310 iholder
->info
= g_memdup (&tmp_info
, sizeof (tmp_info
));
1313 return iholder
; /* we don't modify write lock upon returning NULL */
1317 type_iface_blow_holder_info_Wm (TypeNode
*iface
,
1318 GType instance_type
)
1320 IFaceHolder
*iholder
= iface_node_get_holders_L (iface
);
1322 g_assert (NODE_IS_IFACE (iface
));
1324 while (iholder
->instance_type
!= instance_type
)
1325 iholder
= iholder
->next
;
1327 if (iholder
->info
&& iholder
->plugin
)
1329 g_free (iholder
->info
);
1330 iholder
->info
= NULL
;
1332 G_WRITE_UNLOCK (&type_rw_lock
);
1333 g_type_plugin_unuse (iholder
->plugin
);
1334 G_WRITE_LOCK (&type_rw_lock
);
1336 type_data_unref_Wm (iface
, FALSE
);
1341 /* --- type structure creation/destruction --- */
1343 g_type_create_instance (GType type
)
1346 GTypeInstance
*instance
;
1350 node
= lookup_type_node_I (type
);
1351 if (!node
|| !node
->is_instantiatable
)
1353 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1354 type_descriptive_name_I (type
));
1357 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1358 if (!node
->mutatable_check_cache
&& G_TYPE_IS_ABSTRACT (type
))
1360 g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1361 type_descriptive_name_I (type
));
1365 class = g_type_class_ref (type
);
1367 if (node
->data
->instance
.n_preallocs
)
1369 G_WRITE_LOCK (&type_rw_lock
);
1370 if (!node
->data
->instance
.mem_chunk
)
1371 node
->data
->instance
.mem_chunk
= g_mem_chunk_new (NODE_NAME (node
),
1372 node
->data
->instance
.instance_size
,
1373 (node
->data
->instance
.instance_size
*
1374 node
->data
->instance
.n_preallocs
),
1376 instance
= g_chunk_new0 (GTypeInstance
, node
->data
->instance
.mem_chunk
);
1377 G_WRITE_UNLOCK (&type_rw_lock
);
1380 instance
= g_malloc0 (node
->data
->instance
.instance_size
); /* fine without read lock */
1381 for (i
= node
->n_supers
; i
> 0; i
--)
1385 pnode
= lookup_type_node_I (node
->supers
[i
]);
1386 if (pnode
->data
->instance
.instance_init
)
1388 instance
->g_class
= pnode
->data
->instance
.class;
1389 pnode
->data
->instance
.instance_init (instance
, class);
1392 instance
->g_class
= class;
1394 if (node
->data
->instance
.instance_init
)
1395 node
->data
->instance
.instance_init (instance
, class);
1401 g_type_free_instance (GTypeInstance
*instance
)
1406 g_return_if_fail (instance
!= NULL
&& instance
->g_class
!= NULL
);
1408 class = instance
->g_class
;
1409 node
= lookup_type_node_I (class->g_type
);
1410 if (!node
|| !node
->is_instantiatable
|| !node
->data
|| node
->data
->class.class != (gpointer
) class)
1412 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1413 type_descriptive_name_I (class->g_type
));
1416 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1417 if (!node
->mutatable_check_cache
&& G_TYPE_IS_ABSTRACT (NODE_TYPE (node
)))
1419 g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1424 instance
->g_class
= NULL
;
1425 #ifdef G_ENABLE_DEBUG
1426 memset (instance
, 0xaa, node
->data
->instance
.instance_size
); /* debugging hack */
1428 if (node
->data
->instance
.n_preallocs
)
1430 G_WRITE_LOCK (&type_rw_lock
);
1431 g_chunk_free (instance
, node
->data
->instance
.mem_chunk
);
1432 G_WRITE_UNLOCK (&type_rw_lock
);
1437 g_type_class_unref (class);
1441 type_iface_vtable_init_Wm (TypeNode
*iface
,
1444 IFaceEntry
*entry
= type_lookup_iface_entry_L (node
, iface
);
1445 IFaceHolder
*iholder
;
1446 GTypeInterface
*vtable
= NULL
;
1449 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1450 iholder
= type_iface_retrieve_holder_info_Wm (iface
, NODE_TYPE (node
), TRUE
);
1452 return FALSE
; /* we don't modify write lock upon FALSE */
1454 g_assert (iface
->data
&& entry
&& entry
->vtable
== NULL
&& iholder
&& iholder
->info
);
1456 pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
1457 if (pnode
) /* want to copy over parent iface contents */
1459 IFaceEntry
*pentry
= type_lookup_iface_entry_L (pnode
, iface
);
1462 vtable
= g_memdup (pentry
->vtable
, iface
->data
->iface
.vtable_size
);
1465 vtable
= g_malloc0 (iface
->data
->iface
.vtable_size
);
1466 entry
->vtable
= vtable
;
1467 vtable
->g_type
= NODE_TYPE (iface
);
1468 vtable
->g_instance_type
= NODE_TYPE (node
);
1470 if (iface
->data
->iface
.vtable_init_base
|| iholder
->info
->interface_init
)
1472 G_WRITE_UNLOCK (&type_rw_lock
);
1473 if (iface
->data
->iface
.vtable_init_base
)
1474 iface
->data
->iface
.vtable_init_base (vtable
);
1475 if (iholder
->info
->interface_init
)
1476 iholder
->info
->interface_init (vtable
, iholder
->info
->interface_data
);
1477 G_WRITE_LOCK (&type_rw_lock
);
1479 return TRUE
; /* write lock modified */
1483 type_iface_vtable_finalize_Wm (TypeNode
*iface
,
1485 GTypeInterface
*vtable
)
1487 IFaceEntry
*entry
= type_lookup_iface_entry_L (node
, iface
);
1488 IFaceHolder
*iholder
;
1490 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1491 iholder
= type_iface_retrieve_holder_info_Wm (iface
, NODE_TYPE (node
), FALSE
);
1493 return FALSE
; /* we don't modify write lock upon FALSE */
1495 g_assert (entry
&& entry
->vtable
== vtable
&& iholder
->info
);
1497 entry
->vtable
= NULL
;
1498 if (iholder
->info
->interface_finalize
|| iface
->data
->iface
.vtable_finalize_base
)
1500 G_WRITE_UNLOCK (&type_rw_lock
);
1501 if (iholder
->info
->interface_finalize
)
1502 iholder
->info
->interface_finalize (vtable
, iholder
->info
->interface_data
);
1503 if (iface
->data
->iface
.vtable_finalize_base
)
1504 iface
->data
->iface
.vtable_finalize_base (vtable
);
1505 G_WRITE_LOCK (&type_rw_lock
);
1508 vtable
->g_instance_type
= 0;
1511 type_iface_blow_holder_info_Wm (iface
, NODE_TYPE (node
));
1513 return TRUE
; /* write lock modified */
1517 type_class_init_Wm (TypeNode
*node
,
1520 GSList
*slist
, *init_slist
= NULL
;
1523 TypeNode
*bnode
, *pnode
;
1526 g_assert (node
->is_classed
&& node
->data
&&
1527 node
->data
->class.class_size
&&
1528 !node
->data
->class.class);
1530 class = g_malloc0 (node
->data
->class.class_size
);
1531 node
->data
->class.class = class;
1535 TypeNode
*pnode
= lookup_type_node_I (pclass
->g_type
);
1537 memcpy (class, pclass
, pnode
->data
->class.class_size
);
1539 class->g_type
= NODE_TYPE (node
);
1541 G_WRITE_UNLOCK (&type_rw_lock
);
1543 /* stack all base class initialization functions, so we
1544 * call them in ascending order.
1546 for (bnode
= node
; bnode
; bnode
= lookup_type_node_I (NODE_PARENT_TYPE (bnode
)))
1547 if (bnode
->data
->class.class_init_base
)
1548 init_slist
= g_slist_prepend (init_slist
, (gpointer
) bnode
->data
->class.class_init_base
);
1549 for (slist
= init_slist
; slist
; slist
= slist
->next
)
1551 GBaseInitFunc class_init_base
= (GBaseInitFunc
) slist
->data
;
1553 class_init_base (class);
1555 g_slist_free (init_slist
);
1557 if (node
->data
->class.class_init
)
1558 node
->data
->class.class_init (class, (gpointer
) node
->data
->class.class_data
);
1560 G_WRITE_LOCK (&type_rw_lock
);
1562 /* ok, we got the class done, now initialize all interfaces, either
1563 * from parent, or through our holder info
1565 pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
1566 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + 0;
1569 g_assert (entry
->vtable
== NULL
);
1571 if (!type_iface_vtable_init_Wm (lookup_type_node_I (entry
->iface_type
), node
))
1575 /* type_iface_vtable_init_Wm() doesn't modify write lock upon FALSE,
1576 * need to get this interface from parent
1578 g_assert (pnode
!= NULL
);
1580 for (j
= 0; j
< CLASSED_NODE_N_IFACES (pnode
); j
++)
1582 IFaceEntry
*pentry
= CLASSED_NODE_IFACES_ENTRIES (pnode
) + j
;
1584 if (pentry
->iface_type
== entry
->iface_type
)
1586 entry
->vtable
= pentry
->vtable
;
1590 g_assert (entry
->vtable
!= NULL
);
1593 /* refetch entry, IFACES_ENTRIES might be modified */
1594 for (entry
= NULL
, i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1595 if (!CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
)
1596 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + i
;
1601 type_data_finalize_class_ifaces_Wm (TypeNode
*node
)
1606 g_assert (node
->is_instantiatable
&& node
->data
&& node
->data
->class.class && node
->data
->common
.ref_count
== 0);
1608 g_message ("finalizing interfaces for %sClass `%s'",
1609 type_descriptive_name_I (NODE_FUNDAMENTAL_TYPE (node
)),
1610 type_descriptive_name_I (NODE_TYPE (node
)));
1612 for (entry
= NULL
, i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1613 if (CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
&&
1614 CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
->g_instance_type
== NODE_TYPE (node
))
1615 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + i
;
1618 if (!type_iface_vtable_finalize_Wm (lookup_type_node_I (entry
->iface_type
), node
, entry
->vtable
))
1620 /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
1621 * iface vtable came from parent
1623 entry
->vtable
= NULL
;
1626 /* refetch entry, IFACES_ENTRIES might be modified */
1627 for (entry
= NULL
, i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1628 if (CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
&&
1629 CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
->g_instance_type
== NODE_TYPE (node
))
1630 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + i
;
1635 type_data_finalize_class_U (TypeNode
*node
,
1638 GTypeClass
*class = cdata
->class;
1641 g_assert (cdata
->class && cdata
->common
.ref_count
== 0);
1643 if (cdata
->class_finalize
)
1644 cdata
->class_finalize (class, (gpointer
) cdata
->class_data
);
1646 /* call all base class destruction functions in descending order
1648 if (cdata
->class_finalize_base
)
1649 cdata
->class_finalize_base (class);
1650 for (bnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
)); bnode
; bnode
= lookup_type_node_I (NODE_PARENT_TYPE (bnode
)))
1651 if (bnode
->data
->class.class_finalize_base
)
1652 bnode
->data
->class.class_finalize_base (class);
1655 g_free (cdata
->class);
1659 type_data_last_unref_Wm (GType type
,
1662 TypeNode
*node
= lookup_type_node_I (type
);
1664 g_return_if_fail (node
!= NULL
&& node
->plugin
!= NULL
);
1666 if (!node
->data
|| node
->data
->common
.ref_count
== 0)
1668 g_warning ("cannot drop last reference to unreferenced type `%s'",
1669 type_descriptive_name_I (type
));
1673 if (node
->is_classed
&& node
->data
&& node
->data
->class.class && static_n_class_cache_funcs
)
1677 G_WRITE_UNLOCK (&type_rw_lock
);
1678 G_READ_LOCK (&type_rw_lock
);
1679 for (i
= 0; i
< static_n_class_cache_funcs
; i
++)
1681 GTypeClassCacheFunc cache_func
= static_class_cache_funcs
[i
].cache_func
;
1682 gpointer cache_data
= static_class_cache_funcs
[i
].cache_data
;
1683 gboolean need_break
;
1685 G_READ_UNLOCK (&type_rw_lock
);
1686 need_break
= cache_func (cache_data
, node
->data
->class.class);
1687 G_READ_LOCK (&type_rw_lock
);
1688 if (!node
->data
|| node
->data
->common
.ref_count
== 0)
1689 INVALID_RECURSION ("GType class cache function ", cache_func
, NODE_NAME (node
));
1693 G_READ_UNLOCK (&type_rw_lock
);
1694 G_WRITE_LOCK (&type_rw_lock
);
1697 if (node
->data
->common
.ref_count
> 1) /* may have been re-referenced meanwhile */
1698 node
->data
->common
.ref_count
-= 1;
1701 GType ptype
= NODE_PARENT_TYPE (node
);
1704 node
->data
->common
.ref_count
= 0;
1706 if (node
->is_instantiatable
&& node
->data
->instance
.mem_chunk
)
1708 g_mem_chunk_destroy (node
->data
->instance
.mem_chunk
);
1709 node
->data
->instance
.mem_chunk
= NULL
;
1713 if (node
->is_classed
&& tdata
->class.class)
1715 if (CLASSED_NODE_N_IFACES (node
))
1716 type_data_finalize_class_ifaces_Wm (node
);
1717 node
->mutatable_check_cache
= FALSE
;
1719 G_WRITE_UNLOCK (&type_rw_lock
);
1720 type_data_finalize_class_U (node
, &tdata
->class);
1721 G_WRITE_LOCK (&type_rw_lock
);
1725 node
->mutatable_check_cache
= FALSE
;
1729 /* freeing tdata->common.value_table and its contents is taking care of
1730 * by allocating it in one chunk with tdata
1735 type_data_unref_Wm (lookup_type_node_I (ptype
), FALSE
);
1736 G_WRITE_UNLOCK (&type_rw_lock
);
1737 g_type_plugin_unuse (node
->plugin
);
1738 G_WRITE_LOCK (&type_rw_lock
);
1743 g_type_add_class_cache_func (gpointer cache_data
,
1744 GTypeClassCacheFunc cache_func
)
1748 g_return_if_fail (cache_func
!= NULL
);
1750 G_WRITE_LOCK (&type_rw_lock
);
1751 i
= static_n_class_cache_funcs
++;
1752 static_class_cache_funcs
= g_renew (ClassCacheFunc
, static_class_cache_funcs
, static_n_class_cache_funcs
);
1753 static_class_cache_funcs
[i
].cache_data
= cache_data
;
1754 static_class_cache_funcs
[i
].cache_func
= cache_func
;
1755 G_WRITE_UNLOCK (&type_rw_lock
);
1759 g_type_remove_class_cache_func (gpointer cache_data
,
1760 GTypeClassCacheFunc cache_func
)
1762 gboolean found_it
= FALSE
;
1765 g_return_if_fail (cache_func
!= NULL
);
1767 G_WRITE_LOCK (&type_rw_lock
);
1768 for (i
= 0; i
< static_n_class_cache_funcs
; i
++)
1769 if (static_class_cache_funcs
[i
].cache_data
== cache_data
&&
1770 static_class_cache_funcs
[i
].cache_func
== cache_func
)
1772 static_n_class_cache_funcs
--;
1773 g_memmove (static_class_cache_funcs
+ i
,
1774 static_class_cache_funcs
+ i
+ 1,
1775 sizeof (static_class_cache_funcs
[0]) * (static_n_class_cache_funcs
- i
));
1776 static_class_cache_funcs
= g_renew (ClassCacheFunc
, static_class_cache_funcs
, static_n_class_cache_funcs
);
1780 G_WRITE_UNLOCK (&type_rw_lock
);
1783 g_warning (G_STRLOC
": cannot remove unregistered class cache func %p with data %p",
1784 cache_func
, cache_data
);
1788 /* --- type registration --- */
1790 g_type_register_fundamental (GType type_id
,
1791 const gchar
*type_name
,
1792 const GTypeInfo
*info
,
1793 const GTypeFundamentalInfo
*finfo
,
1796 GTypeFundamentalInfo
*node_finfo
;
1799 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
1800 g_return_val_if_fail (type_id
> 0, 0);
1801 g_return_val_if_fail (type_name
!= NULL
, 0);
1802 g_return_val_if_fail (info
!= NULL
, 0);
1803 g_return_val_if_fail (finfo
!= NULL
, 0);
1805 if (!check_type_name_I (type_name
))
1807 if ((type_id
& TYPE_ID_MASK
) ||
1808 type_id
> G_TYPE_FUNDAMENTAL_MAX
)
1810 g_warning ("attempt to register fundamental type `%s' with invalid type id (%lu)",
1815 if ((finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) &&
1816 !(finfo
->type_flags
& G_TYPE_FLAG_CLASSED
))
1818 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1822 if (lookup_type_node_I (type_id
))
1824 g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1825 type_descriptive_name_I (type_id
),
1830 G_WRITE_LOCK (&type_rw_lock
);
1831 node
= type_node_fundamental_new_W (type_id
, type_name
, finfo
->type_flags
);
1832 node_finfo
= type_node_fundamental_info_I (node
);
1833 type_add_flags_W (node
, flags
);
1835 if (check_type_info_I (NULL
, NODE_FUNDAMENTAL_TYPE (node
), type_name
, info
))
1836 type_data_make_W (node
, info
,
1837 check_value_table_I (type_name
, info
->value_table
) ? info
->value_table
: NULL
);
1838 G_WRITE_UNLOCK (&type_rw_lock
);
1840 return NODE_TYPE (node
);
1844 g_type_register_static (GType parent_type
,
1845 const gchar
*type_name
,
1846 const GTypeInfo
*info
,
1849 TypeNode
*pnode
, *node
;
1852 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
1853 g_return_val_if_fail (parent_type
> 0, 0);
1854 g_return_val_if_fail (type_name
!= NULL
, 0);
1855 g_return_val_if_fail (info
!= NULL
, 0);
1857 if (!check_type_name_I (type_name
) ||
1858 !check_derivation_I (parent_type
, type_name
))
1860 if (info
->class_finalize
)
1862 g_warning ("class finalizer specified for static type `%s'",
1867 pnode
= lookup_type_node_I (parent_type
);
1868 G_WRITE_LOCK (&type_rw_lock
);
1869 type_data_ref_Wm (pnode
);
1870 if (check_type_info_I (pnode
, NODE_FUNDAMENTAL_TYPE (pnode
), type_name
, info
))
1872 node
= type_node_new_W (pnode
, type_name
, NULL
);
1873 type_add_flags_W (node
, flags
);
1874 type
= NODE_TYPE (node
);
1875 type_data_make_W (node
, info
,
1876 check_value_table_I (type_name
, info
->value_table
) ? info
->value_table
: NULL
);
1878 G_WRITE_UNLOCK (&type_rw_lock
);
1884 g_type_register_dynamic (GType parent_type
,
1885 const gchar
*type_name
,
1886 GTypePlugin
*plugin
,
1889 TypeNode
*pnode
, *node
;
1892 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
1893 g_return_val_if_fail (parent_type
> 0, 0);
1894 g_return_val_if_fail (type_name
!= NULL
, 0);
1895 g_return_val_if_fail (plugin
!= NULL
, 0);
1897 if (!check_type_name_I (type_name
) ||
1898 !check_derivation_I (parent_type
, type_name
) ||
1899 !check_plugin_U (plugin
, TRUE
, FALSE
, type_name
))
1902 G_WRITE_LOCK (&type_rw_lock
);
1903 pnode
= lookup_type_node_I (parent_type
);
1904 node
= type_node_new_W (pnode
, type_name
, plugin
);
1905 type_add_flags_W (node
, flags
);
1906 type
= NODE_TYPE (node
);
1907 G_WRITE_UNLOCK (&type_rw_lock
);
1913 g_type_add_interface_static (GType instance_type
,
1914 GType interface_type
,
1915 const GInterfaceInfo
*info
)
1917 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1918 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type
));
1919 g_return_if_fail (g_type_parent (interface_type
) == G_TYPE_INTERFACE
);
1921 G_WRITE_LOCK (&type_rw_lock
);
1922 if (check_add_interface_L (instance_type
, interface_type
))
1924 TypeNode
*node
= lookup_type_node_I (instance_type
);
1925 TypeNode
*iface
= lookup_type_node_I (interface_type
);
1927 if (check_interface_info_I (iface
, NODE_TYPE (node
), info
))
1929 type_add_interface_W (node
, iface
, info
, NULL
);
1930 /* if we have a class already, the interface vtable needs to
1931 * be initialized as well
1933 if (node
->data
&& node
->data
->class.class)
1934 type_iface_vtable_init_Wm (iface
, node
);
1937 G_WRITE_UNLOCK (&type_rw_lock
);
1941 g_type_add_interface_dynamic (GType instance_type
,
1942 GType interface_type
,
1943 GTypePlugin
*plugin
)
1947 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1948 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type
));
1949 g_return_if_fail (g_type_parent (interface_type
) == G_TYPE_INTERFACE
);
1951 node
= lookup_type_node_I (instance_type
);
1952 if (!check_plugin_U (plugin
, FALSE
, TRUE
, NODE_NAME (node
)))
1955 G_WRITE_LOCK (&type_rw_lock
);
1956 if (check_add_interface_L (instance_type
, interface_type
))
1958 TypeNode
*iface
= lookup_type_node_I (interface_type
);
1960 type_add_interface_W (node
, iface
, NULL
, plugin
);
1961 /* if we have a class already, the interface vtable needs to
1962 * be initialized as well
1964 if (node
->data
&& node
->data
->class.class)
1965 type_iface_vtable_init_Wm (iface
, node
);
1967 G_WRITE_UNLOCK (&type_rw_lock
);
1971 /* --- public API functions --- */
1973 g_type_class_ref (GType type
)
1977 /* optimize for common code path
1979 G_WRITE_LOCK (&type_rw_lock
);
1980 node
= lookup_type_node_I (type
);
1981 if (node
&& node
->is_classed
&& node
->data
&&
1982 node
->data
->class.class && node
->data
->common
.ref_count
> 0)
1984 type_data_ref_Wm (node
);
1985 G_WRITE_UNLOCK (&type_rw_lock
);
1987 return node
->data
->class.class;
1990 if (!node
|| !node
->is_classed
||
1991 (node
->data
&& node
->data
->common
.ref_count
< 1))
1993 G_WRITE_UNLOCK (&type_rw_lock
);
1994 g_warning ("cannot retrieve class for invalid (unclassed) type `%s'",
1995 type_descriptive_name_I (type
));
1999 type_data_ref_Wm (node
);
2001 if (!node
->data
->class.class)
2003 GType ptype
= NODE_PARENT_TYPE (node
);
2004 GTypeClass
*pclass
= NULL
;
2008 G_WRITE_UNLOCK (&type_rw_lock
);
2009 pclass
= g_type_class_ref (ptype
);
2010 if (node
->data
->class.class)
2011 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
2012 G_WRITE_LOCK (&type_rw_lock
);
2015 type_class_init_Wm (node
, pclass
);
2017 G_WRITE_UNLOCK (&type_rw_lock
);
2019 return node
->data
->class.class;
2023 g_type_class_unref (gpointer g_class
)
2026 GTypeClass
*class = g_class
;
2028 g_return_if_fail (g_class
!= NULL
);
2030 node
= lookup_type_node_I (class->g_type
);
2031 G_WRITE_LOCK (&type_rw_lock
);
2032 if (node
&& node
->is_classed
&& node
->data
&&
2033 node
->data
->class.class == class && node
->data
->common
.ref_count
> 0)
2034 type_data_unref_Wm (node
, FALSE
);
2036 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2037 type_descriptive_name_I (class->g_type
));
2038 G_WRITE_UNLOCK (&type_rw_lock
);
2042 g_type_class_unref_uncached (gpointer g_class
)
2045 GTypeClass
*class = g_class
;
2047 g_return_if_fail (g_class
!= NULL
);
2049 G_WRITE_LOCK (&type_rw_lock
);
2050 node
= lookup_type_node_I (class->g_type
);
2051 if (node
&& node
->is_classed
&& node
->data
&&
2052 node
->data
->class.class == class && node
->data
->common
.ref_count
> 0)
2053 type_data_unref_Wm (node
, TRUE
);
2055 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2056 type_descriptive_name_I (class->g_type
));
2057 G_WRITE_UNLOCK (&type_rw_lock
);
2061 g_type_class_peek (GType type
)
2066 node
= lookup_type_node_I (type
);
2067 G_READ_LOCK (&type_rw_lock
);
2068 if (node
&& node
->is_classed
&& node
->data
&& node
->data
->class.class) /* common.ref_count _may_ be 0 */
2069 class = node
->data
->class.class;
2072 G_READ_UNLOCK (&type_rw_lock
);
2078 g_type_class_peek_parent (gpointer g_class
)
2081 gpointer
class = NULL
;
2083 g_return_val_if_fail (g_class
!= NULL
, NULL
);
2085 node
= lookup_type_node_I (G_TYPE_FROM_CLASS (g_class
));
2086 G_READ_LOCK (&type_rw_lock
);
2087 if (node
&& node
->is_classed
&& node
->data
&& NODE_PARENT_TYPE (node
))
2089 node
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
2090 class = node
->data
->class.class;
2092 else if (NODE_PARENT_TYPE (node
))
2093 g_warning (G_STRLOC
": invalid class pointer `%p'", g_class
);
2094 G_READ_UNLOCK (&type_rw_lock
);
2100 g_type_interface_peek (gpointer instance_class
,
2105 gpointer vtable
= NULL
;
2106 GTypeClass
*class = instance_class
;
2108 g_return_val_if_fail (instance_class
!= NULL
, NULL
);
2110 node
= lookup_type_node_I (class->g_type
);
2111 iface
= lookup_type_node_I (iface_type
);
2112 if (node
&& node
->is_instantiatable
&& iface
)
2116 G_READ_LOCK (&type_rw_lock
);
2118 entry
= type_lookup_iface_entry_L (node
, iface
);
2119 if (entry
&& entry
->vtable
) /* entry is relocatable */
2120 vtable
= entry
->vtable
;
2122 G_READ_UNLOCK (&type_rw_lock
);
2125 g_warning (G_STRLOC
": invalid class pointer `%p'", class);
2131 g_type_interface_peek_parent (gpointer g_iface
)
2135 gpointer vtable
= NULL
;
2136 GTypeInterface
*iface_class
= g_iface
;
2138 g_return_val_if_fail (g_iface
!= NULL
, NULL
);
2140 iface
= lookup_type_node_I (iface_class
->g_type
);
2141 node
= lookup_type_node_I (iface_class
->g_instance_type
);
2143 node
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
2144 if (node
&& node
->is_instantiatable
&& iface
)
2148 G_READ_LOCK (&type_rw_lock
);
2150 entry
= type_lookup_iface_entry_L (node
, iface
);
2151 if (entry
&& entry
->vtable
) /* entry is relocatable */
2152 vtable
= entry
->vtable
;
2154 G_READ_UNLOCK (&type_rw_lock
);
2157 g_warning (G_STRLOC
": invalid interface pointer `%p'", g_iface
);
2162 G_CONST_RETURN gchar
*
2163 g_type_name (GType type
)
2167 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, NULL
);
2169 node
= lookup_type_node_I (type
);
2171 return node
? NODE_NAME (node
) : NULL
;
2175 g_type_qname (GType type
)
2179 node
= lookup_type_node_I (type
);
2181 return node
? node
->qname
: 0;
2185 g_type_from_name (const gchar
*name
)
2190 g_return_val_if_fail (name
!= NULL
, 0);
2192 quark
= g_quark_try_string (name
);
2195 G_READ_LOCK (&type_rw_lock
);
2196 type
= (GType
) g_hash_table_lookup (static_type_nodes_ht
, GUINT_TO_POINTER (quark
));
2197 G_READ_UNLOCK (&type_rw_lock
);
2204 g_type_parent (GType type
)
2208 node
= lookup_type_node_I (type
);
2210 return node
? NODE_PARENT_TYPE (node
) : 0;
2214 g_type_depth (GType type
)
2218 node
= lookup_type_node_I (type
);
2220 return node
? node
->n_supers
+ 1 : 0;
2224 g_type_next_base (GType type
,
2230 node
= lookup_type_node_I (type
);
2233 TypeNode
*base_node
= lookup_type_node_I (base_type
);
2235 if (base_node
&& base_node
->n_supers
< node
->n_supers
)
2237 guint n
= node
->n_supers
- base_node
->n_supers
;
2239 if (node
->supers
[n
] == base_type
)
2240 atype
= node
->supers
[n
- 1];
2247 static inline gboolean
2248 type_node_check_conformities_UorL (TypeNode
*node
,
2249 TypeNode
*iface_node
,
2250 /* support_inheritance */
2251 gboolean support_interfaces
,
2252 gboolean support_prerequisites
,
2257 if (/* support_inheritance && */
2258 iface_node
->n_supers
<= node
->n_supers
&&
2259 node
->supers
[node
->n_supers
- iface_node
->n_supers
] == NODE_TYPE (iface_node
))
2262 support_interfaces
= support_interfaces
&& node
->is_instantiatable
&& NODE_IS_IFACE (iface_node
);
2263 support_prerequisites
= support_prerequisites
&& NODE_IS_IFACE (node
);
2265 if (support_interfaces
|| support_prerequisites
)
2268 G_READ_LOCK (&type_rw_lock
);
2269 if (support_interfaces
&& type_lookup_iface_entry_L (node
, iface_node
))
2271 else if (support_prerequisites
&& type_lookup_prerequisite_L (node
, NODE_TYPE (iface_node
)))
2274 G_READ_UNLOCK (&type_rw_lock
);
2280 type_node_is_a_L (TypeNode
*node
,
2281 TypeNode
*iface_node
)
2283 return type_node_check_conformities_UorL (node
, iface_node
, TRUE
, TRUE
, TRUE
);
2286 static inline gboolean
2287 type_node_conforms_to_U (TypeNode
*node
,
2288 TypeNode
*iface_node
,
2289 gboolean support_interfaces
,
2290 gboolean support_prerequisites
)
2292 return type_node_check_conformities_UorL (node
, iface_node
, support_interfaces
, support_prerequisites
, FALSE
);
2296 g_type_is_a (GType type
,
2299 TypeNode
*node
, *iface_node
;
2302 node
= lookup_type_node_I (type
);
2303 iface_node
= lookup_type_node_I (iface_type
);
2304 is_a
= node
&& iface_node
&& type_node_conforms_to_U (node
, iface_node
, TRUE
, TRUE
);
2309 GType
* /* free result */
2310 g_type_children (GType type
,
2315 node
= lookup_type_node_I (type
);
2320 G_READ_LOCK (&type_rw_lock
); /* ->children is relocatable */
2321 children
= g_new (GType
, node
->n_children
+ 1);
2322 memcpy (children
, node
->children
, sizeof (GType
) * node
->n_children
);
2323 children
[node
->n_children
] = 0;
2326 *n_children
= node
->n_children
;
2327 G_READ_UNLOCK (&type_rw_lock
);
2340 GType
* /* free result */
2341 g_type_interfaces (GType type
,
2342 guint
*n_interfaces
)
2346 node
= lookup_type_node_I (type
);
2347 if (node
&& node
->is_instantiatable
)
2352 G_READ_LOCK (&type_rw_lock
);
2353 ifaces
= g_new (GType
, CLASSED_NODE_N_IFACES (node
) + 1);
2354 for (i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
2355 ifaces
[i
] = CLASSED_NODE_IFACES_ENTRIES (node
)[i
].iface_type
;
2359 *n_interfaces
= CLASSED_NODE_N_IFACES (node
);
2360 G_READ_UNLOCK (&type_rw_lock
);
2373 typedef struct _QData QData
;
2385 static inline gpointer
2386 type_get_qdata_L (TypeNode
*node
,
2389 GData
*gdata
= node
->global_gdata
;
2391 if (quark
&& gdata
&& gdata
->n_qdatas
)
2393 QData
*qdatas
= gdata
->qdatas
- 1;
2394 guint n_qdatas
= gdata
->n_qdatas
;
2401 i
= (n_qdatas
+ 1) / 2;
2403 if (quark
== check
->quark
)
2405 else if (quark
> check
->quark
)
2410 else /* if (quark < check->quark) */
2419 g_type_get_qdata (GType type
,
2425 node
= lookup_type_node_I (type
);
2428 G_READ_LOCK (&type_rw_lock
);
2429 data
= type_get_qdata_L (node
, quark
);
2430 G_READ_UNLOCK (&type_rw_lock
);
2434 g_return_val_if_fail (node
!= NULL
, NULL
);
2441 type_set_qdata_W (TypeNode
*node
,
2449 /* setup qdata list if necessary */
2450 if (!node
->global_gdata
)
2451 node
->global_gdata
= g_new0 (GData
, 1);
2452 gdata
= node
->global_gdata
;
2454 /* try resetting old data */
2455 qdata
= gdata
->qdatas
;
2456 for (i
= 0; i
< gdata
->n_qdatas
; i
++)
2457 if (qdata
[i
].quark
== quark
)
2459 qdata
[i
].data
= data
;
2465 gdata
->qdatas
= g_renew (QData
, gdata
->qdatas
, gdata
->n_qdatas
);
2466 qdata
= gdata
->qdatas
;
2467 for (i
= 0; i
< gdata
->n_qdatas
- 1; i
++)
2468 if (qdata
[i
].quark
> quark
)
2470 g_memmove (qdata
+ i
+ 1, qdata
+ i
, sizeof (qdata
[0]) * (gdata
->n_qdatas
- i
- 1));
2471 qdata
[i
].quark
= quark
;
2472 qdata
[i
].data
= data
;
2476 g_type_set_qdata (GType type
,
2482 g_return_if_fail (quark
!= 0);
2484 node
= lookup_type_node_I (type
);
2487 G_WRITE_LOCK (&type_rw_lock
);
2488 type_set_qdata_W (node
, quark
, data
);
2489 G_WRITE_UNLOCK (&type_rw_lock
);
2492 g_return_if_fail (node
!= NULL
);
2496 type_add_flags_W (TypeNode
*node
,
2501 g_return_if_fail ((flags
& ~TYPE_FLAG_MASK
) == 0);
2502 g_return_if_fail (node
!= NULL
);
2504 if ((flags
& TYPE_FLAG_MASK
) && node
->is_classed
&& node
->data
&& node
->data
->class.class)
2505 g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node
));
2506 dflags
= GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
));
2508 type_set_qdata_W (node
, static_quark_type_flags
, GUINT_TO_POINTER (dflags
));
2512 g_type_query (GType type
,
2517 g_return_if_fail (query
!= NULL
);
2519 /* if node is not static and classed, we won't allow query */
2521 node
= lookup_type_node_I (type
);
2522 if (node
&& node
->is_classed
&& !node
->plugin
)
2524 /* type is classed and probably even instantiatable */
2525 G_READ_LOCK (&type_rw_lock
);
2526 if (node
->data
) /* type is static or referenced */
2528 query
->type
= NODE_TYPE (node
);
2529 query
->type_name
= NODE_NAME (node
);
2530 query
->class_size
= node
->data
->class.class_size
;
2531 query
->instance_size
= node
->is_instantiatable
? node
->data
->instance
.instance_size
: 0;
2533 G_READ_UNLOCK (&type_rw_lock
);
2538 /* --- implementation details --- */
2540 g_type_test_flags (GType type
,
2544 gboolean result
= FALSE
;
2546 node
= lookup_type_node_I (type
);
2549 guint fflags
= flags
& TYPE_FUNDAMENTAL_FLAG_MASK
;
2550 guint tflags
= flags
& TYPE_FLAG_MASK
;
2554 GTypeFundamentalInfo
*finfo
= type_node_fundamental_info_I (node
);
2556 fflags
= (finfo
->type_flags
& fflags
) == fflags
;
2563 G_READ_LOCK (&type_rw_lock
);
2564 tflags
= (tflags
& GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
))) == tflags
;
2565 G_READ_UNLOCK (&type_rw_lock
);
2570 result
= tflags
&& fflags
;
2577 g_type_get_plugin (GType type
)
2581 node
= lookup_type_node_I (type
);
2583 return node
? node
->plugin
: NULL
;
2587 g_type_interface_get_plugin (GType instance_type
,
2588 GType interface_type
)
2593 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type
), NULL
); /* G_TYPE_IS_INTERFACE() is an external call: _U */
2595 node
= lookup_type_node_I (instance_type
);
2596 iface
= lookup_type_node_I (interface_type
);
2599 IFaceHolder
*iholder
;
2600 GTypePlugin
*plugin
;
2602 G_READ_LOCK (&type_rw_lock
);
2604 iholder
= iface_node_get_holders_L (iface
);
2605 while (iholder
&& iholder
->instance_type
!= instance_type
)
2606 iholder
= iholder
->next
;
2607 plugin
= iholder
? iholder
->plugin
: NULL
;
2609 G_READ_UNLOCK (&type_rw_lock
);
2614 g_return_val_if_fail (node
== NULL
, NULL
);
2615 g_return_val_if_fail (iface
== NULL
, NULL
);
2617 g_warning (G_STRLOC
": attempt to look up plugin for invalid instance/interface type pair.");
2623 g_type_fundamental_next (void)
2627 G_READ_LOCK (&type_rw_lock
);
2628 type
= static_fundamental_next
;
2629 G_READ_UNLOCK (&type_rw_lock
);
2630 type
= G_TYPE_MAKE_FUNDAMENTAL (type
);
2631 return type
<= G_TYPE_FUNDAMENTAL_MAX
? type
: 0;
2635 g_type_fundamental (GType type_id
)
2637 TypeNode
*node
= lookup_type_node_I (type_id
);
2639 return node
? NODE_FUNDAMENTAL_TYPE (node
) : 0;
2643 g_type_check_instance_is_a (GTypeInstance
*type_instance
,
2646 TypeNode
*node
, *iface
;
2649 if (!type_instance
|| !type_instance
->g_class
)
2652 node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
2653 iface
= lookup_type_node_I (iface_type
);
2654 check
= node
&& node
->is_instantiatable
&& iface
&& type_node_conforms_to_U (node
, iface
, TRUE
, FALSE
);
2660 g_type_check_class_is_a (GTypeClass
*type_class
,
2663 TypeNode
*node
, *iface
;
2669 node
= lookup_type_node_I (type_class
->g_type
);
2670 iface
= lookup_type_node_I (is_a_type
);
2671 check
= node
&& node
->is_classed
&& iface
&& type_node_conforms_to_U (node
, iface
, FALSE
, FALSE
);
2677 g_type_check_instance_cast (GTypeInstance
*type_instance
,
2682 if (type_instance
->g_class
)
2684 TypeNode
*node
, *iface
;
2685 gboolean is_instantiatable
, check
;
2687 node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
2688 is_instantiatable
= node
&& node
->is_instantiatable
;
2689 iface
= lookup_type_node_I (iface_type
);
2690 check
= is_instantiatable
&& iface
&& type_node_conforms_to_U (node
, iface
, TRUE
, FALSE
);
2692 return type_instance
;
2694 if (is_instantiatable
)
2695 g_warning ("invalid cast from `%s' to `%s'",
2696 type_descriptive_name_I (type_instance
->g_class
->g_type
),
2697 type_descriptive_name_I (iface_type
));
2699 g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
2700 type_descriptive_name_I (type_instance
->g_class
->g_type
),
2701 type_descriptive_name_I (iface_type
));
2704 g_warning ("invalid unclassed pointer in cast to `%s'",
2705 type_descriptive_name_I (iface_type
));
2708 g_warning ("invalid cast from (NULL) pointer to `%s'",
2709 type_descriptive_name_I (iface_type
));
2711 return type_instance
;
2715 g_type_check_class_cast (GTypeClass
*type_class
,
2720 TypeNode
*node
, *iface
;
2721 gboolean is_classed
, check
;
2723 node
= lookup_type_node_I (type_class
->g_type
);
2724 is_classed
= node
&& node
->is_classed
;
2725 iface
= lookup_type_node_I (is_a_type
);
2726 check
= is_classed
&& iface
&& type_node_conforms_to_U (node
, iface
, FALSE
, FALSE
);
2731 g_warning ("invalid class cast from `%s' to `%s'",
2732 type_descriptive_name_I (type_class
->g_type
),
2733 type_descriptive_name_I (is_a_type
));
2735 g_warning ("invalid unclassed type `%s' in class cast to `%s'",
2736 type_descriptive_name_I (type_class
->g_type
),
2737 type_descriptive_name_I (is_a_type
));
2740 g_warning ("invalid class cast from (NULL) pointer to `%s'",
2741 type_descriptive_name_I (is_a_type
));
2746 g_type_check_instance (GTypeInstance
*type_instance
)
2748 /* this function is just here to make the signal system
2749 * conveniently elaborated on instance checks
2753 if (type_instance
->g_class
)
2755 TypeNode
*node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
2757 if (node
&& node
->is_instantiatable
)
2760 g_warning ("instance of invalid non-instantiatable type `%s'",
2761 type_descriptive_name_I (type_instance
->g_class
->g_type
));
2764 g_warning ("instance with invalid (NULL) class pointer");
2767 g_warning ("invalid (NULL) pointer instance");
2772 static inline gboolean
2773 type_check_is_value_type_U (GType type
)
2775 GTypeFlags tflags
= G_TYPE_FLAG_VALUE_ABSTRACT
;
2778 /* common path speed up */
2779 node
= lookup_type_node_I (type
);
2780 if (node
&& node
->mutatable_check_cache
)
2783 G_READ_LOCK (&type_rw_lock
);
2787 if (node
->data
&& node
->data
->common
.ref_count
> 0 &&
2788 node
->data
->common
.value_table
->value_init
)
2789 tflags
= GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
));
2790 else if (NODE_IS_IFACE (node
))
2794 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (node
); i
++)
2796 GType prtype
= IFACE_NODE_PREREQUISITES (node
)[i
];
2797 TypeNode
*prnode
= lookup_type_node_I (prtype
);
2799 if (prnode
->is_instantiatable
)
2802 node
= lookup_type_node_I (type
);
2808 G_READ_UNLOCK (&type_rw_lock
);
2810 return !(tflags
& G_TYPE_FLAG_VALUE_ABSTRACT
);
2814 g_type_check_is_value_type (GType type
)
2816 return type_check_is_value_type_U (type
);
2820 g_type_check_value (GValue
*value
)
2822 return value
&& type_check_is_value_type_U (value
->g_type
);
2826 g_type_check_value_holds (GValue
*value
,
2829 return value
&& type_check_is_value_type_U (value
->g_type
) && g_type_is_a (value
->g_type
, type
);
2833 g_type_value_table_peek (GType type
)
2835 GTypeValueTable
*vtable
= NULL
;
2836 TypeNode
*node
= lookup_type_node_I (type
);
2837 gboolean has_refed_data
, has_table
;
2840 /* speed up common code path, we're not 100% safe here,
2841 * but we should only get called with referenced types anyway
2843 data
= node
? node
->data
: NULL
;
2844 if (node
&& node
->mutatable_check_cache
)
2845 return data
->common
.value_table
;
2847 G_READ_LOCK (&type_rw_lock
);
2850 has_refed_data
= node
&& node
->data
&& node
->data
->common
.ref_count
;
2851 has_table
= has_refed_data
&& node
->data
->common
.value_table
->value_init
;
2855 vtable
= node
->data
->common
.value_table
;
2856 else if (NODE_IS_IFACE (node
))
2860 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (node
); i
++)
2862 GType prtype
= IFACE_NODE_PREREQUISITES (node
)[i
];
2863 TypeNode
*prnode
= lookup_type_node_I (prtype
);
2865 if (prnode
->is_instantiatable
)
2868 node
= lookup_type_node_I (type
);
2869 goto restart_table_peek
;
2875 G_READ_UNLOCK (&type_rw_lock
);
2881 g_warning (G_STRLOC
": type id `%lu' is invalid", type
);
2882 if (!has_refed_data
)
2883 g_warning ("can't peek value table for type `%s' which is not currently referenced",
2884 type_descriptive_name_I (type
));
2889 G_CONST_RETURN gchar
*
2890 g_type_name_from_instance (GTypeInstance
*instance
)
2893 return "<NULL-instance>";
2895 return g_type_name_from_class (instance
->g_class
);
2898 G_CONST_RETURN gchar
*
2899 g_type_name_from_class (GTypeClass
*g_class
)
2902 return "<NULL-class>";
2904 return g_type_name (g_class
->g_type
);
2908 /* --- foreign prototypes --- */
2909 extern void g_value_c_init (void); /* sync with gvalue.c */
2910 extern void g_value_types_init (void); /* sync with gvaluetypes.c */
2911 extern void g_enum_types_init (void); /* sync with genums.c */
2912 extern void g_param_type_init (void); /* sync with gparam.c */
2913 extern void g_boxed_type_init (void); /* sync with gboxed.c */
2914 extern void g_object_type_init (void); /* sync with gobject.c */
2915 extern void g_param_spec_types_init (void); /* sync with gparamspecs.c */
2916 extern void g_value_transforms_init (void); /* sync with gvaluetransform.c */
2917 extern void g_signal_init (void); /* sync with gsignal.c */
2920 /* --- initialization --- */
2922 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags
)
2924 G_LOCK_DEFINE_STATIC (type_init_lock
);
2925 const gchar
*env_string
;
2930 G_LOCK (type_init_lock
);
2932 G_WRITE_LOCK (&type_rw_lock
);
2934 if (static_quark_type_flags
)
2936 G_WRITE_UNLOCK (&type_rw_lock
);
2937 G_UNLOCK (type_init_lock
);
2941 /* setup GObject library wide debugging flags */
2942 _g_type_debug_flags
= debug_flags
& G_TYPE_DEBUG_MASK
;
2943 env_string
= g_getenv ("GOBJECT_DEBUG");
2944 if (env_string
!= NULL
)
2946 static GDebugKey debug_keys
[] = {
2947 { "objects", G_TYPE_DEBUG_OBJECTS
},
2948 { "signals", G_TYPE_DEBUG_SIGNALS
},
2951 _g_type_debug_flags
|= g_parse_debug_string (env_string
,
2953 sizeof (debug_keys
) / sizeof (debug_keys
[0]));
2958 static_quark_type_flags
= g_quark_from_static_string ("-g-type-private--GTypeFlags");
2959 static_quark_iface_holder
= g_quark_from_static_string ("-g-type-private--IFaceHolder");
2960 static_quark_dependants_array
= g_quark_from_static_string ("-g-type-private--dependants-array");
2962 /* type qname hash table */
2963 static_type_nodes_ht
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
2965 /* invalid type G_TYPE_INVALID (0)
2967 static_fundamental_type_nodes
[0] = NULL
;
2969 /* void type G_TYPE_NONE
2971 node
= type_node_fundamental_new_W (G_TYPE_NONE
, "void", 0);
2972 type
= NODE_TYPE (node
);
2973 g_assert (type
== G_TYPE_NONE
);
2975 /* interface fundamental type G_TYPE_INTERFACE (!classed)
2977 memset (&info
, 0, sizeof (info
));
2978 node
= type_node_fundamental_new_W (G_TYPE_INTERFACE
, "GInterface", G_TYPE_FLAG_DERIVABLE
);
2979 type
= NODE_TYPE (node
);
2980 type_data_make_W (node
, &info
, NULL
);
2981 g_assert (type
== G_TYPE_INTERFACE
);
2983 G_WRITE_UNLOCK (&type_rw_lock
);
2987 /* G_TYPE_TYPE_PLUGIN
2989 g_type_plugin_get_type ();
2991 /* G_TYPE_* value types
2993 g_value_types_init ();
2995 /* G_TYPE_ENUM & G_TYPE_FLAGS
2997 g_enum_types_init ();
3001 g_boxed_type_init ();
3005 g_param_type_init ();
3009 g_object_type_init ();
3011 /* G_TYPE_PARAM_* pspec types
3013 g_param_spec_types_init ();
3015 /* Value Transformations
3017 g_value_transforms_init ();
3023 G_UNLOCK (type_init_lock
);
3029 g_type_init_with_debug_flags (0);