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.
20 #include "gobjectalias.h"
27 #include "gtypeplugin.h"
28 #include "gvaluecollector.h"
29 #include "gbsearcharray.h"
33 /* NOTE: some functions (some internal variants and exported ones)
34 * invalidate data portions of the TypeNodes. if external functions/callbacks
35 * are called, pointers to memory maintained by TypeNodes have to be looked up
36 * again. this affects most of the struct TypeNode fields, e.g. ->children or
37 * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
38 * not ->supers[]), as all those memory portions can get realloc()ed during
39 * callback invocation.
42 * - g_type_from_name() should do an ordered array lookup after fetching the
43 * the quark, instead of a second hashtable lookup.
46 * lock handling issues when calling static functions are indicated by
47 * uppercase letter postfixes, all static functions have to have
48 * one of the below postfixes:
49 * - _I: [Indifferent about locking]
50 * function doesn't care about locks at all
51 * - _U: [Unlocked invocation]
52 * no read or write lock has to be held across function invocation
53 * (locks may be acquired and released during invocation though)
54 * - _L: [Locked invocation]
55 * a write lock or more than 0 read locks have to be held across
57 * - _W: [Write-locked invocation]
58 * a write lock has to be held across function invokation
59 * - _Wm: [Write-locked invocation, mutatable]
60 * like _W, but the write lock might be released and reacquired
61 * during invocation, watch your pointers
64 static GStaticRWLock type_rw_lock
= G_STATIC_RW_LOCK_INIT
;
66 #define G_READ_LOCK(rw_lock) do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0)
67 #define G_READ_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0)
68 #define G_WRITE_LOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL++\n"); g_static_rw_lock_writer_lock (rw_lock); } while (0)
69 #define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_static_rw_lock_writer_unlock (rw_lock); } while (0)
71 #define G_READ_LOCK(rw_lock) g_static_rw_lock_reader_lock (rw_lock)
72 #define G_READ_UNLOCK(rw_lock) g_static_rw_lock_reader_unlock (rw_lock)
73 #define G_WRITE_LOCK(rw_lock) g_static_rw_lock_writer_lock (rw_lock)
74 #define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
76 #define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
77 static const gchar *_action = " invalidly modified type "; \
78 gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
80 g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
82 g_error ("%s()%s`%s'", _fname, _action, _tname); \
84 #define g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{ \
87 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
88 "%s: initialization assertion failed, use %s() prior to this function", \
89 G_STRLOC, G_STRINGIFY (init_function)); \
90 return (return_value); \
95 #define DEBUG_CODE(debug_type, code_block) G_STMT_START { \
96 if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
99 #else /* !G_ENABLE_DEBUG */
100 #define DEBUG_CODE(debug_type, code_block) /* code_block */
101 #endif /* G_ENABLE_DEBUG */
103 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
104 G_TYPE_FLAG_INSTANTIATABLE | \
105 G_TYPE_FLAG_DERIVABLE | \
106 G_TYPE_FLAG_DEEP_DERIVABLE)
107 #define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT)
108 #define SIZEOF_FUNDAMENTAL_INFO ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
109 sizeof (gpointer)), \
112 /* The 2*sizeof(size_t) alignment here is borrowed from
113 * GNU libc, so it should be good most everywhere.
114 * It is more conservative than is needed on some 64-bit
115 * platforms, but ia64 does require a 16-byte alignment.
116 * The SIMD extensions for x86 and ppc32 would want a
117 * larger alignment than this, but we don't need to
118 * do better than malloc.
120 #define STRUCT_ALIGNMENT (2 * sizeof (gsize))
121 #define ALIGN_STRUCT(offset) \
122 ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)
125 /* --- typedefs --- */
126 typedef struct _TypeNode TypeNode
;
127 typedef struct _CommonData CommonData
;
128 typedef struct _IFaceData IFaceData
;
129 typedef struct _ClassData ClassData
;
130 typedef struct _InstanceData InstanceData
;
131 typedef union _TypeData TypeData
;
132 typedef struct _IFaceEntry IFaceEntry
;
133 typedef struct _IFaceHolder IFaceHolder
;
136 /* --- prototypes --- */
137 static inline GTypeFundamentalInfo
* type_node_fundamental_info_I (TypeNode
*node
);
138 static void type_add_flags_W (TypeNode
*node
,
140 static void type_data_make_W (TypeNode
*node
,
141 const GTypeInfo
*info
,
142 const GTypeValueTable
*value_table
);
143 static inline void type_data_ref_Wm (TypeNode
*node
);
144 static inline void type_data_unref_Wm (TypeNode
*node
,
146 static void type_data_last_unref_Wm (GType type
,
148 static inline gpointer
type_get_qdata_L (TypeNode
*node
,
150 static inline void type_set_qdata_W (TypeNode
*node
,
153 static IFaceHolder
* type_iface_peek_holder_L (TypeNode
*iface
,
154 GType instance_type
);
155 static gboolean
type_iface_vtable_base_init_Wm (TypeNode
*iface
,
157 static void type_iface_vtable_iface_init_Wm (TypeNode
*iface
,
159 static gboolean
type_node_is_a_L (TypeNode
*node
,
160 TypeNode
*iface_node
);
163 /* --- enumeration --- */
165 /* The InitState enumeration is used to track the progress of initializing
166 * both classes and interface vtables. Keeping the state of initialization
167 * is necessary to handle new interfaces being added while we are initializing
168 * the class or other interfaces.
180 /* --- structures --- */
184 guint n_children
: 12;
186 guint _prot_n_ifaces_prerequisites
: 9;
187 guint is_classed
: 1;
188 guint is_instantiatable
: 1;
189 guint mutatable_check_cache
: 1; /* combines some common path checks */
191 TypeData
* volatile data
;
195 IFaceEntry
*iface_entries
; /* for !iface types */
196 GType
*prerequisistes
;
198 GType supers
[1]; /* flexible array */
200 #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
201 #define MAX_N_SUPERS (255)
202 #define MAX_N_CHILDREN (4095)
203 #define MAX_N_IFACES (511)
204 #define MAX_N_PREREQUISITES (MAX_N_IFACES)
205 #define NODE_TYPE(node) (node->supers[0])
206 #define NODE_PARENT_TYPE(node) (node->supers[1])
207 #define NODE_FUNDAMENTAL_TYPE(node) (node->supers[node->n_supers])
208 #define NODE_NAME(node) (g_quark_to_string (node->qname))
209 #define NODE_IS_IFACE(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
210 #define CLASSED_NODE_N_IFACES(node) ((node)->_prot_n_ifaces_prerequisites)
211 #define CLASSED_NODE_IFACES_ENTRIES(node) ((node)->_prot.iface_entries)
212 #define IFACE_NODE_N_PREREQUISITES(node) ((node)->_prot_n_ifaces_prerequisites)
213 #define IFACE_NODE_PREREQUISITES(node) ((node)->_prot.prerequisistes)
214 #define iface_node_get_holders_L(node) ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
215 #define iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
216 #define iface_node_get_dependants_array_L(n) ((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
217 #define iface_node_set_dependants_array_W(n,d) (type_set_qdata_W ((n), static_quark_dependants_array, (d)))
218 #define TYPE_ID_MASK ((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1))
220 #define NODE_IS_ANCESTOR(ancestor, node) \
221 ((ancestor)->n_supers <= (node)->n_supers && \
222 (node)->supers[(node)->n_supers - (ancestor)->n_supers] == NODE_TYPE (ancestor))
228 GInterfaceInfo
*info
;
235 GTypeInterface
*vtable
;
236 InitState init_state
;
241 GTypeValueTable
*value_table
;
247 GBaseInitFunc vtable_init_base
;
248 GBaseFinalizeFunc vtable_finalize_base
;
249 GClassInitFunc dflt_init
;
250 GClassFinalizeFunc dflt_finalize
;
251 gconstpointer dflt_data
;
252 gpointer dflt_vtable
;
258 guint init_state
: 4;
259 GBaseInitFunc class_init_base
;
260 GBaseFinalizeFunc class_finalize_base
;
261 GClassInitFunc class_init
;
262 GClassFinalizeFunc class_finalize
;
263 gconstpointer class_data
;
270 guint init_state
: 4;
271 GBaseInitFunc class_init_base
;
272 GBaseFinalizeFunc class_finalize_base
;
273 GClassInitFunc class_init
;
274 GClassFinalizeFunc class_finalize
;
275 gconstpointer class_data
;
277 guint16 instance_size
;
278 guint16 private_size
;
280 GInstanceInitFunc instance_init
;
281 GMemChunk
*mem_chunk
;
288 InstanceData instance
;
292 GTypeClassCacheFunc cache_func
;
296 GTypeInterfaceCheckFunc check_func
;
300 /* --- variables --- */
301 static guint static_n_class_cache_funcs
= 0;
302 static ClassCacheFunc
*static_class_cache_funcs
= NULL
;
303 static guint static_n_iface_check_funcs
= 0;
304 static IFaceCheckFunc
*static_iface_check_funcs
= NULL
;
305 static GQuark static_quark_type_flags
= 0;
306 static GQuark static_quark_iface_holder
= 0;
307 static GQuark static_quark_dependants_array
= 0;
308 GTypeDebugFlags _g_type_debug_flags
= 0;
311 /* --- type nodes --- */
312 static GHashTable
*static_type_nodes_ht
= NULL
;
313 static TypeNode
*static_fundamental_type_nodes
[(G_TYPE_FUNDAMENTAL_MAX
>> G_TYPE_FUNDAMENTAL_SHIFT
) + 1] = { NULL
, };
314 static GType static_fundamental_next
= G_TYPE_RESERVED_USER_FIRST
;
316 static inline TypeNode
*
317 lookup_type_node_I (register GType utype
)
319 if (utype
> G_TYPE_FUNDAMENTAL_MAX
)
320 return (TypeNode
*) (utype
& ~TYPE_ID_MASK
);
322 return static_fundamental_type_nodes
[utype
>> G_TYPE_FUNDAMENTAL_SHIFT
];
326 type_node_any_new_W (TypeNode
*pnode
,
330 GTypeFundamentalFlags type_flags
)
335 guint i
, node_size
= 0;
337 n_supers
= pnode
? pnode
->n_supers
+ 1 : 0;
340 node_size
+= SIZEOF_FUNDAMENTAL_INFO
; /* fundamental type info */
341 node_size
+= SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
342 node_size
+= (sizeof (GType
) * (1 + n_supers
+ 1)); /* self + ancestors + (0) for ->supers[] */
343 node
= g_malloc0 (node_size
);
344 if (!pnode
) /* offset fundamental types */
346 node
= G_STRUCT_MEMBER_P (node
, SIZEOF_FUNDAMENTAL_INFO
);
347 static_fundamental_type_nodes
[ftype
>> G_TYPE_FUNDAMENTAL_SHIFT
] = node
;
353 g_assert ((type
& TYPE_ID_MASK
) == 0);
355 node
->n_supers
= n_supers
;
358 node
->supers
[0] = type
;
361 node
->is_classed
= (type_flags
& G_TYPE_FLAG_CLASSED
) != 0;
362 node
->is_instantiatable
= (type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) != 0;
364 if (NODE_IS_IFACE (node
))
366 IFACE_NODE_N_PREREQUISITES (node
) = 0;
367 IFACE_NODE_PREREQUISITES (node
) = NULL
;
371 CLASSED_NODE_N_IFACES (node
) = 0;
372 CLASSED_NODE_IFACES_ENTRIES (node
) = NULL
;
377 node
->supers
[0] = type
;
378 memcpy (node
->supers
+ 1, pnode
->supers
, sizeof (GType
) * (1 + pnode
->n_supers
+ 1));
380 node
->is_classed
= pnode
->is_classed
;
381 node
->is_instantiatable
= pnode
->is_instantiatable
;
383 if (NODE_IS_IFACE (node
))
385 IFACE_NODE_N_PREREQUISITES (node
) = 0;
386 IFACE_NODE_PREREQUISITES (node
) = NULL
;
392 CLASSED_NODE_N_IFACES (node
) = CLASSED_NODE_N_IFACES (pnode
);
393 CLASSED_NODE_IFACES_ENTRIES (node
) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode
),
394 sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode
)[0]) *
395 CLASSED_NODE_N_IFACES (node
));
396 for (j
= 0; j
< CLASSED_NODE_N_IFACES (node
); j
++)
398 CLASSED_NODE_IFACES_ENTRIES (node
)[j
].vtable
= NULL
;
399 CLASSED_NODE_IFACES_ENTRIES (node
)[j
].init_state
= UNINITIALIZED
;
403 i
= pnode
->n_children
++;
404 pnode
->children
= g_renew (GType
, pnode
->children
, pnode
->n_children
);
405 pnode
->children
[i
] = type
;
408 node
->plugin
= plugin
;
409 node
->n_children
= 0;
410 node
->children
= NULL
;
412 node
->qname
= g_quark_from_string (name
);
413 node
->global_gdata
= NULL
;
415 g_hash_table_insert (static_type_nodes_ht
,
416 GUINT_TO_POINTER (node
->qname
),
421 static inline GTypeFundamentalInfo
*
422 type_node_fundamental_info_I (TypeNode
*node
)
424 GType ftype
= NODE_FUNDAMENTAL_TYPE (node
);
426 if (ftype
!= NODE_TYPE (node
))
427 node
= lookup_type_node_I (ftype
);
429 return node
? G_STRUCT_MEMBER_P (node
, -SIZEOF_FUNDAMENTAL_INFO
) : NULL
;
433 type_node_fundamental_new_W (GType ftype
,
435 GTypeFundamentalFlags type_flags
)
437 GTypeFundamentalInfo
*finfo
;
440 g_assert ((ftype
& TYPE_ID_MASK
) == 0);
441 g_assert (ftype
<= G_TYPE_FUNDAMENTAL_MAX
);
443 if (ftype
>> G_TYPE_FUNDAMENTAL_SHIFT
== static_fundamental_next
)
444 static_fundamental_next
++;
446 type_flags
&= TYPE_FUNDAMENTAL_FLAG_MASK
;
448 node
= type_node_any_new_W (NULL
, ftype
, name
, NULL
, type_flags
);
450 finfo
= type_node_fundamental_info_I (node
);
451 finfo
->type_flags
= type_flags
;
457 type_node_new_W (TypeNode
*pnode
,
463 g_assert (pnode
->n_supers
< MAX_N_SUPERS
);
464 g_assert (pnode
->n_children
< MAX_N_CHILDREN
);
466 return type_node_any_new_W (pnode
, NODE_FUNDAMENTAL_TYPE (pnode
), name
, plugin
, 0);
469 static inline IFaceEntry
*
470 type_lookup_iface_entry_L (TypeNode
*node
,
471 TypeNode
*iface_node
)
473 if (NODE_IS_IFACE (iface_node
) && CLASSED_NODE_N_IFACES (node
))
475 IFaceEntry
*ifaces
= CLASSED_NODE_IFACES_ENTRIES (node
) - 1;
476 guint n_ifaces
= CLASSED_NODE_N_IFACES (node
);
477 GType iface_type
= NODE_TYPE (iface_node
);
484 i
= (n_ifaces
+ 1) >> 1;
486 if (iface_type
== check
->iface_type
)
488 else if (iface_type
> check
->iface_type
)
493 else /* if (iface_type < check->iface_type) */
502 static inline gboolean
503 type_lookup_prerequisite_L (TypeNode
*iface
,
504 GType prerequisite_type
)
506 if (NODE_IS_IFACE (iface
) && IFACE_NODE_N_PREREQUISITES (iface
))
508 GType
*prerequisites
= IFACE_NODE_PREREQUISITES (iface
) - 1;
509 guint n_prerequisites
= IFACE_NODE_N_PREREQUISITES (iface
);
516 i
= (n_prerequisites
+ 1) >> 1;
517 check
= prerequisites
+ i
;
518 if (prerequisite_type
== *check
)
520 else if (prerequisite_type
> *check
)
522 n_prerequisites
-= i
;
523 prerequisites
= check
;
525 else /* if (prerequisite_type < *check) */
526 n_prerequisites
= i
- 1;
528 while (n_prerequisites
);
534 type_descriptive_name_I (GType type
)
538 TypeNode
*node
= lookup_type_node_I (type
);
540 return node
? NODE_NAME (node
) : "<unknown>";
547 /* --- type consistency checks --- */
549 check_plugin_U (GTypePlugin
*plugin
,
550 gboolean need_complete_type_info
,
551 gboolean need_complete_interface_info
,
552 const gchar
*type_name
)
554 /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U
558 g_warning ("plugin handle for type `%s' is NULL",
562 if (!G_IS_TYPE_PLUGIN (plugin
))
564 g_warning ("plugin pointer (%p) for type `%s' is invalid",
568 if (need_complete_type_info
&& !G_TYPE_PLUGIN_GET_CLASS (plugin
)->complete_type_info
)
570 g_warning ("plugin for type `%s' has no complete_type_info() implementation",
574 if (need_complete_interface_info
&& !G_TYPE_PLUGIN_GET_CLASS (plugin
)->complete_interface_info
)
576 g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
584 check_type_name_I (const gchar
*type_name
)
586 static const gchar
*extra_chars
= "-_+";
587 const gchar
*p
= type_name
;
590 if (!type_name
[0] || !type_name
[1] || !type_name
[2])
592 g_warning ("type name `%s' is too short", type_name
);
595 /* check the first letter */
596 name_valid
= (p
[0] >= 'A' && p
[0] <= 'Z') || (p
[0] >= 'a' && p
[0] <= 'z') || p
[0] == '_';
597 for (p
= type_name
+ 1; *p
; p
++)
598 name_valid
&= ((p
[0] >= 'A' && p
[0] <= 'Z') ||
599 (p
[0] >= 'a' && p
[0] <= 'z') ||
600 (p
[0] >= '0' && p
[0] <= '9') ||
601 strchr (extra_chars
, p
[0]));
604 g_warning ("type name `%s' contains invalid characters", type_name
);
607 if (g_type_from_name (type_name
))
609 g_warning ("cannot register existing type `%s'", type_name
);
617 check_derivation_I (GType parent_type
,
618 const gchar
*type_name
)
621 GTypeFundamentalInfo
* finfo
;
623 pnode
= lookup_type_node_I (parent_type
);
626 g_warning ("cannot derive type `%s' from invalid parent type `%s'",
628 type_descriptive_name_I (parent_type
));
631 finfo
= type_node_fundamental_info_I (pnode
);
632 /* ensure flat derivability */
633 if (!(finfo
->type_flags
& G_TYPE_FLAG_DERIVABLE
))
635 g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
640 /* ensure deep derivability */
641 if (parent_type
!= NODE_FUNDAMENTAL_TYPE (pnode
) &&
642 !(finfo
->type_flags
& G_TYPE_FLAG_DEEP_DERIVABLE
))
644 g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
654 check_collect_format_I (const gchar
*collect_format
)
656 const gchar
*p
= collect_format
;
657 gchar valid_format
[] = { G_VALUE_COLLECT_INT
, G_VALUE_COLLECT_LONG
,
658 G_VALUE_COLLECT_INT64
, G_VALUE_COLLECT_DOUBLE
,
659 G_VALUE_COLLECT_POINTER
, 0 };
662 if (!strchr (valid_format
, *p
++))
664 return p
- collect_format
<= G_VALUE_COLLECT_FORMAT_MAX_LENGTH
;
668 check_value_table_I (const gchar
*type_name
,
669 const GTypeValueTable
*value_table
)
673 else if (value_table
->value_init
== NULL
)
675 if (value_table
->value_free
|| value_table
->value_copy
||
676 value_table
->value_peek_pointer
||
677 value_table
->collect_format
|| value_table
->collect_value
||
678 value_table
->lcopy_format
|| value_table
->lcopy_value
)
679 g_warning ("cannot handle uninitializable values of type `%s'",
683 else /* value_table->value_init != NULL */
685 if (!value_table
->value_free
)
688 * g_warning ("missing `value_free()' for type `%s'", type_name);
692 if (!value_table
->value_copy
)
694 g_warning ("missing `value_copy()' for type `%s'", type_name
);
697 if ((value_table
->collect_format
|| value_table
->collect_value
) &&
698 (!value_table
->collect_format
|| !value_table
->collect_value
))
700 g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'",
704 if (value_table
->collect_format
&& !check_collect_format_I (value_table
->collect_format
))
706 g_warning ("the `%s' specification for type `%s' is too long or invalid",
711 if ((value_table
->lcopy_format
|| value_table
->lcopy_value
) &&
712 (!value_table
->lcopy_format
|| !value_table
->lcopy_value
))
714 g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'",
718 if (value_table
->lcopy_format
&& !check_collect_format_I (value_table
->lcopy_format
))
720 g_warning ("the `%s' specification for type `%s' is too long or invalid",
730 check_type_info_I (TypeNode
*pnode
,
732 const gchar
*type_name
,
733 const GTypeInfo
*info
)
735 GTypeFundamentalInfo
*finfo
= type_node_fundamental_info_I (lookup_type_node_I (ftype
));
736 gboolean is_interface
= ftype
== G_TYPE_INTERFACE
;
738 g_assert (ftype
<= G_TYPE_FUNDAMENTAL_MAX
&& !(ftype
& TYPE_ID_MASK
));
740 /* check instance members */
741 if (!(finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) &&
742 (info
->instance_size
|| info
->n_preallocs
|| info
->instance_init
))
745 g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'",
749 g_warning ("cannot instantiate `%s' as non-instantiatable fundamental",
753 /* check class & interface members */
754 if (!((finfo
->type_flags
& G_TYPE_FLAG_CLASSED
) || is_interface
) &&
755 (info
->class_init
|| info
->class_finalize
|| info
->class_data
||
756 info
->class_size
|| info
->base_init
|| info
->base_finalize
))
759 g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'",
763 g_warning ("cannot create class for `%s' as non-classed fundamental",
767 /* check interface size */
768 if (is_interface
&& info
->class_size
< sizeof (GTypeInterface
))
770 g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size",
774 /* check class size */
775 if (finfo
->type_flags
& G_TYPE_FLAG_CLASSED
)
777 if (info
->class_size
< sizeof (GTypeClass
))
779 g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size",
783 if (pnode
&& info
->class_size
< pnode
->data
->class.class_size
)
785 g_warning ("specified class size for type `%s' is smaller "
786 "than the parent type's `%s' class size",
792 /* check instance size */
793 if (finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
)
795 if (info
->instance_size
< sizeof (GTypeInstance
))
797 g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size",
801 if (pnode
&& info
->instance_size
< pnode
->data
->instance
.instance_size
)
803 g_warning ("specified instance size for type `%s' is smaller "
804 "than the parent type's `%s' instance size",
815 find_conforming_child_type_L (TypeNode
*pnode
,
818 TypeNode
*node
= NULL
;
821 if (type_lookup_iface_entry_L (pnode
, iface
))
824 for (i
= 0; i
< pnode
->n_children
&& !node
; i
++)
825 node
= find_conforming_child_type_L (lookup_type_node_I (pnode
->children
[i
]), iface
);
831 check_add_interface_L (GType instance_type
,
834 TypeNode
*node
= lookup_type_node_I (instance_type
);
835 TypeNode
*iface
= lookup_type_node_I (iface_type
);
838 GType
*prerequisites
;
842 if (!node
|| !node
->is_instantiatable
)
844 g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
845 type_descriptive_name_I (instance_type
));
848 if (!iface
|| !NODE_IS_IFACE (iface
))
850 g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
851 type_descriptive_name_I (iface_type
),
855 tnode
= lookup_type_node_I (NODE_PARENT_TYPE (iface
));
856 if (NODE_PARENT_TYPE (tnode
) && !type_lookup_iface_entry_L (node
, tnode
))
858 /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
859 g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
865 /* allow overriding of interface type introduced for parent type */
866 entry
= type_lookup_iface_entry_L (node
, iface
);
867 if (entry
&& entry
->vtable
== NULL
&& !type_iface_peek_holder_L (iface
, NODE_TYPE (node
)))
869 /* ok, we do conform to this interface already, but the interface vtable was not
870 * yet intialized, and we just conform to the interface because it got added to
871 * one of our parents. so we allow overriding of holder info here.
875 /* check whether one of our children already conforms (or whether the interface
876 * got added to this node already)
878 tnode
= find_conforming_child_type_L (node
, iface
); /* tnode is_a node */
881 g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
887 prerequisites
= IFACE_NODE_PREREQUISITES (iface
);
888 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
890 tnode
= lookup_type_node_I (prerequisites
[i
]);
891 if (!type_node_is_a_L (node
, tnode
))
893 g_warning ("cannot add interface type `%s' to type `%s' which does not conform to prerequisite `%s'",
904 check_interface_info_I (TypeNode
*iface
,
906 const GInterfaceInfo
*info
)
908 if ((info
->interface_finalize
|| info
->interface_data
) && !info
->interface_init
)
910 g_warning ("interface type `%s' for type `%s' comes without initializer",
912 type_descriptive_name_I (instance_type
));
919 /* --- type info (type node data) --- */
921 type_data_make_W (TypeNode
*node
,
922 const GTypeInfo
*info
,
923 const GTypeValueTable
*value_table
)
926 GTypeValueTable
*vtable
= NULL
;
927 guint vtable_size
= 0;
929 g_assert (node
->data
== NULL
&& info
!= NULL
);
933 TypeNode
*pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
936 vtable
= pnode
->data
->common
.value_table
;
939 static const GTypeValueTable zero_vtable
= { NULL
, };
941 value_table
= &zero_vtable
;
946 /* need to setup vtable_size since we have to allocate it with data in one chunk */
947 vtable_size
= sizeof (GTypeValueTable
);
948 if (value_table
->collect_format
)
949 vtable_size
+= strlen (value_table
->collect_format
);
950 if (value_table
->lcopy_format
)
951 vtable_size
+= strlen (value_table
->lcopy_format
);
955 if (node
->is_instantiatable
) /* carefull, is_instantiatable is also is_classed */
957 data
= g_malloc0 (sizeof (InstanceData
) + vtable_size
);
959 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (InstanceData
));
960 data
->instance
.class_size
= info
->class_size
;
961 data
->instance
.class_init_base
= info
->base_init
;
962 data
->instance
.class_finalize_base
= info
->base_finalize
;
963 data
->instance
.class_init
= info
->class_init
;
964 data
->instance
.class_finalize
= info
->class_finalize
;
965 data
->instance
.class_data
= info
->class_data
;
966 data
->instance
.class = NULL
;
967 data
->instance
.init_state
= UNINITIALIZED
;
968 data
->instance
.instance_size
= info
->instance_size
;
969 /* We'll set the final value for data->instance.private size
970 * after the parent class has been initialized
972 data
->instance
.private_size
= 0;
973 #ifdef DISABLE_MEM_POOLS
974 data
->instance
.n_preallocs
= 0;
975 #else /* !DISABLE_MEM_POOLS */
976 data
->instance
.n_preallocs
= MIN (info
->n_preallocs
, 1024);
977 #endif /* !DISABLE_MEM_POOLS */
978 data
->instance
.instance_init
= info
->instance_init
;
979 data
->instance
.mem_chunk
= NULL
;
981 else if (node
->is_classed
) /* only classed */
983 data
= g_malloc0 (sizeof (ClassData
) + vtable_size
);
985 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (ClassData
));
986 data
->class.class_size
= info
->class_size
;
987 data
->class.class_init_base
= info
->base_init
;
988 data
->class.class_finalize_base
= info
->base_finalize
;
989 data
->class.class_init
= info
->class_init
;
990 data
->class.class_finalize
= info
->class_finalize
;
991 data
->class.class_data
= info
->class_data
;
992 data
->class.class = NULL
;
993 data
->class.init_state
= UNINITIALIZED
;
995 else if (NODE_IS_IFACE (node
))
997 data
= g_malloc0 (sizeof (IFaceData
) + vtable_size
);
999 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (IFaceData
));
1000 data
->iface
.vtable_size
= info
->class_size
;
1001 data
->iface
.vtable_init_base
= info
->base_init
;
1002 data
->iface
.vtable_finalize_base
= info
->base_finalize
;
1003 data
->iface
.dflt_init
= info
->class_init
;
1004 data
->iface
.dflt_finalize
= info
->class_finalize
;
1005 data
->iface
.dflt_data
= info
->class_data
;
1006 data
->iface
.dflt_vtable
= NULL
;
1010 data
= g_malloc0 (sizeof (CommonData
) + vtable_size
);
1012 vtable
= G_STRUCT_MEMBER_P (data
, sizeof (CommonData
));
1016 node
->data
->common
.ref_count
= 1;
1022 /* we allocate the vtable and its strings together with the type data, so
1023 * children can take over their parent's vtable pointer, and we don't
1024 * need to worry freeing it or not when the child data is destroyed
1026 *vtable
= *value_table
;
1027 p
= G_STRUCT_MEMBER_P (vtable
, sizeof (*vtable
));
1029 vtable
->collect_format
= p
;
1030 if (value_table
->collect_format
)
1032 strcat (p
, value_table
->collect_format
);
1033 p
+= strlen (value_table
->collect_format
);
1037 vtable
->lcopy_format
= p
;
1038 if (value_table
->lcopy_format
)
1039 strcat (p
, value_table
->lcopy_format
);
1041 node
->data
->common
.value_table
= vtable
;
1042 node
->mutatable_check_cache
= (node
->data
->common
.value_table
->value_init
!= NULL
&&
1043 !((G_TYPE_FLAG_VALUE_ABSTRACT
| G_TYPE_FLAG_ABSTRACT
) &
1044 GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
))));
1046 g_assert (node
->data
->common
.value_table
!= NULL
); /* paranoid */
1050 type_data_ref_Wm (TypeNode
*node
)
1054 TypeNode
*pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
1056 GTypeValueTable tmp_value_table
;
1058 g_assert (node
->plugin
!= NULL
);
1062 type_data_ref_Wm (pnode
);
1064 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
1067 memset (&tmp_info
, 0, sizeof (tmp_info
));
1068 memset (&tmp_value_table
, 0, sizeof (tmp_value_table
));
1070 G_WRITE_UNLOCK (&type_rw_lock
);
1071 g_type_plugin_use (node
->plugin
);
1072 g_type_plugin_complete_type_info (node
->plugin
, NODE_TYPE (node
), &tmp_info
, &tmp_value_table
);
1073 G_WRITE_LOCK (&type_rw_lock
);
1075 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
1077 check_type_info_I (pnode
, NODE_FUNDAMENTAL_TYPE (node
), NODE_NAME (node
), &tmp_info
);
1078 type_data_make_W (node
, &tmp_info
,
1079 check_value_table_I (NODE_NAME (node
),
1080 &tmp_value_table
) ? &tmp_value_table
: NULL
);
1084 g_assert (node
->data
->common
.ref_count
> 0);
1086 node
->data
->common
.ref_count
+= 1;
1091 type_data_unref_Wm (TypeNode
*node
,
1094 g_assert (node
->data
&& node
->data
->common
.ref_count
);
1096 if (node
->data
->common
.ref_count
> 1)
1097 node
->data
->common
.ref_count
-= 1;
1102 g_warning ("static type `%s' unreferenced too often",
1107 type_data_last_unref_Wm (NODE_TYPE (node
), uncached
);
1112 type_node_add_iface_entry_W (TypeNode
*node
,
1114 IFaceEntry
*parent_entry
)
1116 IFaceEntry
*entries
;
1119 g_assert (node
->is_instantiatable
&& CLASSED_NODE_N_IFACES (node
) < MAX_N_IFACES
);
1121 entries
= CLASSED_NODE_IFACES_ENTRIES (node
);
1122 for (i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1123 if (entries
[i
].iface_type
== iface_type
)
1125 /* this can happen in two cases:
1126 * - our parent type already conformed to iface_type and node
1127 * got it's own holder info. here, our children already have
1128 * entries and NULL vtables, since this will only work for
1129 * uninitialized classes.
1130 * - an interface type is added to an ancestor after it was
1131 * added to a child type.
1134 g_assert (entries
[i
].vtable
== NULL
&& entries
[i
].init_state
== UNINITIALIZED
);
1137 /* sick, interface is added to ancestor *after* child type;
1138 * nothing todo, the entry and our children were already setup correctly
1143 else if (entries
[i
].iface_type
> iface_type
)
1145 CLASSED_NODE_N_IFACES (node
) += 1;
1146 CLASSED_NODE_IFACES_ENTRIES (node
) = g_renew (IFaceEntry
,
1147 CLASSED_NODE_IFACES_ENTRIES (node
),
1148 CLASSED_NODE_N_IFACES (node
));
1149 entries
= CLASSED_NODE_IFACES_ENTRIES (node
);
1150 g_memmove (entries
+ i
+ 1, entries
+ i
, sizeof (entries
[0]) * (CLASSED_NODE_N_IFACES (node
) - i
- 1));
1151 entries
[i
].iface_type
= iface_type
;
1152 entries
[i
].vtable
= NULL
;
1153 entries
[i
].init_state
= UNINITIALIZED
;
1157 if (node
->data
&& node
->data
->class.init_state
>= BASE_IFACE_INIT
)
1159 entries
[i
].init_state
= INITIALIZED
;
1160 entries
[i
].vtable
= parent_entry
->vtable
;
1162 for (i
= 0; i
< node
->n_children
; i
++)
1163 type_node_add_iface_entry_W (lookup_type_node_I (node
->children
[i
]), iface_type
, &entries
[i
]);
1168 type_add_interface_Wm (TypeNode
*node
,
1170 const GInterfaceInfo
*info
,
1171 GTypePlugin
*plugin
)
1173 IFaceHolder
*iholder
= g_new0 (IFaceHolder
, 1);
1177 g_assert (node
->is_instantiatable
&& NODE_IS_IFACE (iface
) && ((info
&& !plugin
) || (!info
&& plugin
)));
1179 iholder
->next
= iface_node_get_holders_L (iface
);
1180 iface_node_set_holders_W (iface
, iholder
);
1181 iholder
->instance_type
= NODE_TYPE (node
);
1182 iholder
->info
= info
? g_memdup (info
, sizeof (*info
)) : NULL
;
1183 iholder
->plugin
= plugin
;
1185 /* create an iface entry for this type */
1186 type_node_add_iface_entry_W (node
, NODE_TYPE (iface
), NULL
);
1188 /* if the class is already (partly) initialized, we may need to base
1189 * initalize and/or initialize the new interface.
1193 InitState class_state
= node
->data
->class.init_state
;
1195 if (class_state
>= BASE_IFACE_INIT
)
1196 type_iface_vtable_base_init_Wm (iface
, node
);
1198 if (class_state
>= IFACE_INIT
)
1199 type_iface_vtable_iface_init_Wm (iface
, node
);
1202 /* create iface entries for children of this type */
1203 entry
= type_lookup_iface_entry_L (node
, iface
);
1204 for (i
= 0; i
< node
->n_children
; i
++)
1205 type_node_add_iface_entry_W (lookup_type_node_I (node
->children
[i
]), NODE_TYPE (iface
), entry
);
1209 type_iface_add_prerequisite_W (TypeNode
*iface
,
1210 TypeNode
*prerequisite_node
)
1212 GType prerequisite_type
= NODE_TYPE (prerequisite_node
);
1213 GType
*prerequisites
, *dependants
;
1214 guint n_dependants
, i
;
1216 g_assert (NODE_IS_IFACE (iface
) &&
1217 IFACE_NODE_N_PREREQUISITES (iface
) < MAX_N_PREREQUISITES
&&
1218 (prerequisite_node
->is_instantiatable
|| NODE_IS_IFACE (prerequisite_node
)));
1220 prerequisites
= IFACE_NODE_PREREQUISITES (iface
);
1221 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
1222 if (prerequisites
[i
] == prerequisite_type
)
1223 return; /* we already have that prerequisiste */
1224 else if (prerequisites
[i
] > prerequisite_type
)
1226 IFACE_NODE_N_PREREQUISITES (iface
) += 1;
1227 IFACE_NODE_PREREQUISITES (iface
) = g_renew (GType
,
1228 IFACE_NODE_PREREQUISITES (iface
),
1229 IFACE_NODE_N_PREREQUISITES (iface
));
1230 prerequisites
= IFACE_NODE_PREREQUISITES (iface
);
1231 g_memmove (prerequisites
+ i
+ 1, prerequisites
+ i
,
1232 sizeof (prerequisites
[0]) * (IFACE_NODE_N_PREREQUISITES (iface
) - i
- 1));
1233 prerequisites
[i
] = prerequisite_type
;
1235 /* we want to get notified when prerequisites get added to prerequisite_node */
1236 if (NODE_IS_IFACE (prerequisite_node
))
1238 dependants
= iface_node_get_dependants_array_L (prerequisite_node
);
1239 n_dependants
= dependants
? dependants
[0] : 0;
1241 dependants
= g_renew (GType
, dependants
, n_dependants
+ 1);
1242 dependants
[n_dependants
] = NODE_TYPE (iface
);
1243 dependants
[0] = n_dependants
;
1244 iface_node_set_dependants_array_W (prerequisite_node
, dependants
);
1247 /* we need to notify all dependants */
1248 dependants
= iface_node_get_dependants_array_L (iface
);
1249 n_dependants
= dependants
? dependants
[0] : 0;
1250 for (i
= 1; i
<= n_dependants
; i
++)
1251 type_iface_add_prerequisite_W (lookup_type_node_I (dependants
[i
]), prerequisite_node
);
1255 g_type_interface_add_prerequisite (GType interface_type
,
1256 GType prerequisite_type
)
1258 TypeNode
*iface
, *prerequisite_node
;
1259 IFaceHolder
*holders
;
1261 g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type
)); /* G_TYPE_IS_INTERFACE() is an external call: _U */
1262 g_return_if_fail (!g_type_is_a (interface_type
, prerequisite_type
));
1263 g_return_if_fail (!g_type_is_a (prerequisite_type
, interface_type
));
1265 iface
= lookup_type_node_I (interface_type
);
1266 prerequisite_node
= lookup_type_node_I (prerequisite_type
);
1267 if (!iface
|| !prerequisite_node
|| !NODE_IS_IFACE (iface
))
1269 g_warning ("interface type `%s' or prerequisite type `%s' invalid",
1270 type_descriptive_name_I (interface_type
),
1271 type_descriptive_name_I (prerequisite_type
));
1274 G_WRITE_LOCK (&type_rw_lock
);
1275 holders
= iface_node_get_holders_L (iface
);
1278 G_WRITE_UNLOCK (&type_rw_lock
);
1279 g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'",
1280 type_descriptive_name_I (prerequisite_type
),
1281 type_descriptive_name_I (interface_type
),
1282 type_descriptive_name_I (holders
->instance_type
));
1285 if (prerequisite_node
->is_instantiatable
)
1289 /* can have at most one publically installable instantiatable prerequisite */
1290 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
1292 TypeNode
*prnode
= lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface
)[i
]);
1294 if (prnode
->is_instantiatable
)
1296 G_WRITE_UNLOCK (&type_rw_lock
);
1297 g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'",
1298 type_descriptive_name_I (prerequisite_type
),
1299 type_descriptive_name_I (interface_type
),
1300 type_descriptive_name_I (NODE_TYPE (prnode
)));
1305 for (i
= 0; i
< prerequisite_node
->n_supers
+ 1; i
++)
1306 type_iface_add_prerequisite_W (iface
, lookup_type_node_I (prerequisite_node
->supers
[i
]));
1307 G_WRITE_UNLOCK (&type_rw_lock
);
1309 else if (NODE_IS_IFACE (prerequisite_node
))
1311 GType
*prerequisites
;
1314 prerequisites
= IFACE_NODE_PREREQUISITES (prerequisite_node
);
1315 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (prerequisite_node
); i
++)
1316 type_iface_add_prerequisite_W (iface
, lookup_type_node_I (prerequisites
[i
]));
1317 type_iface_add_prerequisite_W (iface
, prerequisite_node
);
1318 G_WRITE_UNLOCK (&type_rw_lock
);
1322 G_WRITE_UNLOCK (&type_rw_lock
);
1323 g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface",
1324 type_descriptive_name_I (prerequisite_type
),
1325 type_descriptive_name_I (interface_type
));
1329 GType
* /* free result */
1330 g_type_interface_prerequisites (GType interface_type
,
1331 guint
*n_prerequisites
)
1335 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type
), NULL
);
1337 iface
= lookup_type_node_I (interface_type
);
1341 TypeNode
*inode
= NULL
;
1344 G_READ_LOCK (&type_rw_lock
);
1345 types
= g_new0 (GType
, IFACE_NODE_N_PREREQUISITES (iface
) + 1);
1346 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (iface
); i
++)
1348 GType prerequisite
= IFACE_NODE_PREREQUISITES (iface
)[i
];
1349 TypeNode
*node
= lookup_type_node_I (prerequisite
);
1350 if (node
->is_instantiatable
&&
1351 (!inode
|| type_node_is_a_L (node
, inode
)))
1354 types
[n
++] = NODE_TYPE (node
);
1357 types
[n
++] = NODE_TYPE (inode
);
1359 if (n_prerequisites
)
1360 *n_prerequisites
= n
;
1361 G_READ_UNLOCK (&type_rw_lock
);
1367 if (n_prerequisites
)
1368 *n_prerequisites
= 0;
1376 type_iface_peek_holder_L (TypeNode
*iface
,
1377 GType instance_type
)
1379 IFaceHolder
*iholder
;
1381 g_assert (NODE_IS_IFACE (iface
));
1383 iholder
= iface_node_get_holders_L (iface
);
1384 while (iholder
&& iholder
->instance_type
!= instance_type
)
1385 iholder
= iholder
->next
;
1390 type_iface_retrieve_holder_info_Wm (TypeNode
*iface
,
1391 GType instance_type
,
1394 IFaceHolder
*iholder
= type_iface_peek_holder_L (iface
, instance_type
);
1396 if (iholder
&& !iholder
->info
&& need_info
)
1398 GInterfaceInfo tmp_info
;
1400 g_assert (iholder
->plugin
!= NULL
);
1402 type_data_ref_Wm (iface
);
1404 INVALID_RECURSION ("g_type_plugin_*", iface
->plugin
, NODE_NAME (iface
));
1406 memset (&tmp_info
, 0, sizeof (tmp_info
));
1408 G_WRITE_UNLOCK (&type_rw_lock
);
1409 g_type_plugin_use (iholder
->plugin
);
1410 g_type_plugin_complete_interface_info (iholder
->plugin
, instance_type
, NODE_TYPE (iface
), &tmp_info
);
1411 G_WRITE_LOCK (&type_rw_lock
);
1413 INVALID_RECURSION ("g_type_plugin_*", iholder
->plugin
, NODE_NAME (iface
));
1415 check_interface_info_I (iface
, instance_type
, &tmp_info
);
1416 iholder
->info
= g_memdup (&tmp_info
, sizeof (tmp_info
));
1419 return iholder
; /* we don't modify write lock upon returning NULL */
1423 type_iface_blow_holder_info_Wm (TypeNode
*iface
,
1424 GType instance_type
)
1426 IFaceHolder
*iholder
= iface_node_get_holders_L (iface
);
1428 g_assert (NODE_IS_IFACE (iface
));
1430 while (iholder
->instance_type
!= instance_type
)
1431 iholder
= iholder
->next
;
1433 if (iholder
->info
&& iholder
->plugin
)
1435 g_free (iholder
->info
);
1436 iholder
->info
= NULL
;
1438 G_WRITE_UNLOCK (&type_rw_lock
);
1439 g_type_plugin_unuse (iholder
->plugin
);
1440 G_WRITE_LOCK (&type_rw_lock
);
1442 type_data_unref_Wm (iface
, FALSE
);
1446 /* Assumes type's class already exists
1448 static inline size_t
1449 type_total_instance_size_I (TypeNode
*node
)
1451 gsize total_instance_size
;
1453 total_instance_size
= node
->data
->instance
.instance_size
;
1454 if (node
->data
->instance
.private_size
!= 0)
1455 total_instance_size
= ALIGN_STRUCT (total_instance_size
) + node
->data
->instance
.private_size
;
1457 return total_instance_size
;
1460 /* --- type structure creation/destruction --- */
1464 } InstanceRealClass
;
1466 instance_real_class_cmp (gconstpointer p1
,
1469 const InstanceRealClass
*irc1
= p1
;
1470 const InstanceRealClass
*irc2
= p2
;
1471 guint8
*i1
= irc1
->instance
;
1472 guint8
*i2
= irc2
->instance
;
1473 return G_BSEARCH_ARRAY_CMP (i1
, i2
);
1475 G_LOCK_DEFINE_STATIC (instance_real_class
);
1476 static GBSearchArray
*instance_real_class_bsa
= NULL
;
1477 static GBSearchConfig instance_real_class_bconfig
= {
1478 sizeof (InstanceRealClass
),
1479 instance_real_class_cmp
,
1483 instance_real_class_set (gpointer instance
,
1486 InstanceRealClass key
;
1487 key
.instance
= instance
;
1489 G_LOCK (instance_real_class
);
1490 if (!instance_real_class_bsa
)
1491 instance_real_class_bsa
= g_bsearch_array_create (&instance_real_class_bconfig
);
1492 instance_real_class_bsa
= g_bsearch_array_replace (instance_real_class_bsa
, &instance_real_class_bconfig
, &key
);
1493 G_UNLOCK (instance_real_class
);
1496 instance_real_class_remove (gpointer instance
)
1498 InstanceRealClass key
, *node
;
1500 key
.instance
= instance
;
1501 G_LOCK (instance_real_class
);
1502 node
= g_bsearch_array_lookup (instance_real_class_bsa
, &instance_real_class_bconfig
, &key
);
1503 index
= g_bsearch_array_get_index (instance_real_class_bsa
, &instance_real_class_bconfig
, node
);
1504 instance_real_class_bsa
= g_bsearch_array_remove (instance_real_class_bsa
, &instance_real_class_bconfig
, index
);
1505 if (!g_bsearch_array_get_n_nodes (instance_real_class_bsa
))
1507 g_bsearch_array_free (instance_real_class_bsa
, &instance_real_class_bconfig
);
1508 instance_real_class_bsa
= NULL
;
1510 G_UNLOCK (instance_real_class
);
1512 static inline GTypeClass
*
1513 instance_real_class_get (gpointer instance
)
1515 InstanceRealClass key
, *node
;
1516 key
.instance
= instance
;
1517 G_LOCK (instance_real_class
);
1518 node
= instance_real_class_bsa
? g_bsearch_array_lookup (instance_real_class_bsa
, &instance_real_class_bconfig
, &key
) : NULL
;
1519 G_UNLOCK (instance_real_class
);
1520 return node
? node
->class : NULL
;
1524 g_type_create_instance (GType type
)
1527 GTypeInstance
*instance
;
1530 gsize total_instance_size
;
1532 node
= lookup_type_node_I (type
);
1533 if (!node
|| !node
->is_instantiatable
)
1535 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
1536 type_descriptive_name_I (type
));
1539 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1540 if (!node
->mutatable_check_cache
&& G_TYPE_IS_ABSTRACT (type
))
1542 g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
1543 type_descriptive_name_I (type
));
1547 class = g_type_class_ref (type
);
1549 total_instance_size
= type_total_instance_size_I (node
);
1551 if (node
->data
->instance
.n_preallocs
)
1553 G_WRITE_LOCK (&type_rw_lock
);
1554 if (!node
->data
->instance
.mem_chunk
)
1556 /* If there isn't private data, the compiler will have already
1557 * added the necessary padding, but in the private data case, we
1558 * have to pad ourselves to ensure proper alignment of all the
1559 * atoms in the slab.
1561 gsize atom_size
= total_instance_size
;
1562 if (node
->data
->instance
.private_size
)
1563 atom_size
= ALIGN_STRUCT (atom_size
);
1565 node
->data
->instance
.mem_chunk
= g_mem_chunk_new (NODE_NAME (node
),
1568 node
->data
->instance
.n_preallocs
),
1572 instance
= g_chunk_new0 (GTypeInstance
, node
->data
->instance
.mem_chunk
);
1573 G_WRITE_UNLOCK (&type_rw_lock
);
1576 instance
= g_malloc0 (total_instance_size
); /* fine without read lock */
1578 if (node
->data
->instance
.private_size
)
1579 instance_real_class_set (instance
, class);
1580 for (i
= node
->n_supers
; i
> 0; i
--)
1584 pnode
= lookup_type_node_I (node
->supers
[i
]);
1585 if (pnode
->data
->instance
.instance_init
)
1587 instance
->g_class
= pnode
->data
->instance
.class;
1588 pnode
->data
->instance
.instance_init (instance
, class);
1591 if (node
->data
->instance
.private_size
)
1592 instance_real_class_remove (instance
);
1594 instance
->g_class
= class;
1595 if (node
->data
->instance
.instance_init
)
1596 node
->data
->instance
.instance_init (instance
, class);
1602 g_type_free_instance (GTypeInstance
*instance
)
1607 g_return_if_fail (instance
!= NULL
&& instance
->g_class
!= NULL
);
1609 class = instance
->g_class
;
1610 node
= lookup_type_node_I (class->g_type
);
1611 if (!node
|| !node
->is_instantiatable
|| !node
->data
|| node
->data
->class.class != (gpointer
) class)
1613 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
1614 type_descriptive_name_I (class->g_type
));
1617 /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1618 if (!node
->mutatable_check_cache
&& G_TYPE_IS_ABSTRACT (NODE_TYPE (node
)))
1620 g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
1625 instance
->g_class
= NULL
;
1626 #ifdef G_ENABLE_DEBUG
1627 memset (instance
, 0xaa, type_total_instance_size_I (node
)); /* debugging hack */
1629 if (node
->data
->instance
.n_preallocs
)
1631 G_WRITE_LOCK (&type_rw_lock
);
1632 g_chunk_free (instance
, node
->data
->instance
.mem_chunk
);
1633 G_WRITE_UNLOCK (&type_rw_lock
);
1638 g_type_class_unref (class);
1642 type_iface_ensure_dflt_vtable_Wm (TypeNode
*iface
)
1644 g_assert (iface
->data
);
1646 if (!iface
->data
->iface
.dflt_vtable
)
1648 GTypeInterface
*vtable
= g_malloc0 (iface
->data
->iface
.vtable_size
);
1649 iface
->data
->iface
.dflt_vtable
= vtable
;
1650 vtable
->g_type
= NODE_TYPE (iface
);
1651 vtable
->g_instance_type
= 0;
1652 if (iface
->data
->iface
.vtable_init_base
||
1653 iface
->data
->iface
.dflt_init
)
1655 G_WRITE_UNLOCK (&type_rw_lock
);
1656 if (iface
->data
->iface
.vtable_init_base
)
1657 iface
->data
->iface
.vtable_init_base (vtable
);
1658 if (iface
->data
->iface
.dflt_init
)
1659 iface
->data
->iface
.dflt_init (vtable
, (gpointer
) iface
->data
->iface
.dflt_data
);
1660 G_WRITE_LOCK (&type_rw_lock
);
1666 /* This is called to allocate and do the first part of initializing
1667 * the interface vtable; type_iface_vtable_iface_init_Wm() does the remainder.
1669 * A FALSE return indicates that we didn't find an init function for
1670 * this type/iface pair, so the vtable from the parent type should
1671 * be used. Note that the write lock is not modified upon a FALSE
1675 type_iface_vtable_base_init_Wm (TypeNode
*iface
,
1679 IFaceHolder
*iholder
;
1680 GTypeInterface
*vtable
= NULL
;
1683 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1684 iholder
= type_iface_retrieve_holder_info_Wm (iface
, NODE_TYPE (node
), TRUE
);
1686 return FALSE
; /* we don't modify write lock upon FALSE */
1688 type_iface_ensure_dflt_vtable_Wm (iface
);
1690 entry
= type_lookup_iface_entry_L (node
, iface
);
1692 g_assert (iface
->data
&& entry
&& entry
->vtable
== NULL
&& iholder
&& iholder
->info
);
1694 entry
->init_state
= IFACE_INIT
;
1696 pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
1697 if (pnode
) /* want to copy over parent iface contents */
1699 IFaceEntry
*pentry
= type_lookup_iface_entry_L (pnode
, iface
);
1702 vtable
= g_memdup (pentry
->vtable
, iface
->data
->iface
.vtable_size
);
1705 vtable
= g_memdup (iface
->data
->iface
.dflt_vtable
, iface
->data
->iface
.vtable_size
);
1706 entry
->vtable
= vtable
;
1707 vtable
->g_type
= NODE_TYPE (iface
);
1708 vtable
->g_instance_type
= NODE_TYPE (node
);
1710 if (iface
->data
->iface
.vtable_init_base
)
1712 G_WRITE_UNLOCK (&type_rw_lock
);
1713 iface
->data
->iface
.vtable_init_base (vtable
);
1714 G_WRITE_LOCK (&type_rw_lock
);
1716 return TRUE
; /* initialized the vtable */
1719 /* Finishes what type_iface_vtable_base_init_Wm started by
1720 * calling the interface init function.
1721 * this function may only be called for types with their
1722 * own interface holder info, i.e. types for which
1723 * g_type_add_interface*() was called and not children thereof.
1726 type_iface_vtable_iface_init_Wm (TypeNode
*iface
,
1729 IFaceEntry
*entry
= type_lookup_iface_entry_L (node
, iface
);
1730 IFaceHolder
*iholder
= type_iface_peek_holder_L (iface
, NODE_TYPE (node
));
1731 GTypeInterface
*vtable
= NULL
;
1734 /* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */
1735 g_assert (iface
->data
&& entry
&& iholder
&& iholder
->info
);
1736 g_assert (entry
->init_state
== IFACE_INIT
); /* assert prior base_init() */
1738 entry
->init_state
= INITIALIZED
;
1740 vtable
= entry
->vtable
;
1742 if (iholder
->info
->interface_init
)
1744 G_WRITE_UNLOCK (&type_rw_lock
);
1745 if (iholder
->info
->interface_init
)
1746 iholder
->info
->interface_init (vtable
, iholder
->info
->interface_data
);
1747 G_WRITE_LOCK (&type_rw_lock
);
1750 for (i
= 0; i
< static_n_iface_check_funcs
; i
++)
1752 GTypeInterfaceCheckFunc check_func
= static_iface_check_funcs
[i
].check_func
;
1753 gpointer check_data
= static_iface_check_funcs
[i
].check_data
;
1755 G_WRITE_UNLOCK (&type_rw_lock
);
1756 check_func (check_data
, (gpointer
)vtable
);
1757 G_WRITE_LOCK (&type_rw_lock
);
1762 type_iface_vtable_finalize_Wm (TypeNode
*iface
,
1764 GTypeInterface
*vtable
)
1766 IFaceEntry
*entry
= type_lookup_iface_entry_L (node
, iface
);
1767 IFaceHolder
*iholder
;
1769 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
1770 iholder
= type_iface_retrieve_holder_info_Wm (iface
, NODE_TYPE (node
), FALSE
);
1772 return FALSE
; /* we don't modify write lock upon FALSE */
1774 g_assert (entry
&& entry
->vtable
== vtable
&& iholder
->info
);
1776 entry
->vtable
= NULL
;
1777 entry
->init_state
= UNINITIALIZED
;
1778 if (iholder
->info
->interface_finalize
|| iface
->data
->iface
.vtable_finalize_base
)
1780 G_WRITE_UNLOCK (&type_rw_lock
);
1781 if (iholder
->info
->interface_finalize
)
1782 iholder
->info
->interface_finalize (vtable
, iholder
->info
->interface_data
);
1783 if (iface
->data
->iface
.vtable_finalize_base
)
1784 iface
->data
->iface
.vtable_finalize_base (vtable
);
1785 G_WRITE_LOCK (&type_rw_lock
);
1788 vtable
->g_instance_type
= 0;
1791 type_iface_blow_holder_info_Wm (iface
, NODE_TYPE (node
));
1793 return TRUE
; /* write lock modified */
1797 type_class_init_Wm (TypeNode
*node
,
1800 GSList
*slist
, *init_slist
= NULL
;
1803 TypeNode
*bnode
, *pnode
;
1806 g_assert (node
->is_classed
&& node
->data
&&
1807 node
->data
->class.class_size
&&
1808 !node
->data
->class.class &&
1809 node
->data
->class.init_state
== UNINITIALIZED
);
1811 class = g_malloc0 (node
->data
->class.class_size
);
1812 node
->data
->class.class = class;
1813 node
->data
->class.init_state
= BASE_CLASS_INIT
;
1817 TypeNode
*pnode
= lookup_type_node_I (pclass
->g_type
);
1819 memcpy (class, pclass
, pnode
->data
->class.class_size
);
1821 if (node
->is_instantiatable
)
1823 /* We need to initialize the private_size here rather than in
1824 * type_data_make_W() since the class init for the parent
1825 * class may have changed pnode->data->instance.private_size.
1827 node
->data
->instance
.private_size
= pnode
->data
->instance
.private_size
;
1830 class->g_type
= NODE_TYPE (node
);
1832 G_WRITE_UNLOCK (&type_rw_lock
);
1834 /* stack all base class initialization functions, so we
1835 * call them in ascending order.
1837 for (bnode
= node
; bnode
; bnode
= lookup_type_node_I (NODE_PARENT_TYPE (bnode
)))
1838 if (bnode
->data
->class.class_init_base
)
1839 init_slist
= g_slist_prepend (init_slist
, (gpointer
) bnode
->data
->class.class_init_base
);
1840 for (slist
= init_slist
; slist
; slist
= slist
->next
)
1842 GBaseInitFunc class_init_base
= (GBaseInitFunc
) slist
->data
;
1844 class_init_base (class);
1846 g_slist_free (init_slist
);
1848 G_WRITE_LOCK (&type_rw_lock
);
1850 node
->data
->class.init_state
= BASE_IFACE_INIT
;
1852 /* Before we initialize the class, base initialize all interfaces, either
1853 * from parent, or through our holder info
1855 pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
1858 while (i
< CLASSED_NODE_N_IFACES (node
))
1860 entry
= &CLASSED_NODE_IFACES_ENTRIES (node
)[i
];
1861 while (i
< CLASSED_NODE_N_IFACES (node
) &&
1862 entry
->init_state
== IFACE_INIT
)
1868 if (i
== CLASSED_NODE_N_IFACES (node
))
1871 if (!type_iface_vtable_base_init_Wm (lookup_type_node_I (entry
->iface_type
), node
))
1875 /* need to get this interface from parent, type_iface_vtable_base_init_Wm()
1876 * doesn't modify write lock upon FALSE, so entry is still valid;
1878 g_assert (pnode
!= NULL
);
1880 for (j
= 0; j
< CLASSED_NODE_N_IFACES (pnode
); j
++)
1882 IFaceEntry
*pentry
= CLASSED_NODE_IFACES_ENTRIES (pnode
) + j
;
1884 if (pentry
->iface_type
== entry
->iface_type
)
1886 entry
->vtable
= pentry
->vtable
;
1887 entry
->init_state
= INITIALIZED
;
1891 g_assert (entry
->vtable
!= NULL
);
1894 /* If the write lock was released, additional interface entries might
1895 * have been inserted into CLASSED_NODE_IFACES_ENTRIES (node); they'll
1896 * be base-initialized when inserted, so we don't have to worry that
1897 * we might miss them. Uninitialized entries can only be moved higher
1898 * when new ones are inserted.
1903 node
->data
->class.init_state
= CLASS_INIT
;
1905 G_WRITE_UNLOCK (&type_rw_lock
);
1907 if (node
->data
->class.class_init
)
1908 node
->data
->class.class_init (class, (gpointer
) node
->data
->class.class_data
);
1910 G_WRITE_LOCK (&type_rw_lock
);
1912 node
->data
->class.init_state
= IFACE_INIT
;
1914 /* finish initializing the interfaces through our holder info.
1915 * inherited interfaces are already init_state == INITIALIZED, because
1916 * they either got setup in the above base_init loop, or during
1917 * class_init from within type_add_interface_Wm() for this or
1918 * an anchestor type.
1923 entry
= &CLASSED_NODE_IFACES_ENTRIES (node
)[i
];
1924 while (i
< CLASSED_NODE_N_IFACES (node
) &&
1925 entry
->init_state
== INITIALIZED
)
1931 if (i
== CLASSED_NODE_N_IFACES (node
))
1934 type_iface_vtable_iface_init_Wm (lookup_type_node_I (entry
->iface_type
), node
);
1936 /* As in the loop above, additional initialized entries might be inserted
1937 * if the write lock is released, but that's harmless because the entries
1938 * we need to initialize only move higher in the list.
1943 node
->data
->class.init_state
= INITIALIZED
;
1947 type_data_finalize_class_ifaces_Wm (TypeNode
*node
)
1951 g_assert (node
->is_instantiatable
&& node
->data
&& node
->data
->class.class && node
->data
->common
.ref_count
== 0);
1954 for (i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
1956 IFaceEntry
*entry
= CLASSED_NODE_IFACES_ENTRIES (node
) + i
;
1959 if (type_iface_vtable_finalize_Wm (lookup_type_node_I (entry
->iface_type
), node
, entry
->vtable
))
1961 /* refetch entries, IFACES_ENTRIES might be modified */
1966 /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
1967 * iface vtable came from parent
1969 entry
->vtable
= NULL
;
1970 entry
->init_state
= UNINITIALIZED
;
1977 type_data_finalize_class_U (TypeNode
*node
,
1980 GTypeClass
*class = cdata
->class;
1983 g_assert (cdata
->class && cdata
->common
.ref_count
== 0);
1985 if (cdata
->class_finalize
)
1986 cdata
->class_finalize (class, (gpointer
) cdata
->class_data
);
1988 /* call all base class destruction functions in descending order
1990 if (cdata
->class_finalize_base
)
1991 cdata
->class_finalize_base (class);
1992 for (bnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
)); bnode
; bnode
= lookup_type_node_I (NODE_PARENT_TYPE (bnode
)))
1993 if (bnode
->data
->class.class_finalize_base
)
1994 bnode
->data
->class.class_finalize_base (class);
1996 g_free (cdata
->class);
2000 type_data_last_unref_Wm (GType type
,
2003 TypeNode
*node
= lookup_type_node_I (type
);
2005 g_return_if_fail (node
!= NULL
&& node
->plugin
!= NULL
);
2007 if (!node
->data
|| node
->data
->common
.ref_count
== 0)
2009 g_warning ("cannot drop last reference to unreferenced type `%s'",
2010 type_descriptive_name_I (type
));
2014 /* call class cache hooks */
2015 if (node
->is_classed
&& node
->data
&& node
->data
->class.class && static_n_class_cache_funcs
&& !uncached
)
2019 G_WRITE_UNLOCK (&type_rw_lock
);
2020 G_READ_LOCK (&type_rw_lock
);
2021 for (i
= 0; i
< static_n_class_cache_funcs
; i
++)
2023 GTypeClassCacheFunc cache_func
= static_class_cache_funcs
[i
].cache_func
;
2024 gpointer cache_data
= static_class_cache_funcs
[i
].cache_data
;
2025 gboolean need_break
;
2027 G_READ_UNLOCK (&type_rw_lock
);
2028 need_break
= cache_func (cache_data
, node
->data
->class.class);
2029 G_READ_LOCK (&type_rw_lock
);
2030 if (!node
->data
|| node
->data
->common
.ref_count
== 0)
2031 INVALID_RECURSION ("GType class cache function ", cache_func
, NODE_NAME (node
));
2035 G_READ_UNLOCK (&type_rw_lock
);
2036 G_WRITE_LOCK (&type_rw_lock
);
2039 if (node
->data
->common
.ref_count
> 1) /* may have been re-referenced meanwhile */
2040 node
->data
->common
.ref_count
-= 1;
2043 GType ptype
= NODE_PARENT_TYPE (node
);
2046 node
->data
->common
.ref_count
= 0;
2048 if (node
->is_instantiatable
&& node
->data
->instance
.mem_chunk
)
2050 g_mem_chunk_destroy (node
->data
->instance
.mem_chunk
);
2051 node
->data
->instance
.mem_chunk
= NULL
;
2055 if (node
->is_classed
&& tdata
->class.class)
2057 if (CLASSED_NODE_N_IFACES (node
))
2058 type_data_finalize_class_ifaces_Wm (node
);
2059 node
->mutatable_check_cache
= FALSE
;
2061 G_WRITE_UNLOCK (&type_rw_lock
);
2062 type_data_finalize_class_U (node
, &tdata
->class);
2063 G_WRITE_LOCK (&type_rw_lock
);
2065 else if (NODE_IS_IFACE (node
) && tdata
->iface
.dflt_vtable
)
2067 node
->mutatable_check_cache
= FALSE
;
2069 if (tdata
->iface
.dflt_finalize
|| tdata
->iface
.vtable_finalize_base
)
2071 G_WRITE_UNLOCK (&type_rw_lock
);
2072 if (tdata
->iface
.dflt_finalize
)
2073 tdata
->iface
.dflt_finalize (tdata
->iface
.dflt_vtable
, (gpointer
) tdata
->iface
.dflt_data
);
2074 if (tdata
->iface
.vtable_finalize_base
)
2075 tdata
->iface
.vtable_finalize_base (tdata
->iface
.dflt_vtable
);
2076 G_WRITE_LOCK (&type_rw_lock
);
2078 g_free (tdata
->iface
.dflt_vtable
);
2082 node
->mutatable_check_cache
= FALSE
;
2086 /* freeing tdata->common.value_table and its contents is taken care of
2087 * by allocating it in one chunk with tdata
2091 G_WRITE_UNLOCK (&type_rw_lock
);
2092 g_type_plugin_unuse (node
->plugin
);
2093 G_WRITE_LOCK (&type_rw_lock
);
2095 type_data_unref_Wm (lookup_type_node_I (ptype
), FALSE
);
2100 g_type_add_class_cache_func (gpointer cache_data
,
2101 GTypeClassCacheFunc cache_func
)
2105 g_return_if_fail (cache_func
!= NULL
);
2107 G_WRITE_LOCK (&type_rw_lock
);
2108 i
= static_n_class_cache_funcs
++;
2109 static_class_cache_funcs
= g_renew (ClassCacheFunc
, static_class_cache_funcs
, static_n_class_cache_funcs
);
2110 static_class_cache_funcs
[i
].cache_data
= cache_data
;
2111 static_class_cache_funcs
[i
].cache_func
= cache_func
;
2112 G_WRITE_UNLOCK (&type_rw_lock
);
2116 g_type_remove_class_cache_func (gpointer cache_data
,
2117 GTypeClassCacheFunc cache_func
)
2119 gboolean found_it
= FALSE
;
2122 g_return_if_fail (cache_func
!= NULL
);
2124 G_WRITE_LOCK (&type_rw_lock
);
2125 for (i
= 0; i
< static_n_class_cache_funcs
; i
++)
2126 if (static_class_cache_funcs
[i
].cache_data
== cache_data
&&
2127 static_class_cache_funcs
[i
].cache_func
== cache_func
)
2129 static_n_class_cache_funcs
--;
2130 g_memmove (static_class_cache_funcs
+ i
,
2131 static_class_cache_funcs
+ i
+ 1,
2132 sizeof (static_class_cache_funcs
[0]) * (static_n_class_cache_funcs
- i
));
2133 static_class_cache_funcs
= g_renew (ClassCacheFunc
, static_class_cache_funcs
, static_n_class_cache_funcs
);
2137 G_WRITE_UNLOCK (&type_rw_lock
);
2140 g_warning (G_STRLOC
": cannot remove unregistered class cache func %p with data %p",
2141 cache_func
, cache_data
);
2146 g_type_add_interface_check (gpointer check_data
,
2147 GTypeInterfaceCheckFunc check_func
)
2151 g_return_if_fail (check_func
!= NULL
);
2153 G_WRITE_LOCK (&type_rw_lock
);
2154 i
= static_n_iface_check_funcs
++;
2155 static_iface_check_funcs
= g_renew (IFaceCheckFunc
, static_iface_check_funcs
, static_n_iface_check_funcs
);
2156 static_iface_check_funcs
[i
].check_data
= check_data
;
2157 static_iface_check_funcs
[i
].check_func
= check_func
;
2158 G_WRITE_UNLOCK (&type_rw_lock
);
2162 g_type_remove_interface_check (gpointer check_data
,
2163 GTypeInterfaceCheckFunc check_func
)
2165 gboolean found_it
= FALSE
;
2168 g_return_if_fail (check_func
!= NULL
);
2170 G_WRITE_LOCK (&type_rw_lock
);
2171 for (i
= 0; i
< static_n_iface_check_funcs
; i
++)
2172 if (static_iface_check_funcs
[i
].check_data
== check_data
&&
2173 static_iface_check_funcs
[i
].check_func
== check_func
)
2175 static_n_iface_check_funcs
--;
2176 g_memmove (static_iface_check_funcs
+ i
,
2177 static_iface_check_funcs
+ i
+ 1,
2178 sizeof (static_iface_check_funcs
[0]) * (static_n_iface_check_funcs
- i
));
2179 static_iface_check_funcs
= g_renew (IFaceCheckFunc
, static_iface_check_funcs
, static_n_iface_check_funcs
);
2183 G_WRITE_UNLOCK (&type_rw_lock
);
2186 g_warning (G_STRLOC
": cannot remove unregistered class check func %p with data %p",
2187 check_func
, check_data
);
2190 /* --- type registration --- */
2192 g_type_register_fundamental (GType type_id
,
2193 const gchar
*type_name
,
2194 const GTypeInfo
*info
,
2195 const GTypeFundamentalInfo
*finfo
,
2198 GTypeFundamentalInfo
*node_finfo
;
2201 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
2202 g_return_val_if_fail (type_id
> 0, 0);
2203 g_return_val_if_fail (type_name
!= NULL
, 0);
2204 g_return_val_if_fail (info
!= NULL
, 0);
2205 g_return_val_if_fail (finfo
!= NULL
, 0);
2207 if (!check_type_name_I (type_name
))
2209 if ((type_id
& TYPE_ID_MASK
) ||
2210 type_id
> G_TYPE_FUNDAMENTAL_MAX
)
2212 g_warning ("attempt to register fundamental type `%s' with invalid type id (%lu)",
2217 if ((finfo
->type_flags
& G_TYPE_FLAG_INSTANTIATABLE
) &&
2218 !(finfo
->type_flags
& G_TYPE_FLAG_CLASSED
))
2220 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
2224 if (lookup_type_node_I (type_id
))
2226 g_warning ("cannot register existing fundamental type `%s' (as `%s')",
2227 type_descriptive_name_I (type_id
),
2232 G_WRITE_LOCK (&type_rw_lock
);
2233 node
= type_node_fundamental_new_W (type_id
, type_name
, finfo
->type_flags
);
2234 node_finfo
= type_node_fundamental_info_I (node
);
2235 type_add_flags_W (node
, flags
);
2237 if (check_type_info_I (NULL
, NODE_FUNDAMENTAL_TYPE (node
), type_name
, info
))
2238 type_data_make_W (node
, info
,
2239 check_value_table_I (type_name
, info
->value_table
) ? info
->value_table
: NULL
);
2240 G_WRITE_UNLOCK (&type_rw_lock
);
2242 return NODE_TYPE (node
);
2246 g_type_register_static (GType parent_type
,
2247 const gchar
*type_name
,
2248 const GTypeInfo
*info
,
2251 TypeNode
*pnode
, *node
;
2254 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
2255 g_return_val_if_fail (parent_type
> 0, 0);
2256 g_return_val_if_fail (type_name
!= NULL
, 0);
2257 g_return_val_if_fail (info
!= NULL
, 0);
2259 if (!check_type_name_I (type_name
) ||
2260 !check_derivation_I (parent_type
, type_name
))
2262 if (info
->class_finalize
)
2264 g_warning ("class finalizer specified for static type `%s'",
2269 pnode
= lookup_type_node_I (parent_type
);
2270 G_WRITE_LOCK (&type_rw_lock
);
2271 type_data_ref_Wm (pnode
);
2272 if (check_type_info_I (pnode
, NODE_FUNDAMENTAL_TYPE (pnode
), type_name
, info
))
2274 node
= type_node_new_W (pnode
, type_name
, NULL
);
2275 type_add_flags_W (node
, flags
);
2276 type
= NODE_TYPE (node
);
2277 type_data_make_W (node
, info
,
2278 check_value_table_I (type_name
, info
->value_table
) ? info
->value_table
: NULL
);
2280 G_WRITE_UNLOCK (&type_rw_lock
);
2286 g_type_register_dynamic (GType parent_type
,
2287 const gchar
*type_name
,
2288 GTypePlugin
*plugin
,
2291 TypeNode
*pnode
, *node
;
2294 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, 0);
2295 g_return_val_if_fail (parent_type
> 0, 0);
2296 g_return_val_if_fail (type_name
!= NULL
, 0);
2297 g_return_val_if_fail (plugin
!= NULL
, 0);
2299 if (!check_type_name_I (type_name
) ||
2300 !check_derivation_I (parent_type
, type_name
) ||
2301 !check_plugin_U (plugin
, TRUE
, FALSE
, type_name
))
2304 G_WRITE_LOCK (&type_rw_lock
);
2305 pnode
= lookup_type_node_I (parent_type
);
2306 node
= type_node_new_W (pnode
, type_name
, plugin
);
2307 type_add_flags_W (node
, flags
);
2308 type
= NODE_TYPE (node
);
2309 G_WRITE_UNLOCK (&type_rw_lock
);
2315 g_type_add_interface_static (GType instance_type
,
2316 GType interface_type
,
2317 const GInterfaceInfo
*info
)
2319 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2320 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type
));
2321 g_return_if_fail (g_type_parent (interface_type
) == G_TYPE_INTERFACE
);
2323 G_WRITE_LOCK (&type_rw_lock
);
2324 if (check_add_interface_L (instance_type
, interface_type
))
2326 TypeNode
*node
= lookup_type_node_I (instance_type
);
2327 TypeNode
*iface
= lookup_type_node_I (interface_type
);
2329 if (check_interface_info_I (iface
, NODE_TYPE (node
), info
))
2330 type_add_interface_Wm (node
, iface
, info
, NULL
);
2332 G_WRITE_UNLOCK (&type_rw_lock
);
2336 g_type_add_interface_dynamic (GType instance_type
,
2337 GType interface_type
,
2338 GTypePlugin
*plugin
)
2342 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2343 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type
));
2344 g_return_if_fail (g_type_parent (interface_type
) == G_TYPE_INTERFACE
);
2346 node
= lookup_type_node_I (instance_type
);
2347 if (!check_plugin_U (plugin
, FALSE
, TRUE
, NODE_NAME (node
)))
2350 G_WRITE_LOCK (&type_rw_lock
);
2351 if (check_add_interface_L (instance_type
, interface_type
))
2353 TypeNode
*iface
= lookup_type_node_I (interface_type
);
2355 type_add_interface_Wm (node
, iface
, NULL
, plugin
);
2357 G_WRITE_UNLOCK (&type_rw_lock
);
2361 /* --- public API functions --- */
2363 g_type_class_ref (GType type
)
2367 /* optimize for common code path
2369 G_WRITE_LOCK (&type_rw_lock
);
2370 node
= lookup_type_node_I (type
);
2371 if (node
&& node
->is_classed
&& node
->data
&&
2372 node
->data
->class.class && node
->data
->common
.ref_count
> 0)
2374 type_data_ref_Wm (node
);
2375 G_WRITE_UNLOCK (&type_rw_lock
);
2377 return node
->data
->class.class;
2380 if (!node
|| !node
->is_classed
||
2381 (node
->data
&& node
->data
->common
.ref_count
< 1))
2383 G_WRITE_UNLOCK (&type_rw_lock
);
2384 g_warning ("cannot retrieve class for invalid (unclassed) type `%s'",
2385 type_descriptive_name_I (type
));
2389 type_data_ref_Wm (node
);
2391 if (!node
->data
->class.class)
2393 GType ptype
= NODE_PARENT_TYPE (node
);
2394 GTypeClass
*pclass
= NULL
;
2398 G_WRITE_UNLOCK (&type_rw_lock
);
2399 pclass
= g_type_class_ref (ptype
);
2400 if (node
->data
->class.class)
2401 INVALID_RECURSION ("g_type_plugin_*", node
->plugin
, NODE_NAME (node
));
2402 G_WRITE_LOCK (&type_rw_lock
);
2405 type_class_init_Wm (node
, pclass
);
2407 G_WRITE_UNLOCK (&type_rw_lock
);
2409 return node
->data
->class.class;
2413 g_type_class_unref (gpointer g_class
)
2416 GTypeClass
*class = g_class
;
2418 g_return_if_fail (g_class
!= NULL
);
2420 node
= lookup_type_node_I (class->g_type
);
2421 G_WRITE_LOCK (&type_rw_lock
);
2422 if (node
&& node
->is_classed
&& node
->data
&&
2423 node
->data
->class.class == class && node
->data
->common
.ref_count
> 0)
2424 type_data_unref_Wm (node
, FALSE
);
2426 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2427 type_descriptive_name_I (class->g_type
));
2428 G_WRITE_UNLOCK (&type_rw_lock
);
2432 g_type_class_unref_uncached (gpointer g_class
)
2435 GTypeClass
*class = g_class
;
2437 g_return_if_fail (g_class
!= NULL
);
2439 G_WRITE_LOCK (&type_rw_lock
);
2440 node
= lookup_type_node_I (class->g_type
);
2441 if (node
&& node
->is_classed
&& node
->data
&&
2442 node
->data
->class.class == class && node
->data
->common
.ref_count
> 0)
2443 type_data_unref_Wm (node
, TRUE
);
2445 g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
2446 type_descriptive_name_I (class->g_type
));
2447 G_WRITE_UNLOCK (&type_rw_lock
);
2451 g_type_class_peek (GType type
)
2456 node
= lookup_type_node_I (type
);
2457 G_READ_LOCK (&type_rw_lock
);
2458 if (node
&& node
->is_classed
&& node
->data
&& node
->data
->class.class) /* common.ref_count _may_ be 0 */
2459 class = node
->data
->class.class;
2462 G_READ_UNLOCK (&type_rw_lock
);
2468 g_type_class_peek_static (GType type
)
2473 node
= lookup_type_node_I (type
);
2474 G_READ_LOCK (&type_rw_lock
);
2475 if (node
&& node
->is_classed
&& node
->data
&&
2476 /* peek only static types: */ node
->plugin
== NULL
&&
2477 node
->data
->class.class) /* common.ref_count _may_ be 0 */
2478 class = node
->data
->class.class;
2481 G_READ_UNLOCK (&type_rw_lock
);
2487 g_type_class_peek_parent (gpointer g_class
)
2490 gpointer
class = NULL
;
2492 g_return_val_if_fail (g_class
!= NULL
, NULL
);
2494 node
= lookup_type_node_I (G_TYPE_FROM_CLASS (g_class
));
2495 /* We used to acquire a read lock here. That is not necessary, since
2496 * parent->data->class.class is constant as long as the derived class
2499 if (node
&& node
->is_classed
&& node
->data
&& NODE_PARENT_TYPE (node
))
2501 node
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
2502 class = node
->data
->class.class;
2504 else if (NODE_PARENT_TYPE (node
))
2505 g_warning (G_STRLOC
": invalid class pointer `%p'", g_class
);
2511 g_type_interface_peek (gpointer instance_class
,
2516 gpointer vtable
= NULL
;
2517 GTypeClass
*class = instance_class
;
2519 g_return_val_if_fail (instance_class
!= NULL
, NULL
);
2521 node
= lookup_type_node_I (class->g_type
);
2522 iface
= lookup_type_node_I (iface_type
);
2523 if (node
&& node
->is_instantiatable
&& iface
)
2527 G_READ_LOCK (&type_rw_lock
);
2529 entry
= type_lookup_iface_entry_L (node
, iface
);
2530 if (entry
&& entry
->vtable
) /* entry is relocatable */
2531 vtable
= entry
->vtable
;
2533 G_READ_UNLOCK (&type_rw_lock
);
2536 g_warning (G_STRLOC
": invalid class pointer `%p'", class);
2542 g_type_interface_peek_parent (gpointer g_iface
)
2546 gpointer vtable
= NULL
;
2547 GTypeInterface
*iface_class
= g_iface
;
2549 g_return_val_if_fail (g_iface
!= NULL
, NULL
);
2551 iface
= lookup_type_node_I (iface_class
->g_type
);
2552 node
= lookup_type_node_I (iface_class
->g_instance_type
);
2554 node
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
2555 if (node
&& node
->is_instantiatable
&& iface
)
2559 G_READ_LOCK (&type_rw_lock
);
2561 entry
= type_lookup_iface_entry_L (node
, iface
);
2562 if (entry
&& entry
->vtable
) /* entry is relocatable */
2563 vtable
= entry
->vtable
;
2565 G_READ_UNLOCK (&type_rw_lock
);
2568 g_warning (G_STRLOC
": invalid interface pointer `%p'", g_iface
);
2574 g_type_default_interface_ref (GType g_type
)
2578 G_WRITE_LOCK (&type_rw_lock
);
2580 node
= lookup_type_node_I (g_type
);
2581 if (!node
|| !NODE_IS_IFACE (node
) ||
2582 (node
->data
&& node
->data
->common
.ref_count
< 1))
2584 G_WRITE_UNLOCK (&type_rw_lock
);
2585 g_warning ("cannot retrieve default vtable for invalid or non-interface type '%s'",
2586 type_descriptive_name_I (g_type
));
2590 type_data_ref_Wm (node
);
2592 type_iface_ensure_dflt_vtable_Wm (node
);
2594 G_WRITE_UNLOCK (&type_rw_lock
);
2596 return node
->data
->iface
.dflt_vtable
;
2600 g_type_default_interface_peek (GType g_type
)
2605 node
= lookup_type_node_I (g_type
);
2606 G_READ_LOCK (&type_rw_lock
);
2607 if (node
&& NODE_IS_IFACE (node
) && node
->data
&& node
->data
->iface
.dflt_vtable
)
2608 vtable
= node
->data
->iface
.dflt_vtable
;
2611 G_READ_UNLOCK (&type_rw_lock
);
2617 g_type_default_interface_unref (gpointer g_iface
)
2620 GTypeInterface
*vtable
= g_iface
;
2622 g_return_if_fail (g_iface
!= NULL
);
2624 node
= lookup_type_node_I (vtable
->g_type
);
2625 G_WRITE_LOCK (&type_rw_lock
);
2626 if (node
&& NODE_IS_IFACE (node
) &&
2627 node
->data
->iface
.dflt_vtable
== g_iface
&&
2628 node
->data
->common
.ref_count
> 0)
2629 type_data_unref_Wm (node
, FALSE
);
2631 g_warning ("cannot unreference invalid interface default vtable for '%s'",
2632 type_descriptive_name_I (vtable
->g_type
));
2633 G_WRITE_UNLOCK (&type_rw_lock
);
2636 G_CONST_RETURN gchar
*
2637 g_type_name (GType type
)
2641 g_return_val_if_uninitialized (static_quark_type_flags
, g_type_init
, NULL
);
2643 node
= lookup_type_node_I (type
);
2645 return node
? NODE_NAME (node
) : NULL
;
2649 g_type_qname (GType type
)
2653 node
= lookup_type_node_I (type
);
2655 return node
? node
->qname
: 0;
2659 g_type_from_name (const gchar
*name
)
2664 g_return_val_if_fail (name
!= NULL
, 0);
2666 quark
= g_quark_try_string (name
);
2669 G_READ_LOCK (&type_rw_lock
);
2670 type
= (GType
) g_hash_table_lookup (static_type_nodes_ht
, GUINT_TO_POINTER (quark
));
2671 G_READ_UNLOCK (&type_rw_lock
);
2678 g_type_parent (GType type
)
2682 node
= lookup_type_node_I (type
);
2684 return node
? NODE_PARENT_TYPE (node
) : 0;
2688 g_type_depth (GType type
)
2692 node
= lookup_type_node_I (type
);
2694 return node
? node
->n_supers
+ 1 : 0;
2698 g_type_next_base (GType type
,
2704 node
= lookup_type_node_I (type
);
2707 TypeNode
*base_node
= lookup_type_node_I (base_type
);
2709 if (base_node
&& base_node
->n_supers
< node
->n_supers
)
2711 guint n
= node
->n_supers
- base_node
->n_supers
;
2713 if (node
->supers
[n
] == base_type
)
2714 atype
= node
->supers
[n
- 1];
2721 static inline gboolean
2722 type_node_check_conformities_UorL (TypeNode
*node
,
2723 TypeNode
*iface_node
,
2724 /* support_inheritance */
2725 gboolean support_interfaces
,
2726 gboolean support_prerequisites
,
2731 if (/* support_inheritance && */
2732 NODE_IS_ANCESTOR (iface_node
, node
))
2735 support_interfaces
= support_interfaces
&& node
->is_instantiatable
&& NODE_IS_IFACE (iface_node
);
2736 support_prerequisites
= support_prerequisites
&& NODE_IS_IFACE (node
);
2738 if (support_interfaces
|| support_prerequisites
)
2741 G_READ_LOCK (&type_rw_lock
);
2742 if (support_interfaces
&& type_lookup_iface_entry_L (node
, iface_node
))
2744 else if (support_prerequisites
&& type_lookup_prerequisite_L (node
, NODE_TYPE (iface_node
)))
2747 G_READ_UNLOCK (&type_rw_lock
);
2753 type_node_is_a_L (TypeNode
*node
,
2754 TypeNode
*iface_node
)
2756 return type_node_check_conformities_UorL (node
, iface_node
, TRUE
, TRUE
, TRUE
);
2759 static inline gboolean
2760 type_node_conforms_to_U (TypeNode
*node
,
2761 TypeNode
*iface_node
,
2762 gboolean support_interfaces
,
2763 gboolean support_prerequisites
)
2765 return type_node_check_conformities_UorL (node
, iface_node
, support_interfaces
, support_prerequisites
, FALSE
);
2769 g_type_is_a (GType type
,
2772 TypeNode
*node
, *iface_node
;
2775 node
= lookup_type_node_I (type
);
2776 iface_node
= lookup_type_node_I (iface_type
);
2777 is_a
= node
&& iface_node
&& type_node_conforms_to_U (node
, iface_node
, TRUE
, TRUE
);
2782 GType
* /* free result */
2783 g_type_children (GType type
,
2788 node
= lookup_type_node_I (type
);
2793 G_READ_LOCK (&type_rw_lock
); /* ->children is relocatable */
2794 children
= g_new (GType
, node
->n_children
+ 1);
2795 memcpy (children
, node
->children
, sizeof (GType
) * node
->n_children
);
2796 children
[node
->n_children
] = 0;
2799 *n_children
= node
->n_children
;
2800 G_READ_UNLOCK (&type_rw_lock
);
2813 GType
* /* free result */
2814 g_type_interfaces (GType type
,
2815 guint
*n_interfaces
)
2819 node
= lookup_type_node_I (type
);
2820 if (node
&& node
->is_instantiatable
)
2825 G_READ_LOCK (&type_rw_lock
);
2826 ifaces
= g_new (GType
, CLASSED_NODE_N_IFACES (node
) + 1);
2827 for (i
= 0; i
< CLASSED_NODE_N_IFACES (node
); i
++)
2828 ifaces
[i
] = CLASSED_NODE_IFACES_ENTRIES (node
)[i
].iface_type
;
2832 *n_interfaces
= CLASSED_NODE_N_IFACES (node
);
2833 G_READ_UNLOCK (&type_rw_lock
);
2846 typedef struct _QData QData
;
2858 static inline gpointer
2859 type_get_qdata_L (TypeNode
*node
,
2862 GData
*gdata
= node
->global_gdata
;
2864 if (quark
&& gdata
&& gdata
->n_qdatas
)
2866 QData
*qdatas
= gdata
->qdatas
- 1;
2867 guint n_qdatas
= gdata
->n_qdatas
;
2874 i
= (n_qdatas
+ 1) / 2;
2876 if (quark
== check
->quark
)
2878 else if (quark
> check
->quark
)
2883 else /* if (quark < check->quark) */
2892 g_type_get_qdata (GType type
,
2898 node
= lookup_type_node_I (type
);
2901 G_READ_LOCK (&type_rw_lock
);
2902 data
= type_get_qdata_L (node
, quark
);
2903 G_READ_UNLOCK (&type_rw_lock
);
2907 g_return_val_if_fail (node
!= NULL
, NULL
);
2914 type_set_qdata_W (TypeNode
*node
,
2922 /* setup qdata list if necessary */
2923 if (!node
->global_gdata
)
2924 node
->global_gdata
= g_new0 (GData
, 1);
2925 gdata
= node
->global_gdata
;
2927 /* try resetting old data */
2928 qdata
= gdata
->qdatas
;
2929 for (i
= 0; i
< gdata
->n_qdatas
; i
++)
2930 if (qdata
[i
].quark
== quark
)
2932 qdata
[i
].data
= data
;
2938 gdata
->qdatas
= g_renew (QData
, gdata
->qdatas
, gdata
->n_qdatas
);
2939 qdata
= gdata
->qdatas
;
2940 for (i
= 0; i
< gdata
->n_qdatas
- 1; i
++)
2941 if (qdata
[i
].quark
> quark
)
2943 g_memmove (qdata
+ i
+ 1, qdata
+ i
, sizeof (qdata
[0]) * (gdata
->n_qdatas
- i
- 1));
2944 qdata
[i
].quark
= quark
;
2945 qdata
[i
].data
= data
;
2949 g_type_set_qdata (GType type
,
2955 g_return_if_fail (quark
!= 0);
2957 node
= lookup_type_node_I (type
);
2960 G_WRITE_LOCK (&type_rw_lock
);
2961 type_set_qdata_W (node
, quark
, data
);
2962 G_WRITE_UNLOCK (&type_rw_lock
);
2965 g_return_if_fail (node
!= NULL
);
2969 type_add_flags_W (TypeNode
*node
,
2974 g_return_if_fail ((flags
& ~TYPE_FLAG_MASK
) == 0);
2975 g_return_if_fail (node
!= NULL
);
2977 if ((flags
& TYPE_FLAG_MASK
) && node
->is_classed
&& node
->data
&& node
->data
->class.class)
2978 g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node
));
2979 dflags
= GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
));
2981 type_set_qdata_W (node
, static_quark_type_flags
, GUINT_TO_POINTER (dflags
));
2985 g_type_query (GType type
,
2990 g_return_if_fail (query
!= NULL
);
2992 /* if node is not static and classed, we won't allow query */
2994 node
= lookup_type_node_I (type
);
2995 if (node
&& node
->is_classed
&& !node
->plugin
)
2997 /* type is classed and probably even instantiatable */
2998 G_READ_LOCK (&type_rw_lock
);
2999 if (node
->data
) /* type is static or referenced */
3001 query
->type
= NODE_TYPE (node
);
3002 query
->type_name
= NODE_NAME (node
);
3003 query
->class_size
= node
->data
->class.class_size
;
3004 query
->instance_size
= node
->is_instantiatable
? node
->data
->instance
.instance_size
: 0;
3006 G_READ_UNLOCK (&type_rw_lock
);
3011 /* --- implementation details --- */
3013 g_type_test_flags (GType type
,
3017 gboolean result
= FALSE
;
3019 node
= lookup_type_node_I (type
);
3022 guint fflags
= flags
& TYPE_FUNDAMENTAL_FLAG_MASK
;
3023 guint tflags
= flags
& TYPE_FLAG_MASK
;
3027 GTypeFundamentalInfo
*finfo
= type_node_fundamental_info_I (node
);
3029 fflags
= (finfo
->type_flags
& fflags
) == fflags
;
3036 G_READ_LOCK (&type_rw_lock
);
3037 tflags
= (tflags
& GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
))) == tflags
;
3038 G_READ_UNLOCK (&type_rw_lock
);
3043 result
= tflags
&& fflags
;
3050 g_type_get_plugin (GType type
)
3054 node
= lookup_type_node_I (type
);
3056 return node
? node
->plugin
: NULL
;
3060 g_type_interface_get_plugin (GType instance_type
,
3061 GType interface_type
)
3066 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type
), NULL
); /* G_TYPE_IS_INTERFACE() is an external call: _U */
3068 node
= lookup_type_node_I (instance_type
);
3069 iface
= lookup_type_node_I (interface_type
);
3072 IFaceHolder
*iholder
;
3073 GTypePlugin
*plugin
;
3075 G_READ_LOCK (&type_rw_lock
);
3077 iholder
= iface_node_get_holders_L (iface
);
3078 while (iholder
&& iholder
->instance_type
!= instance_type
)
3079 iholder
= iholder
->next
;
3080 plugin
= iholder
? iholder
->plugin
: NULL
;
3082 G_READ_UNLOCK (&type_rw_lock
);
3087 g_return_val_if_fail (node
== NULL
, NULL
);
3088 g_return_val_if_fail (iface
== NULL
, NULL
);
3090 g_warning (G_STRLOC
": attempt to look up plugin for invalid instance/interface type pair.");
3096 g_type_fundamental_next (void)
3100 G_READ_LOCK (&type_rw_lock
);
3101 type
= static_fundamental_next
;
3102 G_READ_UNLOCK (&type_rw_lock
);
3103 type
= G_TYPE_MAKE_FUNDAMENTAL (type
);
3104 return type
<= G_TYPE_FUNDAMENTAL_MAX
? type
: 0;
3108 g_type_fundamental (GType type_id
)
3110 TypeNode
*node
= lookup_type_node_I (type_id
);
3112 return node
? NODE_FUNDAMENTAL_TYPE (node
) : 0;
3116 g_type_check_instance_is_a (GTypeInstance
*type_instance
,
3119 TypeNode
*node
, *iface
;
3122 if (!type_instance
|| !type_instance
->g_class
)
3125 node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
3126 iface
= lookup_type_node_I (iface_type
);
3127 check
= node
&& node
->is_instantiatable
&& iface
&& type_node_conforms_to_U (node
, iface
, TRUE
, FALSE
);
3133 g_type_check_class_is_a (GTypeClass
*type_class
,
3136 TypeNode
*node
, *iface
;
3142 node
= lookup_type_node_I (type_class
->g_type
);
3143 iface
= lookup_type_node_I (is_a_type
);
3144 check
= node
&& node
->is_classed
&& iface
&& type_node_conforms_to_U (node
, iface
, FALSE
, FALSE
);
3150 g_type_check_instance_cast (GTypeInstance
*type_instance
,
3155 if (type_instance
->g_class
)
3157 TypeNode
*node
, *iface
;
3158 gboolean is_instantiatable
, check
;
3160 node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
3161 is_instantiatable
= node
&& node
->is_instantiatable
;
3162 iface
= lookup_type_node_I (iface_type
);
3163 check
= is_instantiatable
&& iface
&& type_node_conforms_to_U (node
, iface
, TRUE
, FALSE
);
3165 return type_instance
;
3167 if (is_instantiatable
)
3168 g_warning ("invalid cast from `%s' to `%s'",
3169 type_descriptive_name_I (type_instance
->g_class
->g_type
),
3170 type_descriptive_name_I (iface_type
));
3172 g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
3173 type_descriptive_name_I (type_instance
->g_class
->g_type
),
3174 type_descriptive_name_I (iface_type
));
3177 g_warning ("invalid unclassed pointer in cast to `%s'",
3178 type_descriptive_name_I (iface_type
));
3181 return type_instance
;
3185 g_type_check_class_cast (GTypeClass
*type_class
,
3190 TypeNode
*node
, *iface
;
3191 gboolean is_classed
, check
;
3193 node
= lookup_type_node_I (type_class
->g_type
);
3194 is_classed
= node
&& node
->is_classed
;
3195 iface
= lookup_type_node_I (is_a_type
);
3196 check
= is_classed
&& iface
&& type_node_conforms_to_U (node
, iface
, FALSE
, FALSE
);
3201 g_warning ("invalid class cast from `%s' to `%s'",
3202 type_descriptive_name_I (type_class
->g_type
),
3203 type_descriptive_name_I (is_a_type
));
3205 g_warning ("invalid unclassed type `%s' in class cast to `%s'",
3206 type_descriptive_name_I (type_class
->g_type
),
3207 type_descriptive_name_I (is_a_type
));
3210 g_warning ("invalid class cast from (NULL) pointer to `%s'",
3211 type_descriptive_name_I (is_a_type
));
3216 g_type_check_instance (GTypeInstance
*type_instance
)
3218 /* this function is just here to make the signal system
3219 * conveniently elaborated on instance checks
3223 if (type_instance
->g_class
)
3225 TypeNode
*node
= lookup_type_node_I (type_instance
->g_class
->g_type
);
3227 if (node
&& node
->is_instantiatable
)
3230 g_warning ("instance of invalid non-instantiatable type `%s'",
3231 type_descriptive_name_I (type_instance
->g_class
->g_type
));
3234 g_warning ("instance with invalid (NULL) class pointer");
3237 g_warning ("invalid (NULL) pointer instance");
3242 static inline gboolean
3243 type_check_is_value_type_U (GType type
)
3245 GTypeFlags tflags
= G_TYPE_FLAG_VALUE_ABSTRACT
;
3248 /* common path speed up */
3249 node
= lookup_type_node_I (type
);
3250 if (node
&& node
->mutatable_check_cache
)
3253 G_READ_LOCK (&type_rw_lock
);
3257 if (node
->data
&& node
->data
->common
.ref_count
> 0 &&
3258 node
->data
->common
.value_table
->value_init
)
3259 tflags
= GPOINTER_TO_UINT (type_get_qdata_L (node
, static_quark_type_flags
));
3260 else if (NODE_IS_IFACE (node
))
3264 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (node
); i
++)
3266 GType prtype
= IFACE_NODE_PREREQUISITES (node
)[i
];
3267 TypeNode
*prnode
= lookup_type_node_I (prtype
);
3269 if (prnode
->is_instantiatable
)
3272 node
= lookup_type_node_I (type
);
3278 G_READ_UNLOCK (&type_rw_lock
);
3280 return !(tflags
& G_TYPE_FLAG_VALUE_ABSTRACT
);
3284 g_type_check_is_value_type (GType type
)
3286 return type_check_is_value_type_U (type
);
3290 g_type_check_value (GValue
*value
)
3292 return value
&& type_check_is_value_type_U (value
->g_type
);
3296 g_type_check_value_holds (GValue
*value
,
3299 return value
&& type_check_is_value_type_U (value
->g_type
) && g_type_is_a (value
->g_type
, type
);
3303 g_type_value_table_peek (GType type
)
3305 GTypeValueTable
*vtable
= NULL
;
3306 TypeNode
*node
= lookup_type_node_I (type
);
3307 gboolean has_refed_data
, has_table
;
3310 /* speed up common code path, we're not 100% safe here,
3311 * but we should only get called with referenced types anyway
3313 data
= node
? node
->data
: NULL
;
3314 if (node
&& node
->mutatable_check_cache
)
3315 return data
->common
.value_table
;
3317 G_READ_LOCK (&type_rw_lock
);
3320 has_refed_data
= node
&& node
->data
&& node
->data
->common
.ref_count
;
3321 has_table
= has_refed_data
&& node
->data
->common
.value_table
->value_init
;
3325 vtable
= node
->data
->common
.value_table
;
3326 else if (NODE_IS_IFACE (node
))
3330 for (i
= 0; i
< IFACE_NODE_N_PREREQUISITES (node
); i
++)
3332 GType prtype
= IFACE_NODE_PREREQUISITES (node
)[i
];
3333 TypeNode
*prnode
= lookup_type_node_I (prtype
);
3335 if (prnode
->is_instantiatable
)
3338 node
= lookup_type_node_I (type
);
3339 goto restart_table_peek
;
3345 G_READ_UNLOCK (&type_rw_lock
);
3351 g_warning (G_STRLOC
": type id `%lu' is invalid", type
);
3352 if (!has_refed_data
)
3353 g_warning ("can't peek value table for type `%s' which is not currently referenced",
3354 type_descriptive_name_I (type
));
3359 G_CONST_RETURN gchar
*
3360 g_type_name_from_instance (GTypeInstance
*instance
)
3363 return "<NULL-instance>";
3365 return g_type_name_from_class (instance
->g_class
);
3368 G_CONST_RETURN gchar
*
3369 g_type_name_from_class (GTypeClass
*g_class
)
3372 return "<NULL-class>";
3374 return g_type_name (g_class
->g_type
);
3378 /* --- initialization --- */
3380 g_type_init_with_debug_flags (GTypeDebugFlags debug_flags
)
3382 G_LOCK_DEFINE_STATIC (type_init_lock
);
3383 const gchar
*env_string
;
3388 G_LOCK (type_init_lock
);
3390 G_WRITE_LOCK (&type_rw_lock
);
3392 if (static_quark_type_flags
)
3394 G_WRITE_UNLOCK (&type_rw_lock
);
3395 G_UNLOCK (type_init_lock
);
3399 /* setup GObject library wide debugging flags */
3400 _g_type_debug_flags
= debug_flags
& G_TYPE_DEBUG_MASK
;
3401 env_string
= g_getenv ("GOBJECT_DEBUG");
3402 if (env_string
!= NULL
)
3404 static GDebugKey debug_keys
[] = {
3405 { "objects", G_TYPE_DEBUG_OBJECTS
},
3406 { "signals", G_TYPE_DEBUG_SIGNALS
},
3409 _g_type_debug_flags
|= g_parse_debug_string (env_string
,
3411 sizeof (debug_keys
) / sizeof (debug_keys
[0]));
3416 static_quark_type_flags
= g_quark_from_static_string ("-g-type-private--GTypeFlags");
3417 static_quark_iface_holder
= g_quark_from_static_string ("-g-type-private--IFaceHolder");
3418 static_quark_dependants_array
= g_quark_from_static_string ("-g-type-private--dependants-array");
3420 /* type qname hash table */
3421 static_type_nodes_ht
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
3423 /* invalid type G_TYPE_INVALID (0)
3425 static_fundamental_type_nodes
[0] = NULL
;
3427 /* void type G_TYPE_NONE
3429 node
= type_node_fundamental_new_W (G_TYPE_NONE
, "void", 0);
3430 type
= NODE_TYPE (node
);
3431 g_assert (type
== G_TYPE_NONE
);
3433 /* interface fundamental type G_TYPE_INTERFACE (!classed)
3435 memset (&info
, 0, sizeof (info
));
3436 node
= type_node_fundamental_new_W (G_TYPE_INTERFACE
, "GInterface", G_TYPE_FLAG_DERIVABLE
);
3437 type
= NODE_TYPE (node
);
3438 type_data_make_W (node
, &info
, NULL
);
3439 g_assert (type
== G_TYPE_INTERFACE
);
3441 G_WRITE_UNLOCK (&type_rw_lock
);
3445 /* G_TYPE_TYPE_PLUGIN
3447 g_type_plugin_get_type ();
3449 /* G_TYPE_* value types
3451 g_value_types_init ();
3453 /* G_TYPE_ENUM & G_TYPE_FLAGS
3455 g_enum_types_init ();
3459 g_boxed_type_init ();
3463 g_param_type_init ();
3467 g_object_type_init ();
3469 /* G_TYPE_PARAM_* pspec types
3471 g_param_spec_types_init ();
3473 /* Value Transformations
3475 g_value_transforms_init ();
3481 G_UNLOCK (type_init_lock
);
3487 g_type_init_with_debug_flags (0);
3491 g_type_class_add_private (gpointer g_class
,
3494 GType instance_type
= ((GTypeClass
*)g_class
)->g_type
;
3495 TypeNode
*node
= lookup_type_node_I (instance_type
);
3498 if (!node
|| !node
->is_instantiatable
|| !node
->data
|| node
->data
->class.class != g_class
)
3500 g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'",
3501 type_descriptive_name_I (instance_type
));
3505 if (NODE_PARENT_TYPE (node
))
3507 TypeNode
*pnode
= lookup_type_node_I (NODE_PARENT_TYPE (node
));
3508 if (node
->data
->instance
.private_size
!= pnode
->data
->instance
.private_size
)
3510 g_warning ("g_type_add_private() called multiple times for the same type");
3515 G_WRITE_LOCK (&type_rw_lock
);
3517 offset
= ALIGN_STRUCT (node
->data
->instance
.private_size
);
3518 node
->data
->instance
.private_size
= offset
+ private_size
;
3520 G_WRITE_UNLOCK (&type_rw_lock
);
3524 g_type_instance_get_private (GTypeInstance
*instance
,
3527 TypeNode
*instance_node
;
3528 TypeNode
*private_node
;
3529 TypeNode
*parent_node
;
3533 g_return_val_if_fail (instance
!= NULL
&& instance
->g_class
!= NULL
, NULL
);
3535 /* while instances are initialized, their class pointers change,
3536 * so figure the instances real class first
3538 class = instance_real_class_get (instance
);
3540 class = instance
->g_class
;
3542 instance_node
= lookup_type_node_I (class->g_type
);
3543 if (G_UNLIKELY (!instance_node
|| !instance_node
->is_instantiatable
))
3545 g_warning ("instance of invalid non-instantiatable type `%s'",
3546 type_descriptive_name_I (instance
->g_class
->g_type
));
3550 private_node
= lookup_type_node_I (private_type
);
3551 if (G_UNLIKELY (!private_node
|| !NODE_IS_ANCESTOR (private_node
, instance_node
)))
3553 g_warning ("attempt to retrieve private data for invalid type '%s'",
3554 type_descriptive_name_I (private_type
));
3558 /* Note that we don't need a read lock, since instance existing
3559 * means that the instance class and all parent classes
3560 * exist, so the node->data, node->data->instance.instance_size,
3561 * and node->data->instance.private_size are not going to be changed.
3562 * for any of the relevant types.
3565 offset
= ALIGN_STRUCT (instance_node
->data
->instance
.instance_size
);
3567 if (NODE_PARENT_TYPE (private_node
))
3569 parent_node
= lookup_type_node_I (NODE_PARENT_TYPE (private_node
));
3570 g_assert (parent_node
->data
&& parent_node
->data
->common
.ref_count
);
3572 if (G_UNLIKELY (private_node
->data
->instance
.private_size
== parent_node
->data
->instance
.private_size
))
3574 g_warning ("g_type_get_private() requires a prior call to g_type_add_private()");
3578 offset
+= ALIGN_STRUCT (parent_node
->data
->instance
.private_size
);
3581 return G_STRUCT_MEMBER_P (instance
, offset
);