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
== static_fundamental_next
)
387 static_fundamental_next
+= 1 << G_TYPE_FUNDAMENTAL_SHIFT
;
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
))
1206 guint n_dependants
, i
;
1208 dependants
= iface_node_get_dependants_array_L (prerequisite_node
);
1209 n_dependants
= dependants
? dependants
[0] : 0;
1210 for (i
= 1; i
<= n_dependants
; i
++)
1211 type_iface_add_prerequisite_W (iface
, lookup_type_node_I (dependants
[i
]));
1212 type_iface_add_prerequisite_W (iface
, prerequisite_node
);
1213 G_WRITE_UNLOCK (&type_rw_lock
);
1217 G_WRITE_UNLOCK (&type_rw_lock
);
1218 g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface",
1219 type_descriptive_name_I (prerequisite_type
),
1220 type_descriptive_name_I (interface_type
));
1225 type_iface_peek_holder_L (TypeNode
*iface
,
1226 GType instance_type
)
1228 IFaceHolder
*iholder
;
1230 g_assert (NODE_IS_IFACE (iface
));
1232 iholder
= iface_node_get_holders_L (iface
);
1233 while (iholder
&& iholder
->instance_type
!= instance_type
)
1234 iholder
= iholder
->next
;
1239 type_iface_retrieve_holder_info_Wm (TypeNode
*iface
,
1240 GType instance_type
,
1243 IFaceHolder
*iholder
= type_iface_peek_holder_L (iface
, instance_type
);
1245 if (iholder
&& !iholder
->info
&& need_info
)
1247 GInterfaceInfo tmp_info
;
1249 g_assert (iholder
->plugin
!= NULL
);
1251 type_data_ref_Wm (iface
);
1253 INVALID_RECURSION ("g_type_plugin_*", iface
->plugin
, NODE_NAME (iface
));
1255 memset (&tmp_info
, 0, sizeof (tmp_info
));
1257 G_WRITE_UNLOCK (&type_rw_lock
);
1258 g_type_plugin_use (iholder
->plugin
);
1259 g_type_plugin_complete_interface_info (iholder
->plugin
, instance_type
, NODE_TYPE (iface
), &tmp_info
);
1260 G_WRITE_LOCK (&type_rw_lock
);
1262 INVALID_RECURSION ("g_type_plugin_*", iholder
->plugin
, NODE_NAME (iface
));
1264 check_interface_info_I (iface
, instance_type
, &tmp_info
);
1265 iholder
->info
= g_memdup (&tmp_info
, sizeof (tmp_info
));
1268 return iholder
; /* we don't modify write lock upon returning NULL */
1272 type_iface_blow_holder_info_Wm (TypeNode
*iface
,
1273 GType instance_type
)
1275 IFaceHolder
*iholder
= iface_node_get_holders_L (iface
);
1277 g_assert (NODE_IS_IFACE (iface
));
1279 while (iholder
->instance_type
!= instance_type
)
1280 iholder
= iholder
->next
;
1282 if (iholder
->info
&& iholder
->plugin
)
1284 g_free (iholder
->info
);
1285 iholder
->info
= NULL
;
1287 G_WRITE_UNLOCK (&type_rw_lock
);
1288 g_type_plugin_unuse (iholder
->plugin
);
1289 G_WRITE_LOCK (&type_rw_lock
);
1291 type_data_unref_Wm (iface
, FALSE
);
1296 /* --- type structure creation/destruction --- */
1298 g_type_create_instance (GType type
)
1301 GTypeInstance
*instance
;
1305 node
= lookup_type_node_I (type
);
1306 if (!node
|| !node
->is_instantiatable
)
1308 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1309 type_descriptive_name_I (type
));
1312 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1313 if (!node
->mutatable_check_cache
&& G_TYPE_IS_ABSTRACT (type
))
1315 g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1316 type_descriptive_name_I (type
));
1320 class = g_type_class_ref (type
);
1322 if (node
->data
->instance
.n_preallocs
)
1324 G_WRITE_LOCK (&type_rw_lock
);
1325 if (!node
->data
->instance
.mem_chunk
)
1326 node
->data
->instance
.mem_chunk
= g_mem_chunk_new (NODE_NAME (node
),
1327 node
->data
->instance
.instance_size
,
1328 (node
->data
->instance
.instance_size
*
1329 node
->data
->instance
.n_preallocs
),
1331 instance
= g_chunk_new0 (GTypeInstance
, node
->data
->instance
.mem_chunk
);
1332 G_WRITE_UNLOCK (&type_rw_lock
);
1335 instance
= g_malloc0 (node
->data
->instance
.instance_size
); /* fine without read lock */
1336 for (i
= node
->n_supers
; i
> 0; i
--)
1340 pnode
= lookup_type_node_I (node
->supers
[i
]);
1341 if (pnode
->data
->instance
.instance_init
)
1343 instance
->g_class
= pnode
->data
->instance
.class;
1344 pnode
->data
->instance
.instance_init (instance
, class);
1347 instance
->g_class
= class;
1349 if (node
->data
->instance
.instance_init
)
1350 node
->data
->instance
.instance_init (instance
, class);
1356 g_type_free_instance (GTypeInstance
*instance
)
1361 g_return_if_fail (instance
!= NULL
&& instance
->g_class
!= NULL
);
1363 class = instance
->g_class
;
1364 node
= lookup_type_node_I (class->g_type
);
1365 if (!node
|| !node
->is_instantiatable
|| !node
->data
|| node
->data
->class.class != (gpointer
) class)
1367 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1368 type_descriptive_name_I (class->g_type
));
1371 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1372 if (!node
->mutatable_check_cache
&& G_TYPE_IS_ABSTRACT (NODE_TYPE (node
)))
1374 g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1379 instance
->g_class
= NULL
;
1380 #ifdef G_ENABLE_DEBUG
1381 memset (instance
, 0xaa, node
->data
->instance
.instance_size
); /* debugging hack */
1383 if (node
->data
->instance
.n_preallocs
)
1385 G_WRITE_LOCK (&type_rw_lock
);
1386 g_chunk_free (instance
, node
->data
->instance
.mem_chunk
);
1387 G_WRITE_UNLOCK (&type_rw_lock
);
1392 g_type_class_unref (class);
1396 type_iface_vtable_init_Wm (TypeNode
*iface
,
1399 IFaceEntry
*entry
= type_lookup_iface_entry_L (node
, iface
);
1400 IFaceHolder
*iholder
;
1401 GTypeInterface
*vtable
= NULL
;
1404 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1405 iholder
= type_iface_retrieve_holder_info_Wm (iface
, NODE_TYPE (node
), TRUE
);
1407 return FALSE
; /* we don't modify write lock upon FALSE */
1409 g_assert (iface
->data
&& entry
&& entry
->vtable
== NULL
&& iholder
&& iholder
->info
);
1411 pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
1412 if (pnode
) /* want to copy over parent iface contents */
1414 IFaceEntry
*pentry
= type_lookup_iface_entry_L (pnode
, iface
);
1417 vtable
= g_memdup (pentry
->vtable
, iface
->data
->iface
.vtable_size
);
1420 vtable
= g_malloc0 (iface
->data
->iface
.vtable_size
);
1421 entry
->vtable
= vtable
;
1422 vtable
->g_type
= NODE_TYPE (iface
);
1423 vtable
->g_instance_type
= NODE_TYPE (node
);
1425 if (iface
->data
->iface
.vtable_init_base
|| iholder
->info
->interface_init
)
1427 G_WRITE_UNLOCK (&type_rw_lock
);
1428 if (iface
->data
->iface
.vtable_init_base
)
1429 iface
->data
->iface
.vtable_init_base (vtable
);
1430 if (iholder
->info
->interface_init
)
1431 iholder
->info
->interface_init (vtable
, iholder
->info
->interface_data
);
1432 G_WRITE_LOCK (&type_rw_lock
);
1434 return TRUE
; /* write lock modified */
1438 type_iface_vtable_finalize_Wm (TypeNode
*iface
,
1440 GTypeInterface
*vtable
)
1442 IFaceEntry
*entry
= type_lookup_iface_entry_L (node
, iface
);
1443 IFaceHolder
*iholder
;
1445 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1446 iholder
= type_iface_retrieve_holder_info_Wm (iface
, NODE_TYPE (node
), FALSE
);
1448 return FALSE
; /* we don't modify write lock upon FALSE */
1450 g_assert (entry
&& entry
->vtable
== vtable
&& iholder
->info
);
1452 entry
->vtable
= NULL
;
1453 if (iholder
->info
->interface_finalize
|| iface
->data
->iface
.vtable_finalize_base
)
1455 G_WRITE_UNLOCK (&type_rw_lock
);
1456 if (iholder
->info
->interface_finalize
)
1457 iholder
->info
->interface_finalize (vtable
, iholder
->info
->interface_data
);
1458 if (iface
->data
->iface
.vtable_finalize_base
)
1459 iface
->data
->iface
.vtable_finalize_base (vtable
);
1460 G_WRITE_LOCK (&type_rw_lock
);
1463 vtable
->g_instance_type
= 0;
1466 type_iface_blow_holder_info_Wm (iface
, NODE_TYPE (node
));
1468 return TRUE
; /* write lock modified */
1472 type_class_init_Wm (TypeNode
*node
,
1475 GSList
*slist
, *init_slist
= NULL
;
1478 TypeNode
*bnode
, *pnode
;
1481 g_assert (node
->is_classed
&& node
->data
&&
1482 node
->data
->class.class_size
&&
1483 !node
->data
->class.class);
1485 class = g_malloc0 (node
->data
->class.class_size
);
1486 node
->data
->class.class = class;
1490 TypeNode
*pnode
= lookup_type_node_I (pclass
->g_type
);
1492 memcpy (class, pclass
, pnode
->data
->class.class_size
);
1494 class->g_type
= NODE_TYPE (node
);
1496 G_WRITE_UNLOCK (&type_rw_lock
);
1498 /* stack all base class initialization functions, so we
1499 * call them in ascending order.
1501 for (bnode
= node
; bnode
; bnode
= lookup_type_node_I (NODE_PARENT_TYPE (bnode
)))
1502 if (bnode
->data
->class.class_init_base
)
1503 init_slist
= g_slist_prepend (init_slist
, (gpointer
) bnode
->data
->class.class_init_base
);
1504 for (slist
= init_slist
; slist
; slist
= slist
->next
)
1506 GBaseInitFunc class_init_base
= (GBaseInitFunc
) slist
->data
;
1508 class_init_base (class);
1510 g_slist_free (init_slist
);
1512 if (node
->data
->class.class_init
)
1513 node
->data
->class.class_init (class, (gpointer
) node
->data
->class.class_data
);
1515 G_WRITE_LOCK (&type_rw_lock
);
1517 /* ok, we got the class done, now initialize all interfaces, either
1518 * from parent, or through our holder info
1520 pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
1521 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + 0;
1524 g_assert (entry
->vtable
== NULL
);
1526 if (!type_iface_vtable_init_Wm (lookup_type_node_I (entry
->iface_type
), node
))
1530 /* type_iface_vtable_init_Wm() doesn't modify write lock upon FALSE,
1531 * need to get this interface from parent
1533 g_assert (pnode
!= NULL
);
1535 for (j
= 0; j
< CLASSED_NODE_N_IFACES (pnode
); j
++)
1537 IFaceEntry
*pentry
= CLASSED_NODE_IFACES_ENTRIES (pnode
) + j
;
1539 if (pentry
->iface_type
== entry
->iface_type
)
1541 entry
->vtable
= pentry
->vtable
;
1545 g_assert (entry
->vtable
!= NULL
);
1548 /* refetch entry, IFACES_ENTRIES might be modified */
1549 for (entry
= NULL
, i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1550 if (!CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
)
1551 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + i
;
1556 type_data_finalize_class_ifaces_Wm (TypeNode
*node
)
1561 g_assert (node
->is_instantiatable
&& node
->data
&& node
->data
->class.class && node
->data
->common
.ref_count
== 0);
1563 g_message ("finalizing interfaces for %sClass `%s'",
1564 type_descriptive_name_I (NODE_FUNDAMENTAL_TYPE (node
)),
1565 type_descriptive_name_I (NODE_TYPE (node
)));
1567 for (entry
= NULL
, i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1568 if (CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
&&
1569 CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
->g_instance_type
== NODE_TYPE (node
))
1570 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + i
;
1573 if (!type_iface_vtable_finalize_Wm (lookup_type_node_I (entry
->iface_type
), node
, entry
->vtable
))
1575 /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
1576 * iface vtable came from parent
1578 entry
->vtable
= NULL
;
1581 /* refetch entry, IFACES_ENTRIES might be modified */
1582 for (entry
= NULL
, i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1583 if (CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
&&
1584 CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
->g_instance_type
== NODE_TYPE (node
))
1585 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + i
;
1590 type_data_finalize_class_U (TypeNode
*node
,
1593 GTypeClass
*class = cdata
->class;
1596 g_assert (cdata
->class && cdata
->common
.ref_count
== 0);
1598 if (cdata
->class_finalize
)
1599 cdata
->class_finalize (class, (gpointer
) cdata
->class_data
);
1601 /* call all base class destruction functions in descending order
1603 if (cdata
->class_finalize_base
)
1604 cdata
->class_finalize_base (class);
1605 for (bnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
)); bnode
; bnode
= lookup_type_node_I (NODE_PARENT_TYPE (bnode
)))
1606 if (bnode
->data
->class.class_finalize_base
)
1607 bnode
->data
->class.class_finalize_base (class);
1610 g_free (cdata
->class);
1614 type_data_last_unref_Wm (GType type
,
1617 TypeNode
*node
= lookup_type_node_I (type
);
1619 g_return_if_fail (node
!= NULL
&& node
->plugin
!= NULL
);
1621 if (!node
->data
|| node
->data
->common
.ref_count
== 0)
1623 g_warning ("cannot drop last reference to unreferenced type `%s'",
1624 type_descriptive_name_I (type
));
1628 if (node
->is_classed
&& node
->data
&& node
->data
->class.class && static_n_class_cache_funcs
)
1632 G_WRITE_UNLOCK (&type_rw_lock
);
1633 G_READ_LOCK (&type_rw_lock
);
1634 for (i
= 0; i
< static_n_class_cache_funcs
; i
++)
1636 GTypeClassCacheFunc cache_func
= static_class_cache_funcs
[i
].cache_func
;
1637 gpointer cache_data
= static_class_cache_funcs
[i
].cache_data
;
1638 gboolean need_break
;
1640 G_READ_UNLOCK (&type_rw_lock
);
1641 need_break
= cache_func (cache_data
, node
->data
->class.class);
1642 G_READ_LOCK (&type_rw_lock
);
1643 if (!node
->data
|| node
->data
->common
.ref_count
== 0)
1644 INVALID_RECURSION ("GType class cache function ", cache_func
, NODE_NAME (node
));
1648 G_READ_UNLOCK (&type_rw_lock
);
1649 G_WRITE_LOCK (&type_rw_lock
);
1652 if (node
->data
->common
.ref_count
> 1) /* may have been re-referenced meanwhile */
1653 node
->data
->common
.ref_count
-= 1;
1656 GType ptype
= NODE_PARENT_TYPE (node
);
1659 node
->data
->common
.ref_count
= 0;
1661 if (node
->is_instantiatable
&& node
->data
->instance
.mem_chunk
)
1663 g_mem_chunk_destroy (node
->data
->instance
.mem_chunk
);
1664 node
->data
->instance
.mem_chunk
= NULL
;
1668 if (node
->is_classed
&& tdata
->class.class)
1670 if (CLASSED_NODE_N_IFACES (node
))
1671 type_data_finalize_class_ifaces_Wm (node
);
1672 node
->mutatable_check_cache
= FALSE
;
1674 G_WRITE_UNLOCK (&type_rw_lock
);
1675 type_data_finalize_class_U (node
, &tdata
->class);
1676 G_WRITE_LOCK (&type_rw_lock
);
1680 node
->mutatable_check_cache
= FALSE
;
1684 /* freeing tdata->common.value_table and its contents is taking care of
1685 * by allocating it in one chunk with tdata
1690 type_data_unref_Wm (lookup_type_node_I (ptype
), FALSE
);
1691 G_WRITE_UNLOCK (&type_rw_lock
);
1692 g_type_plugin_unuse (node
->plugin
);
1693 G_WRITE_LOCK (&type_rw_lock
);
1698 g_type_add_class_cache_func (gpointer cache_data
,
1699 GTypeClassCacheFunc cache_func
)
1703 g_return_if_fail (cache_func
!= NULL
);
1705 G_WRITE_LOCK (&type_rw_lock
);
1706 i
= static_n_class_cache_funcs
++;
1707 static_class_cache_funcs
= g_renew (ClassCacheFunc
, static_class_cache_funcs
, static_n_class_cache_funcs
);
1708 static_class_cache_funcs
[i
].cache_data
= cache_data
;
1709 static_class_cache_funcs
[i
].cache_func
= cache_func
;
1710 G_WRITE_UNLOCK (&type_rw_lock
);
1714 g_type_remove_class_cache_func (gpointer cache_data
,
1715 GTypeClassCacheFunc cache_func
)
1717 gboolean found_it
= FALSE
;
1720 g_return_if_fail (cache_func
!= NULL
);
1722 G_WRITE_LOCK (&type_rw_lock
);
1723 for (i
= 0; i
< static_n_class_cache_funcs
; i
++)
1724 if (static_class_cache_funcs
[i
].cache_data
== cache_data
&&
1725 static_class_cache_funcs
[i
].cache_func
== cache_func
)
1727 static_n_class_cache_funcs
--;
1728 g_memmove (static_class_cache_funcs
+ i
,
1729 static_class_cache_funcs
+ i
+ 1,
1730 sizeof (static_class_cache_funcs
[0]) * (static_n_class_cache_funcs
- i
));
1731 static_class_cache_funcs
= g_renew (ClassCacheFunc
, static_class_cache_funcs
, static_n_class_cache_funcs
);
1735 G_WRITE_UNLOCK (&type_rw_lock
);
1738 g_warning (G_STRLOC
": cannot remove unregistered class cache func %p with data %p",
1739 cache_func
, cache_data
);
1743 /* --- type registration --- */
1745 g_type_register_fundamental (GType type_id
,
1746 const gchar
*type_name
,
1747 const GTypeInfo
*info
,
1748 const GTypeFundamentalInfo
*finfo
,
1751 GTypeFundamentalInfo
*node_finfo
;
1754 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
1755 g_return_val_if_fail (type_id
> 0, 0);
1756 g_return_val_if_fail (type_name
!= NULL
, 0);
1757 g_return_val_if_fail (info
!= NULL
, 0);
1758 g_return_val_if_fail (finfo
!= NULL
, 0);
1760 if (!check_type_name_I (type_name
))
1762 if ((type_id
& TYPE_ID_MASK
) ||
1763 type_id
> G_TYPE_FUNDAMENTAL_MAX
)
1765 g_warning ("attempt to register fundamental type `%s' with invalid type id (%lu)",
1770 if ((finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) &&
1771 !(finfo
->type_flags
& G_TYPE_FLAG_CLASSED
))
1773 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1777 if (lookup_type_node_I (type_id
))
1779 g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1780 type_descriptive_name_I (type_id
),
1785 G_WRITE_LOCK (&type_rw_lock
);
1786 node
= type_node_fundamental_new_W (type_id
, type_name
, finfo
->type_flags
);
1787 node_finfo
= type_node_fundamental_info_I (node
);
1788 type_add_flags_W (node
, flags
);
1790 if (check_type_info_I (NULL
, NODE_FUNDAMENTAL_TYPE (node
), type_name
, info
))
1791 type_data_make_W (node
, info
,
1792 check_value_table_I (type_name
, info
->value_table
) ? info
->value_table
: NULL
);
1793 G_WRITE_UNLOCK (&type_rw_lock
);
1795 return NODE_TYPE (node
);
1799 g_type_register_static (GType parent_type
,
1800 const gchar
*type_name
,
1801 const GTypeInfo
*info
,
1804 TypeNode
*pnode
, *node
;
1807 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
1808 g_return_val_if_fail (parent_type
> 0, 0);
1809 g_return_val_if_fail (type_name
!= NULL
, 0);
1810 g_return_val_if_fail (info
!= NULL
, 0);
1812 if (!check_type_name_I (type_name
) ||
1813 !check_derivation_I (parent_type
, type_name
))
1815 if (info
->class_finalize
)
1817 g_warning ("class finalizer specified for static type `%s'",
1822 pnode
= lookup_type_node_I (parent_type
);
1823 G_WRITE_LOCK (&type_rw_lock
);
1824 type_data_ref_Wm (pnode
);
1825 if (check_type_info_I (pnode
, NODE_FUNDAMENTAL_TYPE (pnode
), type_name
, info
))
1827 node
= type_node_new_W (pnode
, type_name
, NULL
);
1828 type_add_flags_W (node
, flags
);
1829 type
= NODE_TYPE (node
);
1830 type_data_make_W (node
, info
,
1831 check_value_table_I (type_name
, info
->value_table
) ? info
->value_table
: NULL
);
1833 G_WRITE_UNLOCK (&type_rw_lock
);
1839 g_type_register_dynamic (GType parent_type
,
1840 const gchar
*type_name
,
1841 GTypePlugin
*plugin
,
1844 TypeNode
*pnode
, *node
;
1847 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
1848 g_return_val_if_fail (parent_type
> 0, 0);
1849 g_return_val_if_fail (type_name
!= NULL
, 0);
1850 g_return_val_if_fail (plugin
!= NULL
, 0);
1852 if (!check_type_name_I (type_name
) ||
1853 !check_derivation_I (parent_type
, type_name
) ||
1854 !check_plugin_U (plugin
, TRUE
, FALSE
, type_name
))
1857 G_WRITE_LOCK (&type_rw_lock
);
1858 pnode
= lookup_type_node_I (parent_type
);
1859 node
= type_node_new_W (pnode
, type_name
, plugin
);
1860 type_add_flags_W (node
, flags
);
1861 type
= NODE_TYPE (node
);
1862 G_WRITE_UNLOCK (&type_rw_lock
);
1868 g_type_add_interface_static (GType instance_type
,
1869 GType interface_type
,
1870 const GInterfaceInfo
*info
)
1872 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1873 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type
));
1874 g_return_if_fail (g_type_parent (interface_type
) == G_TYPE_INTERFACE
);
1876 G_WRITE_LOCK (&type_rw_lock
);
1877 if (check_add_interface_L (instance_type
, interface_type
))
1879 TypeNode
*node
= lookup_type_node_I (instance_type
);
1880 TypeNode
*iface
= lookup_type_node_I (interface_type
);
1882 if (check_interface_info_I (iface
, NODE_TYPE (node
), info
))
1884 type_add_interface_W (node
, iface
, info
, NULL
);
1885 /* if we have a class already, the interface vtable needs to
1886 * be initialized as well
1888 if (node
->data
&& node
->data
->class.class)
1889 type_iface_vtable_init_Wm (iface
, node
);
1892 G_WRITE_UNLOCK (&type_rw_lock
);
1896 g_type_add_interface_dynamic (GType instance_type
,
1897 GType interface_type
,
1898 GTypePlugin
*plugin
)
1902 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1903 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type
));
1904 g_return_if_fail (g_type_parent (interface_type
) == G_TYPE_INTERFACE
);
1906 node
= lookup_type_node_I (instance_type
);
1907 if (!check_plugin_U (plugin
, FALSE
, TRUE
, NODE_NAME (node
)))
1910 G_WRITE_LOCK (&type_rw_lock
);
1911 if (check_add_interface_L (instance_type
, interface_type
))
1913 TypeNode
*iface
= lookup_type_node_I (interface_type
);
1915 type_add_interface_W (node
, iface
, NULL
, plugin
);
1916 /* if we have a class already, the interface vtable needs to
1917 * be initialized as well
1919 if (node
->data
&& node
->data
->class.class)
1920 type_iface_vtable_init_Wm (iface
, node
);
1922 G_WRITE_UNLOCK (&type_rw_lock
);
1926 /* --- public API functions --- */
1928 g_type_class_ref (GType type
)
1932 /* optimize for common code path
1934 G_WRITE_LOCK (&type_rw_lock
);
1935 node
= lookup_type_node_I (type
);
1936 if (node
&& node
->is_classed
&& node
->data
&&
1937 node
->data
->class.class && node
->data
->common
.ref_count
> 0)
1939 type_data_ref_Wm (node
);
1940 G_WRITE_UNLOCK (&type_rw_lock
);
1942 return node
->data
->class.class;
1945 if (!node
|| !node
->is_classed
||
1946 (node
->data
&& node
->data
->common
.ref_count
< 1))
1948 G_WRITE_UNLOCK (&type_rw_lock
);
1949 g_warning ("cannot retrieve class for invalid (unclassed) type `%s'",
1950 type_descriptive_name_I (type
));
1954 type_data_ref_Wm (node
);
1956 if (!node
->data
->class.class)
1958 GType ptype
= NODE_PARENT_TYPE (node
);
1959 GTypeClass
*pclass
= NULL
;
1963 G_WRITE_UNLOCK (&type_rw_lock
);
1964 pclass
= g_type_class_ref (ptype
);
1965 if (node
->data
->class.class)
1966 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
1967 G_WRITE_LOCK (&type_rw_lock
);
1970 type_class_init_Wm (node
, pclass
);
1972 G_WRITE_UNLOCK (&type_rw_lock
);
1974 return node
->data
->class.class;
1978 g_type_class_unref (gpointer g_class
)
1981 GTypeClass
*class = g_class
;
1983 g_return_if_fail (g_class
!= NULL
);
1985 node
= lookup_type_node_I (class->g_type
);
1986 G_WRITE_LOCK (&type_rw_lock
);
1987 if (node
&& node
->is_classed
&& node
->data
&&
1988 node
->data
->class.class == class && node
->data
->common
.ref_count
> 0)
1989 type_data_unref_Wm (node
, FALSE
);
1991 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
1992 type_descriptive_name_I (class->g_type
));
1993 G_WRITE_UNLOCK (&type_rw_lock
);
1997 g_type_class_unref_uncached (gpointer g_class
)
2000 GTypeClass
*class = g_class
;
2002 g_return_if_fail (g_class
!= NULL
);
2004 G_WRITE_LOCK (&type_rw_lock
);
2005 node
= lookup_type_node_I (class->g_type
);
2006 if (node
&& node
->is_classed
&& node
->data
&&
2007 node
->data
->class.class == class && node
->data
->common
.ref_count
> 0)
2008 type_data_unref_Wm (node
, TRUE
);
2010 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2011 type_descriptive_name_I (class->g_type
));
2012 G_WRITE_UNLOCK (&type_rw_lock
);
2016 g_type_class_peek (GType type
)
2021 node
= lookup_type_node_I (type
);
2022 G_READ_LOCK (&type_rw_lock
);
2023 if (node
&& node
->is_classed
&& node
->data
&& node
->data
->class.class) /* common.ref_count _may_ be 0 */
2024 class = node
->data
->class.class;
2027 G_READ_UNLOCK (&type_rw_lock
);
2033 g_type_class_peek_parent (gpointer g_class
)
2036 gpointer
class = NULL
;
2038 g_return_val_if_fail (g_class
!= NULL
, NULL
);
2040 node
= lookup_type_node_I (G_TYPE_FROM_CLASS (g_class
));
2041 G_READ_LOCK (&type_rw_lock
);
2042 if (node
&& node
->is_classed
&& node
->data
&& NODE_PARENT_TYPE (node
))
2044 node
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
2045 class = node
->data
->class.class;
2047 else if (NODE_PARENT_TYPE (node
))
2048 g_warning (G_STRLOC
": invalid class pointer `%p'", g_class
);
2049 G_READ_UNLOCK (&type_rw_lock
);
2055 g_type_interface_peek (gpointer instance_class
,
2060 gpointer vtable
= NULL
;
2061 GTypeClass
*class = instance_class
;
2063 g_return_val_if_fail (instance_class
!= NULL
, NULL
);
2065 node
= lookup_type_node_I (class->g_type
);
2066 iface
= lookup_type_node_I (iface_type
);
2067 if (node
&& node
->is_instantiatable
&& iface
)
2071 G_READ_LOCK (&type_rw_lock
);
2073 entry
= type_lookup_iface_entry_L (node
, iface
);
2074 if (entry
&& entry
->vtable
) /* entry is relocatable */
2075 vtable
= entry
->vtable
;
2077 G_READ_UNLOCK (&type_rw_lock
);
2080 g_warning (G_STRLOC
": invalid class pointer `%p'", class);
2086 g_type_interface_peek_parent (gpointer g_iface
)
2090 gpointer vtable
= NULL
;
2091 GTypeInterface
*iface_class
= g_iface
;
2093 g_return_val_if_fail (g_iface
!= NULL
, NULL
);
2095 iface
= lookup_type_node_I (iface_class
->g_type
);
2096 node
= lookup_type_node_I (iface_class
->g_instance_type
);
2098 node
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
2099 if (node
&& node
->is_instantiatable
&& iface
)
2103 G_READ_LOCK (&type_rw_lock
);
2105 entry
= type_lookup_iface_entry_L (node
, iface
);
2106 if (entry
&& entry
->vtable
) /* entry is relocatable */
2107 vtable
= entry
->vtable
;
2109 G_READ_UNLOCK (&type_rw_lock
);
2112 g_warning (G_STRLOC
": invalid interface pointer `%p'", g_iface
);
2117 G_CONST_RETURN gchar
*
2118 g_type_name (GType type
)
2122 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, NULL
);
2124 node
= lookup_type_node_I (type
);
2126 return node
? NODE_NAME (node
) : NULL
;
2130 g_type_qname (GType type
)
2134 node
= lookup_type_node_I (type
);
2136 return node
? node
->qname
: 0;
2140 g_type_from_name (const gchar
*name
)
2145 g_return_val_if_fail (name
!= NULL
, 0);
2147 quark
= g_quark_try_string (name
);
2150 G_READ_LOCK (&type_rw_lock
);
2151 type
= (GType
) g_hash_table_lookup (static_type_nodes_ht
, GUINT_TO_POINTER (quark
));
2152 G_READ_UNLOCK (&type_rw_lock
);
2159 g_type_parent (GType type
)
2163 node
= lookup_type_node_I (type
);
2165 return node
? NODE_PARENT_TYPE (node
) : 0;
2169 g_type_depth (GType type
)
2173 node
= lookup_type_node_I (type
);
2175 return node
? node
->n_supers
+ 1 : 0;
2179 g_type_next_base (GType type
,
2185 node
= lookup_type_node_I (type
);
2188 TypeNode
*base_node
= lookup_type_node_I (base_type
);
2190 if (base_node
&& base_node
->n_supers
< node
->n_supers
)
2192 guint n
= node
->n_supers
- base_node
->n_supers
;
2194 if (node
->supers
[n
] == base_type
)
2195 atype
= node
->supers
[n
- 1];
2202 static inline gboolean
2203 type_node_check_conformities_UorL (TypeNode
*node
,
2204 TypeNode
*iface_node
,
2205 /* support_inheritance */
2206 gboolean support_interfaces
,
2207 gboolean support_prerequisites
,
2212 if (/* support_inheritance && */
2213 iface_node
->n_supers
<= node
->n_supers
&&
2214 node
->supers
[node
->n_supers
- iface_node
->n_supers
] == NODE_TYPE (iface_node
))
2217 support_interfaces
= support_interfaces
&& node
->is_instantiatable
&& NODE_IS_IFACE (iface_node
);
2218 support_prerequisites
= support_prerequisites
&& NODE_IS_IFACE (node
);
2220 if (support_interfaces
|| support_prerequisites
)
2223 G_READ_LOCK (&type_rw_lock
);
2224 if (support_interfaces
&& type_lookup_iface_entry_L (node
, iface_node
))
2226 else if (support_prerequisites
&& type_lookup_prerequisite_L (node
, NODE_TYPE (iface_node
)))
2229 G_READ_UNLOCK (&type_rw_lock
);
2235 type_node_is_a_L (TypeNode
*node
,
2236 TypeNode
*iface_node
)
2238 return type_node_check_conformities_UorL (node
, iface_node
, TRUE
, TRUE
, TRUE
);
2241 static inline gboolean
2242 type_node_conforms_to_U (TypeNode
*node
,
2243 TypeNode
*iface_node
,
2244 gboolean support_interfaces
,
2245 gboolean support_prerequisites
)
2247 return type_node_check_conformities_UorL (node
, iface_node
, support_interfaces
, support_prerequisites
, FALSE
);
2251 g_type_is_a (GType type
,
2254 TypeNode
*node
, *iface_node
;
2257 node
= lookup_type_node_I (type
);
2258 iface_node
= lookup_type_node_I (iface_type
);
2259 is_a
= node
&& iface_node
&& type_node_conforms_to_U (node
, iface_node
, TRUE
, TRUE
);
2264 GType
* /* free result */
2265 g_type_children (GType type
,
2270 node
= lookup_type_node_I (type
);
2275 G_READ_LOCK (&type_rw_lock
); /* ->children is relocatable */
2276 children
= g_new (GType
, node
->n_children
+ 1);
2277 memcpy (children
, node
->children
, sizeof (GType
) * node
->n_children
);
2278 children
[node
->n_children
] = 0;
2281 *n_children
= node
->n_children
;
2282 G_READ_UNLOCK (&type_rw_lock
);
2295 GType
* /* free result */
2296 g_type_interfaces (GType type
,
2297 guint
*n_interfaces
)
2301 node
= lookup_type_node_I (type
);
2302 if (node
&& node
->is_instantiatable
)
2307 G_READ_LOCK (&type_rw_lock
);
2308 ifaces
= g_new (GType
, CLASSED_NODE_N_IFACES (node
) + 1);
2309 for (i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
2310 ifaces
[i
] = CLASSED_NODE_IFACES_ENTRIES (node
)[i
].iface_type
;
2314 *n_interfaces
= CLASSED_NODE_N_IFACES (node
);
2315 G_READ_UNLOCK (&type_rw_lock
);
2328 typedef struct _QData QData
;
2340 static inline gpointer
2341 type_get_qdata_L (TypeNode
*node
,
2344 GData
*gdata
= node
->global_gdata
;
2346 if (quark
&& gdata
&& gdata
->n_qdatas
)
2348 QData
*qdatas
= gdata
->qdatas
- 1;
2349 guint n_qdatas
= gdata
->n_qdatas
;
2356 i
= (n_qdatas
+ 1) / 2;
2358 if (quark
== check
->quark
)
2360 else if (quark
> check
->quark
)
2365 else /* if (quark < check->quark) */
2374 g_type_get_qdata (GType type
,
2380 node
= lookup_type_node_I (type
);
2383 G_READ_LOCK (&type_rw_lock
);
2384 data
= type_get_qdata_L (node
, quark
);
2385 G_READ_UNLOCK (&type_rw_lock
);
2389 g_return_val_if_fail (node
!= NULL
, NULL
);
2396 type_set_qdata_W (TypeNode
*node
,
2404 /* setup qdata list if necessary */
2405 if (!node
->global_gdata
)
2406 node
->global_gdata
= g_new0 (GData
, 1);
2407 gdata
= node
->global_gdata
;
2409 /* try resetting old data */
2410 qdata
= gdata
->qdatas
;
2411 for (i
= 0; i
< gdata
->n_qdatas
; i
++)
2412 if (qdata
[i
].quark
== quark
)
2414 qdata
[i
].data
= data
;
2420 gdata
->qdatas
= g_renew (QData
, gdata
->qdatas
, gdata
->n_qdatas
);
2421 qdata
= gdata
->qdatas
;
2422 for (i
= 0; i
< gdata
->n_qdatas
- 1; i
++)
2423 if (qdata
[i
].quark
> quark
)
2425 g_memmove (qdata
+ i
+ 1, qdata
+ i
, sizeof (qdata
[0]) * (gdata
->n_qdatas
- i
- 1));
2426 qdata
[i
].quark
= quark
;
2427 qdata
[i
].data
= data
;
2431 g_type_set_qdata (GType type
,
2437 g_return_if_fail (quark
!= 0);
2439 node
= lookup_type_node_I (type
);
2442 G_WRITE_LOCK (&type_rw_lock
);
2443 type_set_qdata_W (node
, quark
, data
);
2444 G_WRITE_UNLOCK (&type_rw_lock
);
2447 g_return_if_fail (node
!= NULL
);
2451 type_add_flags_W (TypeNode
*node
,
2456 g_return_if_fail ((flags
& ~TYPE_FLAG_MASK
) == 0);
2457 g_return_if_fail (node
!= NULL
);
2459 if ((flags
& TYPE_FLAG_MASK
) && node
->is_classed
&& node
->data
&& node
->data
->class.class)
2460 g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node
));
2461 dflags
= GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
));
2463 type_set_qdata_W (node
, static_quark_type_flags
, GUINT_TO_POINTER (dflags
));
2467 g_type_query (GType type
,
2472 g_return_if_fail (query
!= NULL
);
2474 /* if node is not static and classed, we won't allow query */
2476 node
= lookup_type_node_I (type
);
2477 if (node
&& node
->is_classed
&& !node
->plugin
)
2479 /* type is classed and probably even instantiatable */
2480 G_READ_LOCK (&type_rw_lock
);
2481 if (node
->data
) /* type is static or referenced */
2483 query
->type
= NODE_TYPE (node
);
2484 query
->type_name
= NODE_NAME (node
);
2485 query
->class_size
= node
->data
->class.class_size
;
2486 query
->instance_size
= node
->is_instantiatable
? node
->data
->instance
.instance_size
: 0;
2488 G_READ_UNLOCK (&type_rw_lock
);
2493 /* --- implementation details --- */
2495 g_type_test_flags (GType type
,
2499 gboolean result
= FALSE
;
2501 node
= lookup_type_node_I (type
);
2504 guint fflags
= flags
& TYPE_FUNDAMENTAL_FLAG_MASK
;
2505 guint tflags
= flags
& TYPE_FLAG_MASK
;
2509 GTypeFundamentalInfo
*finfo
= type_node_fundamental_info_I (node
);
2511 fflags
= (finfo
->type_flags
& fflags
) == fflags
;
2518 G_READ_LOCK (&type_rw_lock
);
2519 tflags
= (tflags
& GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
))) == tflags
;
2520 G_READ_UNLOCK (&type_rw_lock
);
2525 result
= tflags
&& fflags
;
2532 g_type_get_plugin (GType type
)
2536 node
= lookup_type_node_I (type
);
2538 return node
? node
->plugin
: NULL
;
2542 g_type_interface_get_plugin (GType instance_type
,
2543 GType interface_type
)
2548 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type
), NULL
); /* G_TYPE_IS_INTERFACE() is an external call: _U */
2550 node
= lookup_type_node_I (instance_type
);
2551 iface
= lookup_type_node_I (interface_type
);
2554 IFaceHolder
*iholder
;
2555 GTypePlugin
*plugin
;
2557 G_READ_LOCK (&type_rw_lock
);
2559 iholder
= iface_node_get_holders_L (iface
);
2560 while (iholder
&& iholder
->instance_type
!= instance_type
)
2561 iholder
= iholder
->next
;
2562 plugin
= iholder
? iholder
->plugin
: NULL
;
2564 G_READ_UNLOCK (&type_rw_lock
);
2569 g_return_val_if_fail (node
== NULL
, NULL
);
2570 g_return_val_if_fail (iface
== NULL
, NULL
);
2572 g_warning (G_STRLOC
": attempt to look up plugin for invalid instance/interface type pair.");
2578 g_type_fundamental_next (void)
2582 G_READ_LOCK (&type_rw_lock
);
2583 type
= static_fundamental_next
;
2584 G_READ_UNLOCK (&type_rw_lock
);
2586 return type
<= G_TYPE_FUNDAMENTAL_MAX
? type
: 0;
2590 g_type_fundamental (GType type_id
)
2592 TypeNode
*node
= lookup_type_node_I (type_id
);
2594 return node
? NODE_FUNDAMENTAL_TYPE (node
) : 0;
2598 g_type_check_instance_is_a (GTypeInstance
*type_instance
,
2601 TypeNode
*node
, *iface
;
2604 if (!type_instance
|| !type_instance
->g_class
)
2607 node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
2608 iface
= lookup_type_node_I (iface_type
);
2609 check
= node
&& node
->is_instantiatable
&& iface
&& type_node_conforms_to_U (node
, iface
, TRUE
, FALSE
);
2615 g_type_check_class_is_a (GTypeClass
*type_class
,
2618 TypeNode
*node
, *iface
;
2624 node
= lookup_type_node_I (type_class
->g_type
);
2625 iface
= lookup_type_node_I (is_a_type
);
2626 check
= node
&& node
->is_classed
&& iface
&& type_node_conforms_to_U (node
, iface
, FALSE
, FALSE
);
2632 g_type_check_instance_cast (GTypeInstance
*type_instance
,
2637 if (type_instance
->g_class
)
2639 TypeNode
*node
, *iface
;
2640 gboolean is_instantiatable
, check
;
2642 node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
2643 is_instantiatable
= node
&& node
->is_instantiatable
;
2644 iface
= lookup_type_node_I (iface_type
);
2645 check
= is_instantiatable
&& iface
&& type_node_conforms_to_U (node
, iface
, TRUE
, FALSE
);
2647 return type_instance
;
2649 if (is_instantiatable
)
2650 g_warning ("invalid cast from `%s' to `%s'",
2651 type_descriptive_name_I (type_instance
->g_class
->g_type
),
2652 type_descriptive_name_I (iface_type
));
2654 g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
2655 type_descriptive_name_I (type_instance
->g_class
->g_type
),
2656 type_descriptive_name_I (iface_type
));
2659 g_warning ("invalid unclassed pointer in cast to `%s'",
2660 type_descriptive_name_I (iface_type
));
2663 g_warning ("invalid cast from (NULL) pointer to `%s'",
2664 type_descriptive_name_I (iface_type
));
2666 return type_instance
;
2670 g_type_check_class_cast (GTypeClass
*type_class
,
2675 TypeNode
*node
, *iface
;
2676 gboolean is_classed
, check
;
2678 node
= lookup_type_node_I (type_class
->g_type
);
2679 is_classed
= node
&& node
->is_classed
;
2680 iface
= lookup_type_node_I (is_a_type
);
2681 check
= is_classed
&& iface
&& type_node_conforms_to_U (node
, iface
, FALSE
, FALSE
);
2686 g_warning ("invalid class cast from `%s' to `%s'",
2687 type_descriptive_name_I (type_class
->g_type
),
2688 type_descriptive_name_I (is_a_type
));
2690 g_warning ("invalid unclassed type `%s' in class cast to `%s'",
2691 type_descriptive_name_I (type_class
->g_type
),
2692 type_descriptive_name_I (is_a_type
));
2695 g_warning ("invalid class cast from (NULL) pointer to `%s'",
2696 type_descriptive_name_I (is_a_type
));
2701 g_type_check_instance (GTypeInstance
*type_instance
)
2703 /* this function is just here to make the signal system
2704 * conveniently elaborated on instance checks
2708 if (type_instance
->g_class
)
2710 TypeNode
*node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
2712 if (node
&& node
->is_instantiatable
)
2715 g_warning ("instance of invalid non-instantiatable type `%s'",
2716 type_descriptive_name_I (type_instance
->g_class
->g_type
));
2719 g_warning ("instance with invalid (NULL) class pointer");
2722 g_warning ("invalid (NULL) pointer instance");
2727 static inline gboolean
2728 type_check_is_value_type_U (GType type
)
2730 GTypeFlags tflags
= G_TYPE_FLAG_VALUE_ABSTRACT
;
2733 /* common path speed up */
2734 node
= lookup_type_node_I (type
);
2735 if (node
&& node
->mutatable_check_cache
)
2738 G_READ_LOCK (&type_rw_lock
);
2742 if (node
->data
&& node
->data
->common
.ref_count
> 0 &&
2743 node
->data
->common
.value_table
->value_init
)
2744 tflags
= GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
));
2745 else if (NODE_IS_IFACE (node
))
2749 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (node
); i
++)
2751 GType prtype
= IFACE_NODE_PREREQUISITES (node
)[i
];
2752 TypeNode
*prnode
= lookup_type_node_I (prtype
);
2754 if (prnode
->is_instantiatable
)
2757 node
= lookup_type_node_I (type
);
2763 G_READ_UNLOCK (&type_rw_lock
);
2765 return !(tflags
& G_TYPE_FLAG_VALUE_ABSTRACT
);
2769 g_type_check_is_value_type (GType type
)
2771 return type_check_is_value_type_U (type
);
2775 g_type_check_value (GValue
*value
)
2777 return value
&& type_check_is_value_type_U (value
->g_type
);
2781 g_type_check_value_holds (GValue
*value
,
2784 return value
&& type_check_is_value_type_U (value
->g_type
) && g_type_is_a (value
->g_type
, type
);
2788 g_type_value_table_peek (GType type
)
2790 GTypeValueTable
*vtable
= NULL
;
2791 TypeNode
*node
= lookup_type_node_I (type
);
2792 gboolean has_refed_data
, has_table
;
2795 /* speed up common code path, we're not 100% safe here,
2796 * but we should only get called with referenced types anyway
2798 data
= node
? node
->data
: NULL
;
2799 if (node
&& node
->mutatable_check_cache
)
2800 return data
->common
.value_table
;
2802 G_READ_LOCK (&type_rw_lock
);
2805 has_refed_data
= node
&& node
->data
&& node
->data
->common
.ref_count
;
2806 has_table
= has_refed_data
&& node
->data
->common
.value_table
->value_init
;
2810 vtable
= node
->data
->common
.value_table
;
2811 else if (NODE_IS_IFACE (node
))
2815 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (node
); i
++)
2817 GType prtype
= IFACE_NODE_PREREQUISITES (node
)[i
];
2818 TypeNode
*prnode
= lookup_type_node_I (prtype
);
2820 if (prnode
->is_instantiatable
)
2823 node
= lookup_type_node_I (type
);
2824 goto restart_table_peek
;
2830 G_READ_UNLOCK (&type_rw_lock
);
2836 g_warning (G_STRLOC
": type id `%lu' is invalid", type
);
2837 if (!has_refed_data
)
2838 g_warning ("can't peek value table for type `%s' which is not currently referenced",
2839 type_descriptive_name_I (type
));
2844 G_CONST_RETURN gchar
*
2845 g_type_name_from_instance (GTypeInstance
*instance
)
2848 return "<NULL-instance>";
2850 return g_type_name_from_class (instance
->g_class
);
2853 G_CONST_RETURN gchar
*
2854 g_type_name_from_class (GTypeClass
*g_class
)
2857 return "<NULL-class>";
2859 return g_type_name (g_class
->g_type
);
2863 /* --- foreign prototypes --- */
2864 extern void g_value_c_init (void); /* sync with gvalue.c */
2865 extern void g_value_types_init (void); /* sync with gvaluetypes.c */
2866 extern void g_enum_types_init (void); /* sync with genums.c */
2867 extern void g_param_type_init (void); /* sync with gparam.c */
2868 extern void g_boxed_type_init (void); /* sync with gboxed.c */
2869 extern void g_object_type_init (void); /* sync with gobject.c */
2870 extern void g_param_spec_types_init (void); /* sync with gparamspecs.c */
2871 extern void g_value_transforms_init (void); /* sync with gvaluetransform.c */
2872 extern void g_signal_init (void); /* sync with gsignal.c */
2875 /* --- initialization --- */
2877 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags
)
2879 G_LOCK_DEFINE_STATIC (type_init_lock
);
2880 const gchar
*env_string
;
2885 G_LOCK (type_init_lock
);
2887 G_WRITE_LOCK (&type_rw_lock
);
2889 if (static_quark_type_flags
)
2891 G_WRITE_UNLOCK (&type_rw_lock
);
2892 G_UNLOCK (type_init_lock
);
2896 /* setup GObject library wide debugging flags */
2897 _g_type_debug_flags
= debug_flags
& G_TYPE_DEBUG_MASK
;
2898 env_string
= g_getenv ("GOBJECT_DEBUG");
2899 if (env_string
!= NULL
)
2901 static GDebugKey debug_keys
[] = {
2902 { "objects", G_TYPE_DEBUG_OBJECTS
},
2903 { "signals", G_TYPE_DEBUG_SIGNALS
},
2906 _g_type_debug_flags
|= g_parse_debug_string (env_string
,
2908 sizeof (debug_keys
) / sizeof (debug_keys
[0]));
2913 static_quark_type_flags
= g_quark_from_static_string ("-g-type-private--GTypeFlags");
2914 static_quark_iface_holder
= g_quark_from_static_string ("-g-type-private--IFaceHolder");
2915 static_quark_dependants_array
= g_quark_from_static_string ("-g-type-private--dependants-array");
2917 /* type qname hash table */
2918 static_type_nodes_ht
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
2920 /* invalid type G_TYPE_INVALID (0)
2922 static_fundamental_type_nodes
[0] = NULL
;
2924 /* void type G_TYPE_NONE
2926 node
= type_node_fundamental_new_W (G_TYPE_NONE
, "void", 0);
2927 type
= NODE_TYPE (node
);
2928 g_assert (type
== G_TYPE_NONE
);
2930 /* interface fundamental type G_TYPE_INTERFACE (!classed)
2932 memset (&info
, 0, sizeof (info
));
2933 node
= type_node_fundamental_new_W (G_TYPE_INTERFACE
, "GInterface", G_TYPE_FLAG_DERIVABLE
);
2934 type
= NODE_TYPE (node
);
2935 type_data_make_W (node
, &info
, NULL
);
2936 g_assert (type
== G_TYPE_INTERFACE
);
2938 G_WRITE_UNLOCK (&type_rw_lock
);
2942 /* G_TYPE_TYPE_PLUGIN
2944 g_type_plugin_get_type ();
2946 /* G_TYPE_* value types
2948 g_value_types_init ();
2950 /* G_TYPE_ENUM & G_TYPE_FLAGS
2952 g_enum_types_init ();
2956 g_boxed_type_init ();
2960 g_param_type_init ();
2964 g_object_type_init ();
2966 /* G_TYPE_PARAM_* pspec types
2968 g_param_spec_types_init ();
2970 /* Value Transformations
2972 g_value_transforms_init ();
2978 G_UNLOCK (type_init_lock
);
2984 g_type_init_with_debug_flags (0);