1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307, USA.
26 #include "gtypeplugin.h"
27 #include "gvaluecollector.h"
31 /* NOTE: some functions (some internal variants and exported ones)
32 * invalidate data portions of the TypeNodes. if external functions/callbacks
33 * are called, pointers to memory maintained by TypeNodes have to be looked up
34 * again. this affects most of the struct TypeNode fields, e.g. ->children or
35 * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
36 * not ->supers[]), as all those memory portions can get realloc()ed during
37 * callback invocation.
40 * - g_type_from_name() should do an ordered array lookup after fetching the
41 * the quark, instead of a second hashtable lookup.
44 * lock handling issues when calling static functions are indicated by
45 * uppercase letter postfixes, all static functions have to have
46 * one of the below postfixes:
47 * - _I: [Indifferent about locking]
48 * function doesn't care about locks at all
49 * - _U: [Unlocked invocation]
50 * no read or write lock has to be held across function invocation
51 * (locks may be acquired and released during invocation though)
52 * - _L: [Locked invocation]
53 * a write lock or more than 0 read locks have to be held across
55 * - _W: [Write-locked invocation]
56 * a write lock has to be held across function invokation
57 * - _Wm: [Write-locked invocation, mutatable]
58 * like _W, but the write lock might be released and reacquired
59 * during invocation, watch your pointers
62 static GStaticRWLock type_rw_lock
= G_STATIC_RW_LOCK_INIT
;
64 #define G_READ_LOCK(rw_lock) do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0)
65 #define G_READ_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0)
66 #define G_WRITE_LOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL++\n"); g_static_rw_lock_writer_lock (rw_lock); } while (0)
67 #define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_static_rw_lock_writer_unlock (rw_lock); } while (0)
69 #define G_READ_LOCK(rw_lock) g_static_rw_lock_reader_lock (rw_lock)
70 #define G_READ_UNLOCK(rw_lock) g_static_rw_lock_reader_unlock (rw_lock)
71 #define G_WRITE_LOCK(rw_lock) g_static_rw_lock_writer_lock (rw_lock)
72 #define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
74 #define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
75 static const gchar *_action = " invalidly modified type "; \
76 gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
78 g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
80 g_error ("%s()%s`%s'", _fname, _action, _tname); \
82 #define g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{ \
85 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
86 "%s: initialization assertion failed, use %s() prior to this function", \
87 G_STRLOC, G_STRINGIFY (init_function)); \
88 return (return_value); \
93 #define DEBUG_CODE(debug_type, code_block) G_STMT_START { \
94 if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
97 #else /* !G_ENABLE_DEBUG */
98 #define DEBUG_CODE(debug_type, code_block) /* code_block */
99 #endif /* G_ENABLE_DEBUG */
101 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
102 G_TYPE_FLAG_INSTANTIATABLE | \
103 G_TYPE_FLAG_DERIVABLE | \
104 G_TYPE_FLAG_DEEP_DERIVABLE)
105 #define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
106 #define SIZEOF_FUNDAMENTAL_INFO ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
107 sizeof (gpointer)), \
111 /* --- typedefs --- */
112 typedef struct _TypeNode TypeNode
;
113 typedef struct _CommonData CommonData
;
114 typedef struct _IFaceData IFaceData
;
115 typedef struct _ClassData ClassData
;
116 typedef struct _InstanceData InstanceData
;
117 typedef union _TypeData TypeData
;
118 typedef struct _IFaceEntry IFaceEntry
;
119 typedef struct _IFaceHolder IFaceHolder
;
122 /* --- prototypes --- */
123 static inline GTypeFundamentalInfo
* type_node_fundamental_info_I (TypeNode
*node
);
124 static void type_add_flags_W (TypeNode
*node
,
126 static void type_data_make_W (TypeNode
*node
,
127 const GTypeInfo
*info
,
128 const GTypeValueTable
*value_table
);
129 static inline void type_data_ref_Wm (TypeNode
*node
);
130 static inline void type_data_unref_Wm (TypeNode
*node
,
132 static void type_data_last_unref_Wm (GType type
,
134 static inline gpointer
type_get_qdata_L (TypeNode
*node
,
136 static inline void type_set_qdata_W (TypeNode
*node
,
139 static IFaceHolder
* type_iface_peek_holder_L (TypeNode
*iface
,
140 GType instance_type
);
141 static gboolean
type_node_is_a_L (TypeNode
*node
,
142 TypeNode
*iface_node
);
145 /* --- structures --- */
149 guint n_children
: 12;
151 guint _prot_n_ifaces_prerequisites
: 9;
152 guint is_classed
: 1;
153 guint is_instantiatable
: 1;
154 guint mutatable_check_cache
: 1; /* combines some common path checks */
156 TypeData
* volatile data
;
160 IFaceEntry
*iface_entries
; /* for !iface types */
161 GType
*prerequisistes
;
163 GType supers
[1]; /* flexible array */
165 #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
166 #define MAX_N_SUPERS (255)
167 #define MAX_N_CHILDREN (4095)
168 #define MAX_N_IFACES (511)
169 #define MAX_N_PREREQUISITES (MAX_N_IFACES)
170 #define NODE_TYPE(node) (node->supers[0])
171 #define NODE_PARENT_TYPE(node) (node->supers[1])
172 #define NODE_FUNDAMENTAL_TYPE(node) (node->supers[node->n_supers])
173 #define NODE_NAME(node) (g_quark_to_string (node->qname))
174 #define NODE_IS_IFACE(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
175 #define CLASSED_NODE_N_IFACES(node) ((node)->_prot_n_ifaces_prerequisites)
176 #define CLASSED_NODE_IFACES_ENTRIES(node) ((node)->_prot.iface_entries)
177 #define IFACE_NODE_N_PREREQUISITES(node) ((node)->_prot_n_ifaces_prerequisites)
178 #define IFACE_NODE_PREREQUISITES(node) ((node)->_prot.prerequisistes)
179 #define iface_node_get_holders_L(node) ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
180 #define iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
181 #define iface_node_get_dependants_array_L(n) ((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
182 #define iface_node_set_dependants_array_W(n,d) (type_set_qdata_W ((n), static_quark_dependants_array, (d)))
183 #define TYPE_ID_MASK ((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1))
189 GInterfaceInfo
*info
;
196 GTypeInterface
*vtable
;
201 GTypeValueTable
*value_table
;
207 GBaseInitFunc vtable_init_base
;
208 GBaseFinalizeFunc vtable_finalize_base
;
214 GBaseInitFunc class_init_base
;
215 GBaseFinalizeFunc class_finalize_base
;
216 GClassInitFunc class_init
;
217 GClassFinalizeFunc class_finalize
;
218 gconstpointer class_data
;
225 GBaseInitFunc class_init_base
;
226 GBaseFinalizeFunc class_finalize_base
;
227 GClassInitFunc class_init
;
228 GClassFinalizeFunc class_finalize
;
229 gconstpointer class_data
;
231 guint16 instance_size
;
233 GInstanceInitFunc instance_init
;
234 GMemChunk
*mem_chunk
;
241 InstanceData instance
;
245 GTypeClassCacheFunc cache_func
;
249 /* --- variables --- */
250 static guint static_n_class_cache_funcs
= 0;
251 static ClassCacheFunc
*static_class_cache_funcs
= NULL
;
252 static GQuark static_quark_type_flags
= 0;
253 static GQuark static_quark_iface_holder
= 0;
254 static GQuark static_quark_dependants_array
= 0;
255 GTypeDebugFlags _g_type_debug_flags
= 0;
258 /* --- type nodes --- */
259 static GHashTable
*static_type_nodes_ht
= NULL
;
260 static TypeNode
*static_fundamental_type_nodes
[(G_TYPE_FUNDAMENTAL_MAX
>> G_TYPE_FUNDAMENTAL_SHIFT
) + 1] = { 0, };
261 static GType static_fundamental_next
= G_TYPE_RESERVED_USER_FIRST
;
263 static inline TypeNode
*
264 lookup_type_node_I (register GType utype
)
266 if (utype
> G_TYPE_FUNDAMENTAL_MAX
)
267 return (TypeNode
*) (utype
& ~TYPE_ID_MASK
);
269 return static_fundamental_type_nodes
[utype
>> G_TYPE_FUNDAMENTAL_SHIFT
];
273 type_node_any_new_W (TypeNode
*pnode
,
277 GTypeFundamentalFlags type_flags
)
282 guint i
, node_size
= 0;
284 n_supers
= pnode
? pnode
->n_supers
+ 1 : 0;
287 node_size
+= SIZEOF_FUNDAMENTAL_INFO
; /* fundamental type info */
288 node_size
+= SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
289 node_size
+= (sizeof (GType
) * (1 + n_supers
+ 1)); /* self + ancestors + (0) for ->supers[] */
290 node
= g_malloc0 (node_size
);
291 if (!pnode
) /* offset fundamental types */
293 node
= G_STRUCT_MEMBER_P (node
, SIZEOF_FUNDAMENTAL_INFO
);
294 static_fundamental_type_nodes
[ftype
>> G_TYPE_FUNDAMENTAL_SHIFT
] = node
;
300 g_assert ((type
& TYPE_ID_MASK
) == 0);
302 node
->n_supers
= n_supers
;
305 node
->supers
[0] = type
;
308 node
->is_classed
= (type_flags
& G_TYPE_FLAG_CLASSED
) != 0;
309 node
->is_instantiatable
= (type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) != 0;
311 if (NODE_IS_IFACE (node
))
313 IFACE_NODE_N_PREREQUISITES (node
) = 0;
314 IFACE_NODE_PREREQUISITES (node
) = NULL
;
318 CLASSED_NODE_N_IFACES (node
) = 0;
319 CLASSED_NODE_IFACES_ENTRIES (node
) = NULL
;
324 node
->supers
[0] = type
;
325 memcpy (node
->supers
+ 1, pnode
->supers
, sizeof (GType
) * (1 + pnode
->n_supers
+ 1));
327 node
->is_classed
= pnode
->is_classed
;
328 node
->is_instantiatable
= pnode
->is_instantiatable
;
330 if (NODE_IS_IFACE (node
))
332 IFACE_NODE_N_PREREQUISITES (node
) = 0;
333 IFACE_NODE_PREREQUISITES (node
) = NULL
;
339 CLASSED_NODE_N_IFACES (node
) = CLASSED_NODE_N_IFACES (pnode
);
340 CLASSED_NODE_IFACES_ENTRIES (node
) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode
),
341 sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode
)[0]) *
342 CLASSED_NODE_N_IFACES (node
));
343 for (j
= 0; j
< CLASSED_NODE_N_IFACES (node
); j
++)
344 CLASSED_NODE_IFACES_ENTRIES (node
)[j
].vtable
= NULL
;
347 i
= pnode
->n_children
++;
348 pnode
->children
= g_renew (GType
, pnode
->children
, pnode
->n_children
);
349 pnode
->children
[i
] = type
;
352 node
->plugin
= plugin
;
353 node
->n_children
= 0;
354 node
->children
= NULL
;
356 node
->qname
= g_quark_from_string (name
);
357 node
->global_gdata
= NULL
;
359 g_hash_table_insert (static_type_nodes_ht
,
360 GUINT_TO_POINTER (node
->qname
),
365 static inline GTypeFundamentalInfo
*
366 type_node_fundamental_info_I (TypeNode
*node
)
368 GType ftype
= NODE_FUNDAMENTAL_TYPE (node
);
370 if (ftype
!= NODE_TYPE (node
))
371 node
= lookup_type_node_I (ftype
);
373 return node
? G_STRUCT_MEMBER_P (node
, -SIZEOF_FUNDAMENTAL_INFO
) : NULL
;
377 type_node_fundamental_new_W (GType ftype
,
379 GTypeFundamentalFlags type_flags
)
381 GTypeFundamentalInfo
*finfo
;
384 g_assert ((ftype
& TYPE_ID_MASK
) == 0);
385 g_assert (ftype
<= G_TYPE_FUNDAMENTAL_MAX
);
387 if (ftype
>> G_TYPE_FUNDAMENTAL_SHIFT
== static_fundamental_next
)
388 static_fundamental_next
++;
390 type_flags
&= TYPE_FUNDAMENTAL_FLAG_MASK
;
392 node
= type_node_any_new_W (NULL
, ftype
, name
, NULL
, type_flags
);
394 finfo
= type_node_fundamental_info_I (node
);
395 finfo
->type_flags
= type_flags
;
401 type_node_new_W (TypeNode
*pnode
,
407 g_assert (pnode
->n_supers
< MAX_N_SUPERS
);
408 g_assert (pnode
->n_children
< MAX_N_CHILDREN
);
410 return type_node_any_new_W (pnode
, NODE_FUNDAMENTAL_TYPE (pnode
), name
, plugin
, 0);
413 static inline IFaceEntry
*
414 type_lookup_iface_entry_L (TypeNode
*node
,
415 TypeNode
*iface_node
)
417 if (NODE_IS_IFACE (iface_node
) && CLASSED_NODE_N_IFACES (node
))
419 IFaceEntry
*ifaces
= CLASSED_NODE_IFACES_ENTRIES (node
) - 1;
420 guint n_ifaces
= CLASSED_NODE_N_IFACES (node
);
421 GType iface_type
= NODE_TYPE (iface_node
);
428 i
= (n_ifaces
+ 1) >> 1;
430 if (iface_type
== check
->iface_type
)
432 else if (iface_type
> check
->iface_type
)
437 else /* if (iface_type < check->iface_type) */
446 static inline gboolean
447 type_lookup_prerequisite_L (TypeNode
*iface
,
448 GType prerequisite_type
)
450 if (NODE_IS_IFACE (iface
) && IFACE_NODE_N_PREREQUISITES (iface
))
452 GType
*prerequisites
= IFACE_NODE_PREREQUISITES (iface
) - 1;
453 guint n_prerequisites
= IFACE_NODE_N_PREREQUISITES (iface
);
460 i
= (n_prerequisites
+ 1) >> 1;
461 check
= prerequisites
+ i
;
462 if (prerequisite_type
== *check
)
464 else if (prerequisite_type
> *check
)
466 n_prerequisites
-= i
;
467 prerequisites
= check
;
469 else /* if (prerequisite_type < *check) */
470 n_prerequisites
= i
- 1;
472 while (n_prerequisites
);
478 type_descriptive_name_I (GType type
)
482 TypeNode
*node
= lookup_type_node_I (type
);
484 return node
? NODE_NAME (node
) : "<unknown>";
491 /* --- type consistency checks --- */
493 check_plugin_U (GTypePlugin
*plugin
,
494 gboolean need_complete_type_info
,
495 gboolean need_complete_interface_info
,
496 const gchar
*type_name
)
498 /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U
502 g_warning ("plugin handle for type `%s' is NULL",
506 if (!G_IS_TYPE_PLUGIN (plugin
))
508 g_warning ("plugin pointer (%p) for type `%s' is invalid",
512 if (need_complete_type_info
&& !G_TYPE_PLUGIN_GET_CLASS (plugin
)->complete_type_info
)
514 g_warning ("plugin for type `%s' has no complete_type_info() implementation",
518 if (need_complete_interface_info
&& !G_TYPE_PLUGIN_GET_CLASS (plugin
)->complete_interface_info
)
520 g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
528 check_type_name_I (const gchar
*type_name
)
530 static const gchar
*extra_chars
= "-_+";
531 const gchar
*p
= type_name
;
534 if (!type_name
[0] || !type_name
[1] || !type_name
[2])
536 g_warning ("type name `%s' is too short", type_name
);
539 /* check the first letter */
540 name_valid
= (p
[0] >= 'A' && p
[0] <= 'Z') || (p
[0] >= 'a' && p
[0] <= 'z') || p
[0] == '_';
541 for (p
= type_name
+ 1; *p
; p
++)
542 name_valid
&= ((p
[0] >= 'A' && p
[0] <= 'Z') ||
543 (p
[0] >= 'a' && p
[0] <= 'z') ||
544 (p
[0] >= '0' && p
[0] <= '9') ||
545 strchr (extra_chars
, p
[0]));
548 g_warning ("type name `%s' contains invalid characters", type_name
);
551 if (g_type_from_name (type_name
))
553 g_warning ("cannot register existing type `%s'", type_name
);
561 check_derivation_I (GType parent_type
,
562 const gchar
*type_name
)
565 GTypeFundamentalInfo
* finfo
;
567 pnode
= lookup_type_node_I (parent_type
);
570 g_warning ("cannot derive type `%s' from invalid parent type `%s'",
572 type_descriptive_name_I (parent_type
));
575 finfo
= type_node_fundamental_info_I (pnode
);
576 /* ensure flat derivability */
577 if (!(finfo
->type_flags
& G_TYPE_FLAG_DERIVABLE
))
579 g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
584 /* ensure deep derivability */
585 if (parent_type
!= NODE_FUNDAMENTAL_TYPE (pnode
) &&
586 !(finfo
->type_flags
& G_TYPE_FLAG_DEEP_DERIVABLE
))
588 g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
598 check_collect_format_I (const gchar
*collect_format
)
600 const gchar
*p
= collect_format
;
601 gchar valid_format
[] = { G_VALUE_COLLECT_INT
, G_VALUE_COLLECT_LONG
,
602 G_VALUE_COLLECT_INT64
, G_VALUE_COLLECT_DOUBLE
,
603 G_VALUE_COLLECT_POINTER
, 0 };
606 if (!strchr (valid_format
, *p
++))
608 return p
- collect_format
<= G_VALUE_COLLECT_FORMAT_MAX_LENGTH
;
612 check_value_table_I (const gchar
*type_name
,
613 const GTypeValueTable
*value_table
)
617 else if (value_table
->value_init
== NULL
)
619 if (value_table
->value_free
|| value_table
->value_copy
||
620 value_table
->value_peek_pointer
||
621 value_table
->collect_format
|| value_table
->collect_value
||
622 value_table
->lcopy_format
|| value_table
->lcopy_value
)
623 g_warning ("cannot handle uninitializable values of type `%s'",
627 else /* value_table->value_init != NULL */
629 if (!value_table
->value_free
)
632 * g_warning ("missing `value_free()' for type `%s'", type_name);
636 if (!value_table
->value_copy
)
638 g_warning ("missing `value_copy()' for type `%s'", type_name
);
641 if ((value_table
->collect_format
|| value_table
->collect_value
) &&
642 (!value_table
->collect_format
|| !value_table
->collect_value
))
644 g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
648 if (value_table
->collect_format
&& !check_collect_format_I (value_table
->collect_format
))
650 g_warning ("the `%s' specification for type `%s' is too long or invalid",
655 if ((value_table
->lcopy_format
|| value_table
->lcopy_value
) &&
656 (!value_table
->lcopy_format
|| !value_table
->lcopy_value
))
658 g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
662 if (value_table
->lcopy_format
&& !check_collect_format_I (value_table
->lcopy_format
))
664 g_warning ("the `%s' specification for type `%s' is too long or invalid",
674 check_type_info_I (TypeNode
*pnode
,
676 const gchar
*type_name
,
677 const GTypeInfo
*info
)
679 GTypeFundamentalInfo
*finfo
= type_node_fundamental_info_I (lookup_type_node_I (ftype
));
680 gboolean is_interface
= ftype
== G_TYPE_INTERFACE
;
682 g_assert (ftype
<= G_TYPE_FUNDAMENTAL_MAX
&& !(ftype
& TYPE_ID_MASK
));
684 /* check instance members */
685 if (!(finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) &&
686 (info
->instance_size
|| info
->n_preallocs
|| info
->instance_init
))
689 g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
693 g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
697 /* check class & interface members */
698 if (!(finfo
->type_flags
& G_TYPE_FLAG_CLASSED
) &&
699 (info
->class_init
|| info
->class_finalize
|| info
->class_data
||
700 (!is_interface
&& (info
->class_size
|| info
->base_init
|| info
->base_finalize
))))
703 g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
707 g_warning ("cannot create class for `%s' as non-classed fundamental",
711 /* check interface size */
712 if (is_interface
&& info
->class_size
< sizeof (GTypeInterface
))
714 g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
718 /* check class size */
719 if (finfo
->type_flags
& G_TYPE_FLAG_CLASSED
)
721 if (info
->class_size
< sizeof (GTypeClass
))
723 g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
727 if (pnode
&& info
->class_size
< pnode
->data
->class.class_size
)
729 g_warning ("specified class size for type `%s' is smaller "
730 "than the parent type's `%s' class size",
736 /* check instance size */
737 if (finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
)
739 if (info
->instance_size
< sizeof (GTypeInstance
))
741 g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
745 if (pnode
&& info
->instance_size
< pnode
->data
->instance
.instance_size
)
747 g_warning ("specified instance size for type `%s' is smaller "
748 "than the parent type's `%s' instance size",
759 find_conforming_child_type_L (TypeNode
*pnode
,
762 TypeNode
*node
= NULL
;
765 if (type_lookup_iface_entry_L (pnode
, iface
))
768 for (i
= 0; i
< pnode
->n_children
&& !node
; i
++)
769 node
= find_conforming_child_type_L (lookup_type_node_I (pnode
->children
[i
]), iface
);
775 check_add_interface_L (GType instance_type
,
778 TypeNode
*node
= lookup_type_node_I (instance_type
);
779 TypeNode
*iface
= lookup_type_node_I (iface_type
);
782 GType
*prerequisites
;
786 if (!node
|| !node
->is_instantiatable
)
788 g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
789 type_descriptive_name_I (instance_type
));
792 if (!iface
|| !NODE_IS_IFACE (iface
))
794 g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
795 type_descriptive_name_I (iface_type
),
799 tnode
= lookup_type_node_I (NODE_PARENT_TYPE (iface
));
800 if (NODE_PARENT_TYPE (tnode
) && !type_lookup_iface_entry_L (node
, tnode
))
802 /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
803 g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
809 /* allow overriding of interface type introduced for parent type */
810 entry
= type_lookup_iface_entry_L (node
, iface
);
811 if (entry
&& entry
->vtable
== NULL
&& !type_iface_peek_holder_L (iface
, NODE_TYPE (node
)))
813 /* ok, we do conform to this interface already, but the interface vtable was not
814 * yet intialized, and we just conform to the interface because it got added to
815 * one of our parents. so we allow overriding of holder info here.
819 /* check whether one of our children already conforms (or whether the interface
820 * got added to this node already)
822 tnode
= find_conforming_child_type_L (node
, iface
); /* tnode is_a node */
825 g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
831 prerequisites
= IFACE_NODE_PREREQUISITES (iface
);
832 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
834 tnode
= lookup_type_node_I (prerequisites
[i
]);
835 if (!type_node_is_a_L (node
, tnode
))
837 g_warning ("cannot add interface type `%s' to type `%s' which does not conform to prerequisite `%s'",
848 check_interface_info_I (TypeNode
*iface
,
850 const GInterfaceInfo
*info
)
852 if ((info
->interface_finalize
|| info
->interface_data
) && !info
->interface_init
)
854 g_warning ("interface type `%s' for type `%s' comes without initializer",
856 type_descriptive_name_I (instance_type
));
863 /* --- type info (type node data) --- */
865 type_data_make_W (TypeNode
*node
,
866 const GTypeInfo
*info
,
867 const GTypeValueTable
*value_table
)
870 GTypeValueTable
*vtable
= NULL
;
871 guint vtable_size
= 0;
873 g_assert (node
->data
== NULL
&& info
!= NULL
);
877 TypeNode
*pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
880 vtable
= pnode
->data
->common
.value_table
;
883 static const GTypeValueTable zero_vtable
= { NULL
, };
885 value_table
= &zero_vtable
;
890 /* need to setup vtable_size since we have to allocate it with data in one chunk */
891 vtable_size
= sizeof (GTypeValueTable
);
892 if (value_table
->collect_format
)
893 vtable_size
+= strlen (value_table
->collect_format
);
894 if (value_table
->lcopy_format
)
895 vtable_size
+= strlen (value_table
->lcopy_format
);
899 if (node
->is_instantiatable
) /* carefull, is_instantiatable is also is_classed */
901 data
= g_malloc0 (sizeof (InstanceData
) + vtable_size
);
903 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (InstanceData
));
904 data
->instance
.class_size
= info
->class_size
;
905 data
->instance
.class_init_base
= info
->base_init
;
906 data
->instance
.class_finalize_base
= info
->base_finalize
;
907 data
->instance
.class_init
= info
->class_init
;
908 data
->instance
.class_finalize
= info
->class_finalize
;
909 data
->instance
.class_data
= info
->class_data
;
910 data
->instance
.class = NULL
;
911 data
->instance
.instance_size
= info
->instance_size
;
912 #ifdef DISABLE_MEM_POOLS
913 data
->instance
.n_preallocs
= 0;
914 #else /* !DISABLE_MEM_POOLS */
915 data
->instance
.n_preallocs
= MIN (info
->n_preallocs
, 1024);
916 #endif /* !DISABLE_MEM_POOLS */
917 data
->instance
.instance_init
= info
->instance_init
;
918 data
->instance
.mem_chunk
= NULL
;
920 else if (node
->is_classed
) /* only classed */
922 data
= g_malloc0 (sizeof (ClassData
) + vtable_size
);
924 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (ClassData
));
925 data
->class.class_size
= info
->class_size
;
926 data
->class.class_init_base
= info
->base_init
;
927 data
->class.class_finalize_base
= info
->base_finalize
;
928 data
->class.class_init
= info
->class_init
;
929 data
->class.class_finalize
= info
->class_finalize
;
930 data
->class.class_data
= info
->class_data
;
931 data
->class.class = NULL
;
933 else if (NODE_IS_IFACE (node
))
935 data
= g_malloc0 (sizeof (IFaceData
) + vtable_size
);
937 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (IFaceData
));
938 data
->iface
.vtable_size
= info
->class_size
;
939 data
->iface
.vtable_init_base
= info
->base_init
;
940 data
->iface
.vtable_finalize_base
= info
->base_finalize
;
944 data
= g_malloc0 (sizeof (CommonData
) + vtable_size
);
946 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (CommonData
));
950 node
->data
->common
.ref_count
= 1;
956 /* we allocate the vtable and its strings together with the type data, so
957 * children can take over their parent's vtable pointer, and we don't
958 * need to worry freeing it or not when the child data is destroyed
960 *vtable
= *value_table
;
961 p
= G_STRUCT_MEMBER_P (vtable
, sizeof (*vtable
));
963 vtable
->collect_format
= p
;
964 if (value_table
->collect_format
)
966 strcat (p
, value_table
->collect_format
);
967 p
+= strlen (value_table
->collect_format
);
971 vtable
->lcopy_format
= p
;
972 if (value_table
->lcopy_format
)
973 strcat (p
, value_table
->lcopy_format
);
975 node
->data
->common
.value_table
= vtable
;
976 node
->mutatable_check_cache
= (node
->data
->common
.value_table
->value_init
!= NULL
&&
977 !((G_TYPE_FLAG_VALUE_ABSTRACT
| G_TYPE_FLAG_ABSTRACT
) &
978 GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
))));
980 g_assert (node
->data
->common
.value_table
!= NULL
); /* paranoid */
984 type_data_ref_Wm (TypeNode
*node
)
988 TypeNode
*pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
990 GTypeValueTable tmp_value_table
;
992 g_assert (node
->plugin
!= NULL
);
996 type_data_ref_Wm (pnode
);
998 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
1001 memset (&tmp_info
, 0, sizeof (tmp_info
));
1002 memset (&tmp_value_table
, 0, sizeof (tmp_value_table
));
1004 G_WRITE_UNLOCK (&type_rw_lock
);
1005 g_type_plugin_use (node
->plugin
);
1006 g_type_plugin_complete_type_info (node
->plugin
, NODE_TYPE (node
), &tmp_info
, &tmp_value_table
);
1007 G_WRITE_LOCK (&type_rw_lock
);
1009 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
1011 check_type_info_I (pnode
, NODE_FUNDAMENTAL_TYPE (node
), NODE_NAME (node
), &tmp_info
);
1012 type_data_make_W (node
, &tmp_info
,
1013 check_value_table_I (NODE_NAME (node
),
1014 &tmp_value_table
) ? &tmp_value_table
: NULL
);
1018 g_assert (node
->data
->common
.ref_count
> 0);
1020 node
->data
->common
.ref_count
+= 1;
1025 type_data_unref_Wm (TypeNode
*node
,
1028 g_assert (node
->data
&& node
->data
->common
.ref_count
);
1030 if (node
->data
->common
.ref_count
> 1)
1031 node
->data
->common
.ref_count
-= 1;
1036 g_warning ("static type `%s' unreferenced too often",
1041 type_data_last_unref_Wm (NODE_TYPE (node
), uncached
);
1046 type_node_add_iface_entry_W (TypeNode
*node
,
1049 IFaceEntry
*entries
;
1052 g_assert (node
->is_instantiatable
&& CLASSED_NODE_N_IFACES (node
) < MAX_N_IFACES
);
1054 entries
= CLASSED_NODE_IFACES_ENTRIES (node
);
1055 for (i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1056 if (entries
[i
].iface_type
== iface_type
)
1058 /* this can (should) only happen if our parent type already conformed
1059 * to iface_type and node got it's own holder info. here, our
1060 * children should already have entries with NULL vtables, so
1061 * we're actually done.
1063 g_assert (entries
[i
].vtable
== NULL
);
1066 else if (entries
[i
].iface_type
> iface_type
)
1068 CLASSED_NODE_N_IFACES (node
) += 1;
1069 CLASSED_NODE_IFACES_ENTRIES (node
) = g_renew (IFaceEntry
,
1070 CLASSED_NODE_IFACES_ENTRIES (node
),
1071 CLASSED_NODE_N_IFACES (node
));
1072 entries
= CLASSED_NODE_IFACES_ENTRIES (node
);
1073 g_memmove (entries
+ i
+ 1, entries
+ i
, sizeof (entries
[0]) * (CLASSED_NODE_N_IFACES (node
) - i
- 1));
1074 entries
[i
].iface_type
= iface_type
;
1075 entries
[i
].vtable
= NULL
;
1077 for (i
= 0; i
< node
->n_children
; i
++)
1078 type_node_add_iface_entry_W (lookup_type_node_I (node
->children
[i
]), iface_type
);
1082 type_add_interface_W (TypeNode
*node
,
1084 const GInterfaceInfo
*info
,
1085 GTypePlugin
*plugin
)
1087 IFaceHolder
*iholder
= g_new0 (IFaceHolder
, 1);
1089 /* we must not call any functions of GInterfaceInfo from within here, since
1090 * we got most probably called from _within_ a type registration function
1092 g_assert (node
->is_instantiatable
&& NODE_IS_IFACE (iface
) && ((info
&& !plugin
) || (!info
&& plugin
)));
1094 iholder
->next
= iface_node_get_holders_L (iface
);
1095 iface_node_set_holders_W (iface
, iholder
);
1096 iholder
->instance_type
= NODE_TYPE (node
);
1097 iholder
->info
= info
? g_memdup (info
, sizeof (*info
)) : NULL
;
1098 iholder
->plugin
= plugin
;
1100 type_node_add_iface_entry_W (node
, NODE_TYPE (iface
));
1104 type_iface_add_prerequisite_W (TypeNode
*iface
,
1105 TypeNode
*prerequisite_node
)
1107 GType prerequisite_type
= NODE_TYPE (prerequisite_node
);
1108 GType
*prerequisites
, *dependants
;
1109 guint n_dependants
, i
;
1111 g_assert (NODE_IS_IFACE (iface
) &&
1112 IFACE_NODE_N_PREREQUISITES (iface
) < MAX_N_PREREQUISITES
&&
1113 (prerequisite_node
->is_instantiatable
|| NODE_IS_IFACE (prerequisite_node
)));
1115 prerequisites
= IFACE_NODE_PREREQUISITES (iface
);
1116 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
1117 if (prerequisites
[i
] == prerequisite_type
)
1118 return; /* we already have that prerequisiste */
1119 else if (prerequisites
[i
] > prerequisite_type
)
1121 IFACE_NODE_N_PREREQUISITES (iface
) += 1;
1122 IFACE_NODE_PREREQUISITES (iface
) = g_renew (GType
,
1123 IFACE_NODE_PREREQUISITES (iface
),
1124 IFACE_NODE_N_PREREQUISITES (iface
));
1125 prerequisites
= IFACE_NODE_PREREQUISITES (iface
);
1126 g_memmove (prerequisites
+ i
+ 1, prerequisites
+ i
,
1127 sizeof (prerequisites
[0]) * (IFACE_NODE_N_PREREQUISITES (iface
) - i
- 1));
1128 prerequisites
[i
] = prerequisite_type
;
1130 /* we want to get notified when prerequisites get added to prerequisite_node */
1131 if (NODE_IS_IFACE (prerequisite_node
))
1133 dependants
= iface_node_get_dependants_array_L (prerequisite_node
);
1134 n_dependants
= dependants
? dependants
[0] : 0;
1136 dependants
= g_renew (GType
, dependants
, n_dependants
+ 1);
1137 dependants
[n_dependants
] = NODE_TYPE (iface
);
1138 dependants
[0] = n_dependants
;
1139 iface_node_set_dependants_array_W (prerequisite_node
, dependants
);
1142 /* we need to notify all dependants */
1143 dependants
= iface_node_get_dependants_array_L (iface
);
1144 n_dependants
= dependants
? dependants
[0] : 0;
1145 for (i
= 1; i
<= n_dependants
; i
++)
1146 type_iface_add_prerequisite_W (lookup_type_node_I (dependants
[i
]), prerequisite_node
);
1150 * g_type_interface_add_prerequisite:
1151 * @interface_type: #GType value of an interface type.
1152 * @prerequisite_type: #GType value of an interface or instantiatable type.
1154 * Adds @prerequisite_type to the list of prerequisites of @interface_type.
1155 * This means that any type implementing @interface_type must also implement
1156 * @prerequisite_type. Prerequisites can be thought of as an alternative to
1157 * interface derivation (which GType doesn't support). An interface can have
1158 * at most one instantiatable prerequisite type.
1161 g_type_interface_add_prerequisite (GType interface_type
,
1162 GType prerequisite_type
)
1164 TypeNode
*iface
, *prerequisite_node
;
1165 IFaceHolder
*holders
;
1167 g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type
)); /* G_TYPE_IS_INTERFACE() is an external call: _U */
1168 g_return_if_fail (!g_type_is_a (interface_type
, prerequisite_type
));
1169 g_return_if_fail (!g_type_is_a (prerequisite_type
, interface_type
));
1171 iface
= lookup_type_node_I (interface_type
);
1172 prerequisite_node
= lookup_type_node_I (prerequisite_type
);
1173 if (!iface
|| !prerequisite_node
|| !NODE_IS_IFACE (iface
))
1175 g_warning ("interface type `%s' or prerequisite type `%s' invalid",
1176 type_descriptive_name_I (interface_type
),
1177 type_descriptive_name_I (prerequisite_type
));
1180 G_WRITE_LOCK (&type_rw_lock
);
1181 holders
= iface_node_get_holders_L (iface
);
1184 G_WRITE_UNLOCK (&type_rw_lock
);
1185 g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'",
1186 type_descriptive_name_I (prerequisite_type
),
1187 type_descriptive_name_I (interface_type
),
1188 type_descriptive_name_I (holders
->instance_type
));
1191 if (prerequisite_node
->is_instantiatable
)
1195 /* can have at most one publically installable instantiatable prerequisite */
1196 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
1198 TypeNode
*prnode
= lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface
)[i
]);
1200 if (prnode
->is_instantiatable
)
1202 G_WRITE_UNLOCK (&type_rw_lock
);
1203 g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
1204 type_descriptive_name_I (prerequisite_type
),
1205 type_descriptive_name_I (interface_type
),
1206 type_descriptive_name_I (NODE_TYPE (prnode
)));
1211 for (i
= 0; i
< prerequisite_node
->n_supers
+ 1; i
++)
1212 type_iface_add_prerequisite_W (iface
, lookup_type_node_I (prerequisite_node
->supers
[i
]));
1213 G_WRITE_UNLOCK (&type_rw_lock
);
1215 else if (NODE_IS_IFACE (prerequisite_node
))
1217 GType
*prerequisites
;
1220 prerequisites
= IFACE_NODE_PREREQUISITES (prerequisite_node
);
1221 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (prerequisite_node
); i
++)
1222 type_iface_add_prerequisite_W (iface
, lookup_type_node_I (prerequisites
[i
]));
1223 type_iface_add_prerequisite_W (iface
, prerequisite_node
);
1224 G_WRITE_UNLOCK (&type_rw_lock
);
1228 G_WRITE_UNLOCK (&type_rw_lock
);
1229 g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface",
1230 type_descriptive_name_I (prerequisite_type
),
1231 type_descriptive_name_I (interface_type
));
1236 * g_type_interface_prerequisites:
1237 * @interface_type: an interface type
1238 * @n_prerequisites: location to return the number of prerequisites, or %NULL
1240 * Returns the prerequisites of an interfaces type.
1242 * Return value: a newly-allocated zero-terminated array of #GType containing
1243 * the prerequisites of @interface_type
1247 GType
* /* free result */
1248 g_type_interface_prerequisites (GType interface_type
,
1249 guint
*n_prerequisites
)
1253 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type
), NULL
);
1255 iface
= lookup_type_node_I (interface_type
);
1259 TypeNode
*inode
= NULL
;
1262 G_READ_LOCK (&type_rw_lock
);
1263 types
= g_new0 (GType
, IFACE_NODE_N_PREREQUISITES (iface
) + 1);
1264 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
1266 GType prerequisite
= IFACE_NODE_PREREQUISITES (iface
)[i
];
1267 TypeNode
*node
= lookup_type_node_I (prerequisite
);
1268 if (node
->is_instantiatable
&&
1269 (!inode
|| type_node_is_a_L (node
, inode
)))
1272 types
[n
++] = NODE_TYPE (node
);
1275 types
[n
++] = NODE_TYPE (inode
);
1277 if (n_prerequisites
)
1278 *n_prerequisites
= n
;
1279 G_READ_UNLOCK (&type_rw_lock
);
1285 if (n_prerequisites
)
1286 *n_prerequisites
= 0;
1294 type_iface_peek_holder_L (TypeNode
*iface
,
1295 GType instance_type
)
1297 IFaceHolder
*iholder
;
1299 g_assert (NODE_IS_IFACE (iface
));
1301 iholder
= iface_node_get_holders_L (iface
);
1302 while (iholder
&& iholder
->instance_type
!= instance_type
)
1303 iholder
= iholder
->next
;
1308 type_iface_retrieve_holder_info_Wm (TypeNode
*iface
,
1309 GType instance_type
,
1312 IFaceHolder
*iholder
= type_iface_peek_holder_L (iface
, instance_type
);
1314 if (iholder
&& !iholder
->info
&& need_info
)
1316 GInterfaceInfo tmp_info
;
1318 g_assert (iholder
->plugin
!= NULL
);
1320 type_data_ref_Wm (iface
);
1322 INVALID_RECURSION ("g_type_plugin_*", iface
->plugin
, NODE_NAME (iface
));
1324 memset (&tmp_info
, 0, sizeof (tmp_info
));
1326 G_WRITE_UNLOCK (&type_rw_lock
);
1327 g_type_plugin_use (iholder
->plugin
);
1328 g_type_plugin_complete_interface_info (iholder
->plugin
, instance_type
, NODE_TYPE (iface
), &tmp_info
);
1329 G_WRITE_LOCK (&type_rw_lock
);
1331 INVALID_RECURSION ("g_type_plugin_*", iholder
->plugin
, NODE_NAME (iface
));
1333 check_interface_info_I (iface
, instance_type
, &tmp_info
);
1334 iholder
->info
= g_memdup (&tmp_info
, sizeof (tmp_info
));
1337 return iholder
; /* we don't modify write lock upon returning NULL */
1341 type_iface_blow_holder_info_Wm (TypeNode
*iface
,
1342 GType instance_type
)
1344 IFaceHolder
*iholder
= iface_node_get_holders_L (iface
);
1346 g_assert (NODE_IS_IFACE (iface
));
1348 while (iholder
->instance_type
!= instance_type
)
1349 iholder
= iholder
->next
;
1351 if (iholder
->info
&& iholder
->plugin
)
1353 g_free (iholder
->info
);
1354 iholder
->info
= NULL
;
1356 G_WRITE_UNLOCK (&type_rw_lock
);
1357 g_type_plugin_unuse (iholder
->plugin
);
1358 G_WRITE_LOCK (&type_rw_lock
);
1360 type_data_unref_Wm (iface
, FALSE
);
1365 /* --- type structure creation/destruction --- */
1367 g_type_create_instance (GType type
)
1370 GTypeInstance
*instance
;
1374 node
= lookup_type_node_I (type
);
1375 if (!node
|| !node
->is_instantiatable
)
1377 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1378 type_descriptive_name_I (type
));
1381 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1382 if (!node
->mutatable_check_cache
&& G_TYPE_IS_ABSTRACT (type
))
1384 g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1385 type_descriptive_name_I (type
));
1389 class = g_type_class_ref (type
);
1391 if (node
->data
->instance
.n_preallocs
)
1393 G_WRITE_LOCK (&type_rw_lock
);
1394 if (!node
->data
->instance
.mem_chunk
)
1395 node
->data
->instance
.mem_chunk
= g_mem_chunk_new (NODE_NAME (node
),
1396 node
->data
->instance
.instance_size
,
1397 (node
->data
->instance
.instance_size
*
1398 node
->data
->instance
.n_preallocs
),
1400 instance
= g_chunk_new0 (GTypeInstance
, node
->data
->instance
.mem_chunk
);
1401 G_WRITE_UNLOCK (&type_rw_lock
);
1404 instance
= g_malloc0 (node
->data
->instance
.instance_size
); /* fine without read lock */
1405 for (i
= node
->n_supers
; i
> 0; i
--)
1409 pnode
= lookup_type_node_I (node
->supers
[i
]);
1410 if (pnode
->data
->instance
.instance_init
)
1412 instance
->g_class
= pnode
->data
->instance
.class;
1413 pnode
->data
->instance
.instance_init (instance
, class);
1416 instance
->g_class
= class;
1418 if (node
->data
->instance
.instance_init
)
1419 node
->data
->instance
.instance_init (instance
, class);
1425 g_type_free_instance (GTypeInstance
*instance
)
1430 g_return_if_fail (instance
!= NULL
&& instance
->g_class
!= NULL
);
1432 class = instance
->g_class
;
1433 node
= lookup_type_node_I (class->g_type
);
1434 if (!node
|| !node
->is_instantiatable
|| !node
->data
|| node
->data
->class.class != (gpointer
) class)
1436 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1437 type_descriptive_name_I (class->g_type
));
1440 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1441 if (!node
->mutatable_check_cache
&& G_TYPE_IS_ABSTRACT (NODE_TYPE (node
)))
1443 g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1448 instance
->g_class
= NULL
;
1449 #ifdef G_ENABLE_DEBUG
1450 memset (instance
, 0xaa, node
->data
->instance
.instance_size
); /* debugging hack */
1452 if (node
->data
->instance
.n_preallocs
)
1454 G_WRITE_LOCK (&type_rw_lock
);
1455 g_chunk_free (instance
, node
->data
->instance
.mem_chunk
);
1456 G_WRITE_UNLOCK (&type_rw_lock
);
1461 g_type_class_unref (class);
1465 type_iface_vtable_init_Wm (TypeNode
*iface
,
1468 IFaceEntry
*entry
= type_lookup_iface_entry_L (node
, iface
);
1469 IFaceHolder
*iholder
;
1470 GTypeInterface
*vtable
= NULL
;
1473 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1474 iholder
= type_iface_retrieve_holder_info_Wm (iface
, NODE_TYPE (node
), TRUE
);
1476 return FALSE
; /* we don't modify write lock upon FALSE */
1478 g_assert (iface
->data
&& entry
&& entry
->vtable
== NULL
&& iholder
&& iholder
->info
);
1480 pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
1481 if (pnode
) /* want to copy over parent iface contents */
1483 IFaceEntry
*pentry
= type_lookup_iface_entry_L (pnode
, iface
);
1486 vtable
= g_memdup (pentry
->vtable
, iface
->data
->iface
.vtable_size
);
1489 vtable
= g_malloc0 (iface
->data
->iface
.vtable_size
);
1490 entry
->vtable
= vtable
;
1491 vtable
->g_type
= NODE_TYPE (iface
);
1492 vtable
->g_instance_type
= NODE_TYPE (node
);
1494 if (iface
->data
->iface
.vtable_init_base
|| iholder
->info
->interface_init
)
1496 G_WRITE_UNLOCK (&type_rw_lock
);
1497 if (iface
->data
->iface
.vtable_init_base
)
1498 iface
->data
->iface
.vtable_init_base (vtable
);
1499 if (iholder
->info
->interface_init
)
1500 iholder
->info
->interface_init (vtable
, iholder
->info
->interface_data
);
1501 G_WRITE_LOCK (&type_rw_lock
);
1503 return TRUE
; /* write lock modified */
1507 type_iface_vtable_finalize_Wm (TypeNode
*iface
,
1509 GTypeInterface
*vtable
)
1511 IFaceEntry
*entry
= type_lookup_iface_entry_L (node
, iface
);
1512 IFaceHolder
*iholder
;
1514 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1515 iholder
= type_iface_retrieve_holder_info_Wm (iface
, NODE_TYPE (node
), FALSE
);
1517 return FALSE
; /* we don't modify write lock upon FALSE */
1519 g_assert (entry
&& entry
->vtable
== vtable
&& iholder
->info
);
1521 entry
->vtable
= NULL
;
1522 if (iholder
->info
->interface_finalize
|| iface
->data
->iface
.vtable_finalize_base
)
1524 G_WRITE_UNLOCK (&type_rw_lock
);
1525 if (iholder
->info
->interface_finalize
)
1526 iholder
->info
->interface_finalize (vtable
, iholder
->info
->interface_data
);
1527 if (iface
->data
->iface
.vtable_finalize_base
)
1528 iface
->data
->iface
.vtable_finalize_base (vtable
);
1529 G_WRITE_LOCK (&type_rw_lock
);
1532 vtable
->g_instance_type
= 0;
1535 type_iface_blow_holder_info_Wm (iface
, NODE_TYPE (node
));
1537 return TRUE
; /* write lock modified */
1541 type_class_init_Wm (TypeNode
*node
,
1544 GSList
*slist
, *init_slist
= NULL
;
1547 TypeNode
*bnode
, *pnode
;
1550 g_assert (node
->is_classed
&& node
->data
&&
1551 node
->data
->class.class_size
&&
1552 !node
->data
->class.class);
1554 class = g_malloc0 (node
->data
->class.class_size
);
1555 node
->data
->class.class = class;
1559 TypeNode
*pnode
= lookup_type_node_I (pclass
->g_type
);
1561 memcpy (class, pclass
, pnode
->data
->class.class_size
);
1563 class->g_type
= NODE_TYPE (node
);
1565 G_WRITE_UNLOCK (&type_rw_lock
);
1567 /* stack all base class initialization functions, so we
1568 * call them in ascending order.
1570 for (bnode
= node
; bnode
; bnode
= lookup_type_node_I (NODE_PARENT_TYPE (bnode
)))
1571 if (bnode
->data
->class.class_init_base
)
1572 init_slist
= g_slist_prepend (init_slist
, (gpointer
) bnode
->data
->class.class_init_base
);
1573 for (slist
= init_slist
; slist
; slist
= slist
->next
)
1575 GBaseInitFunc class_init_base
= (GBaseInitFunc
) slist
->data
;
1577 class_init_base (class);
1579 g_slist_free (init_slist
);
1581 if (node
->data
->class.class_init
)
1582 node
->data
->class.class_init (class, (gpointer
) node
->data
->class.class_data
);
1584 G_WRITE_LOCK (&type_rw_lock
);
1586 /* ok, we got the class done, now initialize all interfaces, either
1587 * from parent, or through our holder info
1589 pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
1590 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + 0;
1593 g_assert (entry
->vtable
== NULL
);
1595 if (!type_iface_vtable_init_Wm (lookup_type_node_I (entry
->iface_type
), node
))
1599 /* type_iface_vtable_init_Wm() doesn't modify write lock upon FALSE,
1600 * need to get this interface from parent
1602 g_assert (pnode
!= NULL
);
1604 for (j
= 0; j
< CLASSED_NODE_N_IFACES (pnode
); j
++)
1606 IFaceEntry
*pentry
= CLASSED_NODE_IFACES_ENTRIES (pnode
) + j
;
1608 if (pentry
->iface_type
== entry
->iface_type
)
1610 entry
->vtable
= pentry
->vtable
;
1614 g_assert (entry
->vtable
!= NULL
);
1617 /* refetch entry, IFACES_ENTRIES might be modified */
1618 for (entry
= NULL
, i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1619 if (!CLASSED_NODE_IFACES_ENTRIES (node
)[i
].vtable
)
1620 entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + i
;
1625 type_data_finalize_class_ifaces_Wm (TypeNode
*node
)
1629 g_assert (node
->is_instantiatable
&& node
->data
&& node
->data
->class.class && node
->data
->common
.ref_count
== 0);
1632 for (i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1634 IFaceEntry
*entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + i
;
1637 if (type_iface_vtable_finalize_Wm (lookup_type_node_I (entry
->iface_type
), node
, entry
->vtable
))
1639 /* refetch entries, IFACES_ENTRIES might be modified */
1644 /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
1645 * iface vtable came from parent
1647 entry
->vtable
= NULL
;
1654 type_data_finalize_class_U (TypeNode
*node
,
1657 GTypeClass
*class = cdata
->class;
1660 g_assert (cdata
->class && cdata
->common
.ref_count
== 0);
1662 if (cdata
->class_finalize
)
1663 cdata
->class_finalize (class, (gpointer
) cdata
->class_data
);
1665 /* call all base class destruction functions in descending order
1667 if (cdata
->class_finalize_base
)
1668 cdata
->class_finalize_base (class);
1669 for (bnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
)); bnode
; bnode
= lookup_type_node_I (NODE_PARENT_TYPE (bnode
)))
1670 if (bnode
->data
->class.class_finalize_base
)
1671 bnode
->data
->class.class_finalize_base (class);
1674 g_free (cdata
->class);
1678 type_data_last_unref_Wm (GType type
,
1681 TypeNode
*node
= lookup_type_node_I (type
);
1683 g_return_if_fail (node
!= NULL
&& node
->plugin
!= NULL
);
1685 if (!node
->data
|| node
->data
->common
.ref_count
== 0)
1687 g_warning ("cannot drop last reference to unreferenced type `%s'",
1688 type_descriptive_name_I (type
));
1692 if (node
->is_classed
&& node
->data
&& node
->data
->class.class && static_n_class_cache_funcs
)
1696 G_WRITE_UNLOCK (&type_rw_lock
);
1697 G_READ_LOCK (&type_rw_lock
);
1698 for (i
= 0; i
< static_n_class_cache_funcs
; i
++)
1700 GTypeClassCacheFunc cache_func
= static_class_cache_funcs
[i
].cache_func
;
1701 gpointer cache_data
= static_class_cache_funcs
[i
].cache_data
;
1702 gboolean need_break
;
1704 G_READ_UNLOCK (&type_rw_lock
);
1705 need_break
= cache_func (cache_data
, node
->data
->class.class);
1706 G_READ_LOCK (&type_rw_lock
);
1707 if (!node
->data
|| node
->data
->common
.ref_count
== 0)
1708 INVALID_RECURSION ("GType class cache function ", cache_func
, NODE_NAME (node
));
1712 G_READ_UNLOCK (&type_rw_lock
);
1713 G_WRITE_LOCK (&type_rw_lock
);
1716 if (node
->data
->common
.ref_count
> 1) /* may have been re-referenced meanwhile */
1717 node
->data
->common
.ref_count
-= 1;
1720 GType ptype
= NODE_PARENT_TYPE (node
);
1723 node
->data
->common
.ref_count
= 0;
1725 if (node
->is_instantiatable
&& node
->data
->instance
.mem_chunk
)
1727 g_mem_chunk_destroy (node
->data
->instance
.mem_chunk
);
1728 node
->data
->instance
.mem_chunk
= NULL
;
1732 if (node
->is_classed
&& tdata
->class.class)
1734 if (CLASSED_NODE_N_IFACES (node
))
1735 type_data_finalize_class_ifaces_Wm (node
);
1736 node
->mutatable_check_cache
= FALSE
;
1738 G_WRITE_UNLOCK (&type_rw_lock
);
1739 type_data_finalize_class_U (node
, &tdata
->class);
1740 G_WRITE_LOCK (&type_rw_lock
);
1744 node
->mutatable_check_cache
= FALSE
;
1748 /* freeing tdata->common.value_table and its contents is taking care of
1749 * by allocating it in one chunk with tdata
1754 type_data_unref_Wm (lookup_type_node_I (ptype
), FALSE
);
1755 G_WRITE_UNLOCK (&type_rw_lock
);
1756 g_type_plugin_unuse (node
->plugin
);
1757 G_WRITE_LOCK (&type_rw_lock
);
1762 g_type_add_class_cache_func (gpointer cache_data
,
1763 GTypeClassCacheFunc cache_func
)
1767 g_return_if_fail (cache_func
!= NULL
);
1769 G_WRITE_LOCK (&type_rw_lock
);
1770 i
= static_n_class_cache_funcs
++;
1771 static_class_cache_funcs
= g_renew (ClassCacheFunc
, static_class_cache_funcs
, static_n_class_cache_funcs
);
1772 static_class_cache_funcs
[i
].cache_data
= cache_data
;
1773 static_class_cache_funcs
[i
].cache_func
= cache_func
;
1774 G_WRITE_UNLOCK (&type_rw_lock
);
1778 g_type_remove_class_cache_func (gpointer cache_data
,
1779 GTypeClassCacheFunc cache_func
)
1781 gboolean found_it
= FALSE
;
1784 g_return_if_fail (cache_func
!= NULL
);
1786 G_WRITE_LOCK (&type_rw_lock
);
1787 for (i
= 0; i
< static_n_class_cache_funcs
; i
++)
1788 if (static_class_cache_funcs
[i
].cache_data
== cache_data
&&
1789 static_class_cache_funcs
[i
].cache_func
== cache_func
)
1791 static_n_class_cache_funcs
--;
1792 g_memmove (static_class_cache_funcs
+ i
,
1793 static_class_cache_funcs
+ i
+ 1,
1794 sizeof (static_class_cache_funcs
[0]) * (static_n_class_cache_funcs
- i
));
1795 static_class_cache_funcs
= g_renew (ClassCacheFunc
, static_class_cache_funcs
, static_n_class_cache_funcs
);
1799 G_WRITE_UNLOCK (&type_rw_lock
);
1802 g_warning (G_STRLOC
": cannot remove unregistered class cache func %p with data %p",
1803 cache_func
, cache_data
);
1807 /* --- type registration --- */
1809 g_type_register_fundamental (GType type_id
,
1810 const gchar
*type_name
,
1811 const GTypeInfo
*info
,
1812 const GTypeFundamentalInfo
*finfo
,
1815 GTypeFundamentalInfo
*node_finfo
;
1818 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
1819 g_return_val_if_fail (type_id
> 0, 0);
1820 g_return_val_if_fail (type_name
!= NULL
, 0);
1821 g_return_val_if_fail (info
!= NULL
, 0);
1822 g_return_val_if_fail (finfo
!= NULL
, 0);
1824 if (!check_type_name_I (type_name
))
1826 if ((type_id
& TYPE_ID_MASK
) ||
1827 type_id
> G_TYPE_FUNDAMENTAL_MAX
)
1829 g_warning ("attempt to register fundamental type `%s' with invalid type id (%lu)",
1834 if ((finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) &&
1835 !(finfo
->type_flags
& G_TYPE_FLAG_CLASSED
))
1837 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
1841 if (lookup_type_node_I (type_id
))
1843 g_warning ("cannot register existing fundamental type `%s' (as `%s')",
1844 type_descriptive_name_I (type_id
),
1849 G_WRITE_LOCK (&type_rw_lock
);
1850 node
= type_node_fundamental_new_W (type_id
, type_name
, finfo
->type_flags
);
1851 node_finfo
= type_node_fundamental_info_I (node
);
1852 type_add_flags_W (node
, flags
);
1854 if (check_type_info_I (NULL
, NODE_FUNDAMENTAL_TYPE (node
), type_name
, info
))
1855 type_data_make_W (node
, info
,
1856 check_value_table_I (type_name
, info
->value_table
) ? info
->value_table
: NULL
);
1857 G_WRITE_UNLOCK (&type_rw_lock
);
1859 return NODE_TYPE (node
);
1863 g_type_register_static (GType parent_type
,
1864 const gchar
*type_name
,
1865 const GTypeInfo
*info
,
1868 TypeNode
*pnode
, *node
;
1871 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
1872 g_return_val_if_fail (parent_type
> 0, 0);
1873 g_return_val_if_fail (type_name
!= NULL
, 0);
1874 g_return_val_if_fail (info
!= NULL
, 0);
1876 if (!check_type_name_I (type_name
) ||
1877 !check_derivation_I (parent_type
, type_name
))
1879 if (info
->class_finalize
)
1881 g_warning ("class finalizer specified for static type `%s'",
1886 pnode
= lookup_type_node_I (parent_type
);
1887 G_WRITE_LOCK (&type_rw_lock
);
1888 type_data_ref_Wm (pnode
);
1889 if (check_type_info_I (pnode
, NODE_FUNDAMENTAL_TYPE (pnode
), type_name
, info
))
1891 node
= type_node_new_W (pnode
, type_name
, NULL
);
1892 type_add_flags_W (node
, flags
);
1893 type
= NODE_TYPE (node
);
1894 type_data_make_W (node
, info
,
1895 check_value_table_I (type_name
, info
->value_table
) ? info
->value_table
: NULL
);
1897 G_WRITE_UNLOCK (&type_rw_lock
);
1903 g_type_register_dynamic (GType parent_type
,
1904 const gchar
*type_name
,
1905 GTypePlugin
*plugin
,
1908 TypeNode
*pnode
, *node
;
1911 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
1912 g_return_val_if_fail (parent_type
> 0, 0);
1913 g_return_val_if_fail (type_name
!= NULL
, 0);
1914 g_return_val_if_fail (plugin
!= NULL
, 0);
1916 if (!check_type_name_I (type_name
) ||
1917 !check_derivation_I (parent_type
, type_name
) ||
1918 !check_plugin_U (plugin
, TRUE
, FALSE
, type_name
))
1921 G_WRITE_LOCK (&type_rw_lock
);
1922 pnode
= lookup_type_node_I (parent_type
);
1923 node
= type_node_new_W (pnode
, type_name
, plugin
);
1924 type_add_flags_W (node
, flags
);
1925 type
= NODE_TYPE (node
);
1926 G_WRITE_UNLOCK (&type_rw_lock
);
1932 g_type_add_interface_static (GType instance_type
,
1933 GType interface_type
,
1934 const GInterfaceInfo
*info
)
1936 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1937 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type
));
1938 g_return_if_fail (g_type_parent (interface_type
) == G_TYPE_INTERFACE
);
1940 G_WRITE_LOCK (&type_rw_lock
);
1941 if (check_add_interface_L (instance_type
, interface_type
))
1943 TypeNode
*node
= lookup_type_node_I (instance_type
);
1944 TypeNode
*iface
= lookup_type_node_I (interface_type
);
1946 if (check_interface_info_I (iface
, NODE_TYPE (node
), info
))
1948 type_add_interface_W (node
, iface
, info
, NULL
);
1949 /* if we have a class already, the interface vtable needs to
1950 * be initialized as well
1952 if (node
->data
&& node
->data
->class.class)
1953 type_iface_vtable_init_Wm (iface
, node
);
1956 G_WRITE_UNLOCK (&type_rw_lock
);
1960 * g_type_add_interface_dynamic:
1961 * @instance_type: the #GType value of an instantiable type.
1962 * @interface_type: the #GType value of an interface type.
1963 * @plugin: the #GTypePlugin structure to retrieve the #GInterfaceInfo from.
1965 * Adds the dynamic @interface_type to @instantiable_type. The information
1966 * contained in the #GTypePlugin structure pointed to by @plugin
1967 * is used to manage the relationship.
1970 g_type_add_interface_dynamic (GType instance_type
,
1971 GType interface_type
,
1972 GTypePlugin
*plugin
)
1976 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
1977 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type
));
1978 g_return_if_fail (g_type_parent (interface_type
) == G_TYPE_INTERFACE
);
1980 node
= lookup_type_node_I (instance_type
);
1981 if (!check_plugin_U (plugin
, FALSE
, TRUE
, NODE_NAME (node
)))
1984 G_WRITE_LOCK (&type_rw_lock
);
1985 if (check_add_interface_L (instance_type
, interface_type
))
1987 TypeNode
*iface
= lookup_type_node_I (interface_type
);
1989 type_add_interface_W (node
, iface
, NULL
, plugin
);
1990 /* if we have a class already, the interface vtable needs to
1991 * be initialized as well
1993 if (node
->data
&& node
->data
->class.class)
1994 type_iface_vtable_init_Wm (iface
, node
);
1996 G_WRITE_UNLOCK (&type_rw_lock
);
2000 /* --- public API functions --- */
2002 g_type_class_ref (GType type
)
2006 /* optimize for common code path
2008 G_WRITE_LOCK (&type_rw_lock
);
2009 node
= lookup_type_node_I (type
);
2010 if (node
&& node
->is_classed
&& node
->data
&&
2011 node
->data
->class.class && node
->data
->common
.ref_count
> 0)
2013 type_data_ref_Wm (node
);
2014 G_WRITE_UNLOCK (&type_rw_lock
);
2016 return node
->data
->class.class;
2019 if (!node
|| !node
->is_classed
||
2020 (node
->data
&& node
->data
->common
.ref_count
< 1))
2022 G_WRITE_UNLOCK (&type_rw_lock
);
2023 g_warning ("cannot retrieve class for invalid (unclassed) type `%s'",
2024 type_descriptive_name_I (type
));
2028 type_data_ref_Wm (node
);
2030 if (!node
->data
->class.class)
2032 GType ptype
= NODE_PARENT_TYPE (node
);
2033 GTypeClass
*pclass
= NULL
;
2037 G_WRITE_UNLOCK (&type_rw_lock
);
2038 pclass
= g_type_class_ref (ptype
);
2039 if (node
->data
->class.class)
2040 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
2041 G_WRITE_LOCK (&type_rw_lock
);
2044 type_class_init_Wm (node
, pclass
);
2046 G_WRITE_UNLOCK (&type_rw_lock
);
2048 return node
->data
->class.class;
2052 g_type_class_unref (gpointer g_class
)
2055 GTypeClass
*class = g_class
;
2057 g_return_if_fail (g_class
!= NULL
);
2059 node
= lookup_type_node_I (class->g_type
);
2060 G_WRITE_LOCK (&type_rw_lock
);
2061 if (node
&& node
->is_classed
&& node
->data
&&
2062 node
->data
->class.class == class && node
->data
->common
.ref_count
> 0)
2063 type_data_unref_Wm (node
, FALSE
);
2065 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2066 type_descriptive_name_I (class->g_type
));
2067 G_WRITE_UNLOCK (&type_rw_lock
);
2071 g_type_class_unref_uncached (gpointer g_class
)
2074 GTypeClass
*class = g_class
;
2076 g_return_if_fail (g_class
!= NULL
);
2078 G_WRITE_LOCK (&type_rw_lock
);
2079 node
= lookup_type_node_I (class->g_type
);
2080 if (node
&& node
->is_classed
&& node
->data
&&
2081 node
->data
->class.class == class && node
->data
->common
.ref_count
> 0)
2082 type_data_unref_Wm (node
, TRUE
);
2084 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2085 type_descriptive_name_I (class->g_type
));
2086 G_WRITE_UNLOCK (&type_rw_lock
);
2090 g_type_class_peek (GType type
)
2095 node
= lookup_type_node_I (type
);
2096 G_READ_LOCK (&type_rw_lock
);
2097 if (node
&& node
->is_classed
&& node
->data
&& node
->data
->class.class) /* common.ref_count _may_ be 0 */
2098 class = node
->data
->class.class;
2101 G_READ_UNLOCK (&type_rw_lock
);
2107 g_type_class_peek_parent (gpointer g_class
)
2110 gpointer
class = NULL
;
2112 g_return_val_if_fail (g_class
!= NULL
, NULL
);
2114 node
= lookup_type_node_I (G_TYPE_FROM_CLASS (g_class
));
2115 G_READ_LOCK (&type_rw_lock
);
2116 if (node
&& node
->is_classed
&& node
->data
&& NODE_PARENT_TYPE (node
))
2118 node
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
2119 class = node
->data
->class.class;
2121 else if (NODE_PARENT_TYPE (node
))
2122 g_warning (G_STRLOC
": invalid class pointer `%p'", g_class
);
2123 G_READ_UNLOCK (&type_rw_lock
);
2129 g_type_interface_peek (gpointer instance_class
,
2134 gpointer vtable
= NULL
;
2135 GTypeClass
*class = instance_class
;
2137 g_return_val_if_fail (instance_class
!= NULL
, NULL
);
2139 node
= lookup_type_node_I (class->g_type
);
2140 iface
= lookup_type_node_I (iface_type
);
2141 if (node
&& node
->is_instantiatable
&& iface
)
2145 G_READ_LOCK (&type_rw_lock
);
2147 entry
= type_lookup_iface_entry_L (node
, iface
);
2148 if (entry
&& entry
->vtable
) /* entry is relocatable */
2149 vtable
= entry
->vtable
;
2151 G_READ_UNLOCK (&type_rw_lock
);
2154 g_warning (G_STRLOC
": invalid class pointer `%p'", class);
2160 * g_type_interface_peek_parent:
2161 * @g_iface: A #GTypeInterface structure.
2163 * Returns the corresponding #GTypeInterface structure of the parent type
2164 * of the instance type to which @g_iface belongs. This is useful when
2165 * deriving the implementation of an interface from the parent type and
2166 * then possibly overriding some methods.
2168 * Return value: The corresponding #GTypeInterface structure of the parent type
2169 * of the instance type to which @g_iface belongs, or %NULL if the parent type
2170 * doesn't conform to the interface.
2173 g_type_interface_peek_parent (gpointer g_iface
)
2177 gpointer vtable
= NULL
;
2178 GTypeInterface
*iface_class
= g_iface
;
2180 g_return_val_if_fail (g_iface
!= NULL
, NULL
);
2182 iface
= lookup_type_node_I (iface_class
->g_type
);
2183 node
= lookup_type_node_I (iface_class
->g_instance_type
);
2185 node
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
2186 if (node
&& node
->is_instantiatable
&& iface
)
2190 G_READ_LOCK (&type_rw_lock
);
2192 entry
= type_lookup_iface_entry_L (node
, iface
);
2193 if (entry
&& entry
->vtable
) /* entry is relocatable */
2194 vtable
= entry
->vtable
;
2196 G_READ_UNLOCK (&type_rw_lock
);
2199 g_warning (G_STRLOC
": invalid interface pointer `%p'", g_iface
);
2204 G_CONST_RETURN gchar
*
2205 g_type_name (GType type
)
2209 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, NULL
);
2211 node
= lookup_type_node_I (type
);
2213 return node
? NODE_NAME (node
) : NULL
;
2217 g_type_qname (GType type
)
2221 node
= lookup_type_node_I (type
);
2223 return node
? node
->qname
: 0;
2227 g_type_from_name (const gchar
*name
)
2232 g_return_val_if_fail (name
!= NULL
, 0);
2234 quark
= g_quark_try_string (name
);
2237 G_READ_LOCK (&type_rw_lock
);
2238 type
= (GType
) g_hash_table_lookup (static_type_nodes_ht
, GUINT_TO_POINTER (quark
));
2239 G_READ_UNLOCK (&type_rw_lock
);
2246 g_type_parent (GType type
)
2250 node
= lookup_type_node_I (type
);
2252 return node
? NODE_PARENT_TYPE (node
) : 0;
2256 g_type_depth (GType type
)
2260 node
= lookup_type_node_I (type
);
2262 return node
? node
->n_supers
+ 1 : 0;
2266 g_type_next_base (GType type
,
2272 node
= lookup_type_node_I (type
);
2275 TypeNode
*base_node
= lookup_type_node_I (base_type
);
2277 if (base_node
&& base_node
->n_supers
< node
->n_supers
)
2279 guint n
= node
->n_supers
- base_node
->n_supers
;
2281 if (node
->supers
[n
] == base_type
)
2282 atype
= node
->supers
[n
- 1];
2289 static inline gboolean
2290 type_node_check_conformities_UorL (TypeNode
*node
,
2291 TypeNode
*iface_node
,
2292 /* support_inheritance */
2293 gboolean support_interfaces
,
2294 gboolean support_prerequisites
,
2299 if (/* support_inheritance && */
2300 iface_node
->n_supers
<= node
->n_supers
&&
2301 node
->supers
[node
->n_supers
- iface_node
->n_supers
] == NODE_TYPE (iface_node
))
2304 support_interfaces
= support_interfaces
&& node
->is_instantiatable
&& NODE_IS_IFACE (iface_node
);
2305 support_prerequisites
= support_prerequisites
&& NODE_IS_IFACE (node
);
2307 if (support_interfaces
|| support_prerequisites
)
2310 G_READ_LOCK (&type_rw_lock
);
2311 if (support_interfaces
&& type_lookup_iface_entry_L (node
, iface_node
))
2313 else if (support_prerequisites
&& type_lookup_prerequisite_L (node
, NODE_TYPE (iface_node
)))
2316 G_READ_UNLOCK (&type_rw_lock
);
2322 type_node_is_a_L (TypeNode
*node
,
2323 TypeNode
*iface_node
)
2325 return type_node_check_conformities_UorL (node
, iface_node
, TRUE
, TRUE
, TRUE
);
2328 static inline gboolean
2329 type_node_conforms_to_U (TypeNode
*node
,
2330 TypeNode
*iface_node
,
2331 gboolean support_interfaces
,
2332 gboolean support_prerequisites
)
2334 return type_node_check_conformities_UorL (node
, iface_node
, support_interfaces
, support_prerequisites
, FALSE
);
2338 g_type_is_a (GType type
,
2341 TypeNode
*node
, *iface_node
;
2344 node
= lookup_type_node_I (type
);
2345 iface_node
= lookup_type_node_I (iface_type
);
2346 is_a
= node
&& iface_node
&& type_node_conforms_to_U (node
, iface_node
, TRUE
, TRUE
);
2351 GType
* /* free result */
2352 g_type_children (GType type
,
2357 node
= lookup_type_node_I (type
);
2362 G_READ_LOCK (&type_rw_lock
); /* ->children is relocatable */
2363 children
= g_new (GType
, node
->n_children
+ 1);
2364 memcpy (children
, node
->children
, sizeof (GType
) * node
->n_children
);
2365 children
[node
->n_children
] = 0;
2368 *n_children
= node
->n_children
;
2369 G_READ_UNLOCK (&type_rw_lock
);
2382 GType
* /* free result */
2383 g_type_interfaces (GType type
,
2384 guint
*n_interfaces
)
2388 node
= lookup_type_node_I (type
);
2389 if (node
&& node
->is_instantiatable
)
2394 G_READ_LOCK (&type_rw_lock
);
2395 ifaces
= g_new (GType
, CLASSED_NODE_N_IFACES (node
) + 1);
2396 for (i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
2397 ifaces
[i
] = CLASSED_NODE_IFACES_ENTRIES (node
)[i
].iface_type
;
2401 *n_interfaces
= CLASSED_NODE_N_IFACES (node
);
2402 G_READ_UNLOCK (&type_rw_lock
);
2415 typedef struct _QData QData
;
2427 static inline gpointer
2428 type_get_qdata_L (TypeNode
*node
,
2431 GData
*gdata
= node
->global_gdata
;
2433 if (quark
&& gdata
&& gdata
->n_qdatas
)
2435 QData
*qdatas
= gdata
->qdatas
- 1;
2436 guint n_qdatas
= gdata
->n_qdatas
;
2443 i
= (n_qdatas
+ 1) / 2;
2445 if (quark
== check
->quark
)
2447 else if (quark
> check
->quark
)
2452 else /* if (quark < check->quark) */
2463 * @quark: a #GQuark id to identify the data
2465 * Obtains data which has previously been attached to @type
2466 * with g_type_set_qdata().
2468 * Return value: the data, or %NULL if no data was found
2471 g_type_get_qdata (GType type
,
2477 node
= lookup_type_node_I (type
);
2480 G_READ_LOCK (&type_rw_lock
);
2481 data
= type_get_qdata_L (node
, quark
);
2482 G_READ_UNLOCK (&type_rw_lock
);
2486 g_return_val_if_fail (node
!= NULL
, NULL
);
2493 type_set_qdata_W (TypeNode
*node
,
2501 /* setup qdata list if necessary */
2502 if (!node
->global_gdata
)
2503 node
->global_gdata
= g_new0 (GData
, 1);
2504 gdata
= node
->global_gdata
;
2506 /* try resetting old data */
2507 qdata
= gdata
->qdatas
;
2508 for (i
= 0; i
< gdata
->n_qdatas
; i
++)
2509 if (qdata
[i
].quark
== quark
)
2511 qdata
[i
].data
= data
;
2517 gdata
->qdatas
= g_renew (QData
, gdata
->qdatas
, gdata
->n_qdatas
);
2518 qdata
= gdata
->qdatas
;
2519 for (i
= 0; i
< gdata
->n_qdatas
- 1; i
++)
2520 if (qdata
[i
].quark
> quark
)
2522 g_memmove (qdata
+ i
+ 1, qdata
+ i
, sizeof (qdata
[0]) * (gdata
->n_qdatas
- i
- 1));
2523 qdata
[i
].quark
= quark
;
2524 qdata
[i
].data
= data
;
2530 * @quark: a #GQuark id to identify the data
2533 * Attaches arbitrary data to a type.
2536 g_type_set_qdata (GType type
,
2542 g_return_if_fail (quark
!= 0);
2544 node
= lookup_type_node_I (type
);
2547 G_WRITE_LOCK (&type_rw_lock
);
2548 type_set_qdata_W (node
, quark
, data
);
2549 G_WRITE_UNLOCK (&type_rw_lock
);
2552 g_return_if_fail (node
!= NULL
);
2556 type_add_flags_W (TypeNode
*node
,
2561 g_return_if_fail ((flags
& ~TYPE_FLAG_MASK
) == 0);
2562 g_return_if_fail (node
!= NULL
);
2564 if ((flags
& TYPE_FLAG_MASK
) && node
->is_classed
&& node
->data
&& node
->data
->class.class)
2565 g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node
));
2566 dflags
= GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
));
2568 type_set_qdata_W (node
, static_quark_type_flags
, GUINT_TO_POINTER (dflags
));
2573 * @type: the #GType value of a static, classed type.
2574 * @query: A user provided structure that is filled in with constant values
2577 * Queries the type system for information about a specific type.
2578 * This function will fill in a user-provided structure to hold type-specific
2579 * information. If an invalid #GType is passed in, the @type member of the
2580 * #GTypeQuery is 0. All members filled into the #GTypeQuery structure should
2581 * be considered constant and have to be left untouched.
2584 g_type_query (GType type
,
2589 g_return_if_fail (query
!= NULL
);
2591 /* if node is not static and classed, we won't allow query */
2593 node
= lookup_type_node_I (type
);
2594 if (node
&& node
->is_classed
&& !node
->plugin
)
2596 /* type is classed and probably even instantiatable */
2597 G_READ_LOCK (&type_rw_lock
);
2598 if (node
->data
) /* type is static or referenced */
2600 query
->type
= NODE_TYPE (node
);
2601 query
->type_name
= NODE_NAME (node
);
2602 query
->class_size
= node
->data
->class.class_size
;
2603 query
->instance_size
= node
->is_instantiatable
? node
->data
->instance
.instance_size
: 0;
2605 G_READ_UNLOCK (&type_rw_lock
);
2610 /* --- implementation details --- */
2612 g_type_test_flags (GType type
,
2616 gboolean result
= FALSE
;
2618 node
= lookup_type_node_I (type
);
2621 guint fflags
= flags
& TYPE_FUNDAMENTAL_FLAG_MASK
;
2622 guint tflags
= flags
& TYPE_FLAG_MASK
;
2626 GTypeFundamentalInfo
*finfo
= type_node_fundamental_info_I (node
);
2628 fflags
= (finfo
->type_flags
& fflags
) == fflags
;
2635 G_READ_LOCK (&type_rw_lock
);
2636 tflags
= (tflags
& GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
))) == tflags
;
2637 G_READ_UNLOCK (&type_rw_lock
);
2642 result
= tflags
&& fflags
;
2649 g_type_get_plugin (GType type
)
2653 node
= lookup_type_node_I (type
);
2655 return node
? node
->plugin
: NULL
;
2659 * g_type_interface_get_plugin:
2660 * @instance_type: the #GType value of an instantiatable type.
2661 * @interface_type: the #GType value of an interface type.
2663 * Returns the #GTypePlugin structure for the dynamic interface
2664 * @interface_type which has been added to @instance_type, or
2665 * %NULL if @interface_type has not been added to @instance_type or does
2666 * not have a #GTypePlugin structure. See g_type_add_interface_dynamic().
2668 * Return value: the #GTypePlugin for the dynamic interface @interface_type
2669 * of @instance_type.
2672 g_type_interface_get_plugin (GType instance_type
,
2673 GType interface_type
)
2678 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type
), NULL
); /* G_TYPE_IS_INTERFACE() is an external call: _U */
2680 node
= lookup_type_node_I (instance_type
);
2681 iface
= lookup_type_node_I (interface_type
);
2684 IFaceHolder
*iholder
;
2685 GTypePlugin
*plugin
;
2687 G_READ_LOCK (&type_rw_lock
);
2689 iholder
= iface_node_get_holders_L (iface
);
2690 while (iholder
&& iholder
->instance_type
!= instance_type
)
2691 iholder
= iholder
->next
;
2692 plugin
= iholder
? iholder
->plugin
: NULL
;
2694 G_READ_UNLOCK (&type_rw_lock
);
2699 g_return_val_if_fail (node
== NULL
, NULL
);
2700 g_return_val_if_fail (iface
== NULL
, NULL
);
2702 g_warning (G_STRLOC
": attempt to look up plugin for invalid instance/interface type pair.");
2708 g_type_fundamental_next (void)
2712 G_READ_LOCK (&type_rw_lock
);
2713 type
= static_fundamental_next
;
2714 G_READ_UNLOCK (&type_rw_lock
);
2715 type
= G_TYPE_MAKE_FUNDAMENTAL (type
);
2716 return type
<= G_TYPE_FUNDAMENTAL_MAX
? type
: 0;
2720 g_type_fundamental (GType type_id
)
2722 TypeNode
*node
= lookup_type_node_I (type_id
);
2724 return node
? NODE_FUNDAMENTAL_TYPE (node
) : 0;
2728 g_type_check_instance_is_a (GTypeInstance
*type_instance
,
2731 TypeNode
*node
, *iface
;
2734 if (!type_instance
|| !type_instance
->g_class
)
2737 node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
2738 iface
= lookup_type_node_I (iface_type
);
2739 check
= node
&& node
->is_instantiatable
&& iface
&& type_node_conforms_to_U (node
, iface
, TRUE
, FALSE
);
2745 g_type_check_class_is_a (GTypeClass
*type_class
,
2748 TypeNode
*node
, *iface
;
2754 node
= lookup_type_node_I (type_class
->g_type
);
2755 iface
= lookup_type_node_I (is_a_type
);
2756 check
= node
&& node
->is_classed
&& iface
&& type_node_conforms_to_U (node
, iface
, FALSE
, FALSE
);
2762 g_type_check_instance_cast (GTypeInstance
*type_instance
,
2767 if (type_instance
->g_class
)
2769 TypeNode
*node
, *iface
;
2770 gboolean is_instantiatable
, check
;
2772 node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
2773 is_instantiatable
= node
&& node
->is_instantiatable
;
2774 iface
= lookup_type_node_I (iface_type
);
2775 check
= is_instantiatable
&& iface
&& type_node_conforms_to_U (node
, iface
, TRUE
, FALSE
);
2777 return type_instance
;
2779 if (is_instantiatable
)
2780 g_warning ("invalid cast from `%s' to `%s'",
2781 type_descriptive_name_I (type_instance
->g_class
->g_type
),
2782 type_descriptive_name_I (iface_type
));
2784 g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
2785 type_descriptive_name_I (type_instance
->g_class
->g_type
),
2786 type_descriptive_name_I (iface_type
));
2789 g_warning ("invalid unclassed pointer in cast to `%s'",
2790 type_descriptive_name_I (iface_type
));
2793 return type_instance
;
2797 g_type_check_class_cast (GTypeClass
*type_class
,
2802 TypeNode
*node
, *iface
;
2803 gboolean is_classed
, check
;
2805 node
= lookup_type_node_I (type_class
->g_type
);
2806 is_classed
= node
&& node
->is_classed
;
2807 iface
= lookup_type_node_I (is_a_type
);
2808 check
= is_classed
&& iface
&& type_node_conforms_to_U (node
, iface
, FALSE
, FALSE
);
2813 g_warning ("invalid class cast from `%s' to `%s'",
2814 type_descriptive_name_I (type_class
->g_type
),
2815 type_descriptive_name_I (is_a_type
));
2817 g_warning ("invalid unclassed type `%s' in class cast to `%s'",
2818 type_descriptive_name_I (type_class
->g_type
),
2819 type_descriptive_name_I (is_a_type
));
2822 g_warning ("invalid class cast from (NULL) pointer to `%s'",
2823 type_descriptive_name_I (is_a_type
));
2828 g_type_check_instance (GTypeInstance
*type_instance
)
2830 /* this function is just here to make the signal system
2831 * conveniently elaborated on instance checks
2835 if (type_instance
->g_class
)
2837 TypeNode
*node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
2839 if (node
&& node
->is_instantiatable
)
2842 g_warning ("instance of invalid non-instantiatable type `%s'",
2843 type_descriptive_name_I (type_instance
->g_class
->g_type
));
2846 g_warning ("instance with invalid (NULL) class pointer");
2849 g_warning ("invalid (NULL) pointer instance");
2854 static inline gboolean
2855 type_check_is_value_type_U (GType type
)
2857 GTypeFlags tflags
= G_TYPE_FLAG_VALUE_ABSTRACT
;
2860 /* common path speed up */
2861 node
= lookup_type_node_I (type
);
2862 if (node
&& node
->mutatable_check_cache
)
2865 G_READ_LOCK (&type_rw_lock
);
2869 if (node
->data
&& node
->data
->common
.ref_count
> 0 &&
2870 node
->data
->common
.value_table
->value_init
)
2871 tflags
= GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
));
2872 else if (NODE_IS_IFACE (node
))
2876 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (node
); i
++)
2878 GType prtype
= IFACE_NODE_PREREQUISITES (node
)[i
];
2879 TypeNode
*prnode
= lookup_type_node_I (prtype
);
2881 if (prnode
->is_instantiatable
)
2884 node
= lookup_type_node_I (type
);
2890 G_READ_UNLOCK (&type_rw_lock
);
2892 return !(tflags
& G_TYPE_FLAG_VALUE_ABSTRACT
);
2896 g_type_check_is_value_type (GType type
)
2898 return type_check_is_value_type_U (type
);
2902 g_type_check_value (GValue
*value
)
2904 return value
&& type_check_is_value_type_U (value
->g_type
);
2908 g_type_check_value_holds (GValue
*value
,
2911 return value
&& type_check_is_value_type_U (value
->g_type
) && g_type_is_a (value
->g_type
, type
);
2915 g_type_value_table_peek (GType type
)
2917 GTypeValueTable
*vtable
= NULL
;
2918 TypeNode
*node
= lookup_type_node_I (type
);
2919 gboolean has_refed_data
, has_table
;
2922 /* speed up common code path, we're not 100% safe here,
2923 * but we should only get called with referenced types anyway
2925 data
= node
? node
->data
: NULL
;
2926 if (node
&& node
->mutatable_check_cache
)
2927 return data
->common
.value_table
;
2929 G_READ_LOCK (&type_rw_lock
);
2932 has_refed_data
= node
&& node
->data
&& node
->data
->common
.ref_count
;
2933 has_table
= has_refed_data
&& node
->data
->common
.value_table
->value_init
;
2937 vtable
= node
->data
->common
.value_table
;
2938 else if (NODE_IS_IFACE (node
))
2942 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (node
); i
++)
2944 GType prtype
= IFACE_NODE_PREREQUISITES (node
)[i
];
2945 TypeNode
*prnode
= lookup_type_node_I (prtype
);
2947 if (prnode
->is_instantiatable
)
2950 node
= lookup_type_node_I (type
);
2951 goto restart_table_peek
;
2957 G_READ_UNLOCK (&type_rw_lock
);
2963 g_warning (G_STRLOC
": type id `%lu' is invalid", type
);
2964 if (!has_refed_data
)
2965 g_warning ("can't peek value table for type `%s' which is not currently referenced",
2966 type_descriptive_name_I (type
));
2971 G_CONST_RETURN gchar
*
2972 g_type_name_from_instance (GTypeInstance
*instance
)
2975 return "<NULL-instance>";
2977 return g_type_name_from_class (instance
->g_class
);
2980 G_CONST_RETURN gchar
*
2981 g_type_name_from_class (GTypeClass
*g_class
)
2984 return "<NULL-class>";
2986 return g_type_name (g_class
->g_type
);
2990 /* --- foreign prototypes --- */
2991 extern void g_value_c_init (void); /* sync with gvalue.c */
2992 extern void g_value_types_init (void); /* sync with gvaluetypes.c */
2993 extern void g_enum_types_init (void); /* sync with genums.c */
2994 extern void g_param_type_init (void); /* sync with gparam.c */
2995 extern void g_boxed_type_init (void); /* sync with gboxed.c */
2996 extern void g_object_type_init (void); /* sync with gobject.c */
2997 extern void g_param_spec_types_init (void); /* sync with gparamspecs.c */
2998 extern void g_value_transforms_init (void); /* sync with gvaluetransform.c */
2999 extern void g_signal_init (void); /* sync with gsignal.c */
3002 /* --- initialization --- */
3004 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags
)
3006 G_LOCK_DEFINE_STATIC (type_init_lock
);
3007 const gchar
*env_string
;
3012 G_LOCK (type_init_lock
);
3014 G_WRITE_LOCK (&type_rw_lock
);
3016 if (static_quark_type_flags
)
3018 G_WRITE_UNLOCK (&type_rw_lock
);
3019 G_UNLOCK (type_init_lock
);
3023 /* setup GObject library wide debugging flags */
3024 _g_type_debug_flags
= debug_flags
& G_TYPE_DEBUG_MASK
;
3025 env_string
= g_getenv ("GOBJECT_DEBUG");
3026 if (env_string
!= NULL
)
3028 static GDebugKey debug_keys
[] = {
3029 { "objects", G_TYPE_DEBUG_OBJECTS
},
3030 { "signals", G_TYPE_DEBUG_SIGNALS
},
3033 _g_type_debug_flags
|= g_parse_debug_string (env_string
,
3035 sizeof (debug_keys
) / sizeof (debug_keys
[0]));
3040 static_quark_type_flags
= g_quark_from_static_string ("-g-type-private--GTypeFlags");
3041 static_quark_iface_holder
= g_quark_from_static_string ("-g-type-private--IFaceHolder");
3042 static_quark_dependants_array
= g_quark_from_static_string ("-g-type-private--dependants-array");
3044 /* type qname hash table */
3045 static_type_nodes_ht
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
3047 /* invalid type G_TYPE_INVALID (0)
3049 static_fundamental_type_nodes
[0] = NULL
;
3051 /* void type G_TYPE_NONE
3053 node
= type_node_fundamental_new_W (G_TYPE_NONE
, "void", 0);
3054 type
= NODE_TYPE (node
);
3055 g_assert (type
== G_TYPE_NONE
);
3057 /* interface fundamental type G_TYPE_INTERFACE (!classed)
3059 memset (&info
, 0, sizeof (info
));
3060 node
= type_node_fundamental_new_W (G_TYPE_INTERFACE
, "GInterface", G_TYPE_FLAG_DERIVABLE
);
3061 type
= NODE_TYPE (node
);
3062 type_data_make_W (node
, &info
, NULL
);
3063 g_assert (type
== G_TYPE_INTERFACE
);
3065 G_WRITE_UNLOCK (&type_rw_lock
);
3069 /* G_TYPE_TYPE_PLUGIN
3071 g_type_plugin_get_type ();
3073 /* G_TYPE_* value types
3075 g_value_types_init ();
3077 /* G_TYPE_ENUM & G_TYPE_FLAGS
3079 g_enum_types_init ();
3083 g_boxed_type_init ();
3087 g_param_type_init ();
3091 g_object_type_init ();
3093 /* G_TYPE_PARAM_* pspec types
3095 g_param_spec_types_init ();
3097 /* Value Transformations
3099 g_value_transforms_init ();
3105 G_UNLOCK (type_init_lock
);
3111 g_type_init_with_debug_flags (0);