Branch data Line data Source code
1 : : /* GObject - GLib Type, Object, Parameter and Signal Library
2 : : * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc.
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General
17 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : */
19 : :
20 : : /*
21 : : * MT safe
22 : : */
23 : :
24 : : #include "config.h"
25 : :
26 : : #include "../glib/gvalgrind.h"
27 : : #include <string.h>
28 : :
29 : : #include "gtype.h"
30 : : #include "gtype-private.h"
31 : : #include "gtypeplugin.h"
32 : : #include "gvaluecollector.h"
33 : : #include "gatomicarray.h"
34 : : #include "gobject_trace.h"
35 : :
36 : : #include "glib-private.h"
37 : : #include "gconstructor.h"
38 : :
39 : : #ifdef G_OS_WIN32
40 : : #include <windows.h>
41 : : #endif
42 : :
43 : : #ifdef G_ENABLE_DEBUG
44 : : #define IF_DEBUG(debug_type) if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
45 : : #endif
46 : :
47 : :
48 : : /* NOTE: some functions (some internal variants and exported ones)
49 : : * invalidate data portions of the TypeNodes. if external functions/callbacks
50 : : * are called, pointers to memory maintained by TypeNodes have to be looked up
51 : : * again. this affects most of the struct TypeNode fields, e.g. ->children or
52 : : * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
53 : : * not ->supers[]), as all those memory portions can get realloc()ed during
54 : : * callback invocation.
55 : : *
56 : : * LOCKING:
57 : : * lock handling issues when calling static functions are indicated by
58 : : * uppercase letter postfixes, all static functions have to have
59 : : * one of the below postfixes:
60 : : * - _I: [Indifferent about locking]
61 : : * function doesn't care about locks at all
62 : : * - _U: [Unlocked invocation]
63 : : * no read or write lock has to be held across function invocation
64 : : * (locks may be acquired and released during invocation though)
65 : : * - _L: [Locked invocation]
66 : : * a write lock or more than 0 read locks have to be held across
67 : : * function invocation
68 : : * - _W: [Write-locked invocation]
69 : : * a write lock has to be held across function invocation
70 : : * - _Wm: [Write-locked invocation, mutatable]
71 : : * like _W, but the write lock might be released and reacquired
72 : : * during invocation, watch your pointers
73 : : * - _WmREC: [Write-locked invocation, mutatable, recursive]
74 : : * like _Wm, but also acquires recursive mutex class_init_rec_mutex
75 : : */
76 : :
77 : : #ifdef LOCK_DEBUG
78 : : #define G_READ_LOCK(rw_lock) do { g_printerr (G_STRLOC ": readL++\n"); g_rw_lock_reader_lock (rw_lock); } while (0)
79 : : #define G_READ_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": readL--\n"); g_rw_lock_reader_unlock (rw_lock); } while (0)
80 : : #define G_WRITE_LOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL++\n"); g_rw_lock_writer_lock (rw_lock); } while (0)
81 : : #define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_rw_lock_writer_unlock (rw_lock); } while (0)
82 : : #else
83 : : #define G_READ_LOCK(rw_lock) g_rw_lock_reader_lock (rw_lock)
84 : : #define G_READ_UNLOCK(rw_lock) g_rw_lock_reader_unlock (rw_lock)
85 : : #define G_WRITE_LOCK(rw_lock) g_rw_lock_writer_lock (rw_lock)
86 : : #define G_WRITE_UNLOCK(rw_lock) g_rw_lock_writer_unlock (rw_lock)
87 : : #endif
88 : : #define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
89 : : static const gchar _action[] = " invalidly modified type "; \
90 : : gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
91 : : if (_arg) \
92 : : g_error ("%s(%p)%s'%s'", _fname, _arg, _action, _tname); \
93 : : else \
94 : : g_error ("%s()%s'%s'", _fname, _action, _tname); \
95 : : }G_STMT_END
96 : : #define g_assert_type_system_initialized() \
97 : : g_assert (static_quark_type_flags)
98 : :
99 : : /* Make sure G_TYPE_IS_*() macros still end up inlined */
100 : : #define g_type_test_flags(t,f) _g_type_test_flags(t,f)
101 : :
102 : : #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
103 : : G_TYPE_FLAG_INSTANTIATABLE | \
104 : : G_TYPE_FLAG_DERIVABLE | \
105 : : G_TYPE_FLAG_DEEP_DERIVABLE)
106 : : #define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_FINAL | G_TYPE_FLAG_DEPRECATED)
107 : :
108 : : /* List the flags that are directly accessible via the TypeNode struct flags */
109 : : #define NODE_FLAG_MASK ( \
110 : : G_TYPE_FLAG_ABSTRACT | \
111 : : G_TYPE_FLAG_CLASSED | \
112 : : G_TYPE_FLAG_DEPRECATED | \
113 : : G_TYPE_FLAG_INSTANTIATABLE | \
114 : : G_TYPE_FLAG_FINAL)
115 : :
116 : : #define SIZEOF_FUNDAMENTAL_INFO ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
117 : : sizeof (gpointer)), \
118 : : sizeof (glong)))
119 : :
120 : : /* The 2*sizeof(size_t) alignment here is borrowed from
121 : : * GNU libc, so it should be good most everywhere.
122 : : * It is more conservative than is needed on some 64-bit
123 : : * platforms, but ia64 does require a 16-byte alignment.
124 : : * The SIMD extensions for x86 and ppc32 would want a
125 : : * larger alignment than this, but we don't need to
126 : : * do better than malloc.
127 : : */
128 : : #define STRUCT_ALIGNMENT (2u * sizeof (gsize))
129 : : #define ALIGN_STRUCT(offset) \
130 : : (((size_t) (offset) + (STRUCT_ALIGNMENT - 1u)) & -STRUCT_ALIGNMENT)
131 : :
132 : :
133 : : /* --- typedefs --- */
134 : : typedef struct _TypeNode TypeNode;
135 : : typedef struct _CommonData CommonData;
136 : : typedef struct _BoxedData BoxedData;
137 : : typedef struct _IFaceData IFaceData;
138 : : typedef struct _ClassData ClassData;
139 : : typedef struct _InstanceData InstanceData;
140 : : typedef union _TypeData TypeData;
141 : : typedef struct _IFaceEntries IFaceEntries;
142 : : typedef struct _IFaceEntry IFaceEntry;
143 : : typedef struct _IFaceHolder IFaceHolder;
144 : :
145 : :
146 : : /* --- prototypes --- */
147 : : static inline gboolean _g_type_test_flags (GType type,
148 : : guint flags);
149 : : static inline GTypeFundamentalInfo* type_node_fundamental_info_I (TypeNode *node);
150 : : static void type_add_flags_W (TypeNode *node,
151 : : GTypeFlags flags);
152 : : static void type_data_make_W (TypeNode *node,
153 : : const GTypeInfo *info,
154 : : const GTypeValueTable *value_table);
155 : : static inline void type_data_ref_Wm (TypeNode *node);
156 : : static inline gpointer type_get_qdata_L (TypeNode *node,
157 : : GQuark quark);
158 : : static inline void type_set_qdata_W (TypeNode *node,
159 : : GQuark quark,
160 : : gpointer data);
161 : : static IFaceHolder* type_iface_peek_holder_L (TypeNode *iface,
162 : : GType instance_type);
163 : : static gboolean type_iface_vtable_base_init_Wm (TypeNode *iface,
164 : : TypeNode *node);
165 : : static void type_iface_vtable_iface_init_Wm (TypeNode *iface,
166 : : TypeNode *node);
167 : : static gboolean type_node_is_a_L (TypeNode *node,
168 : : TypeNode *iface_node);
169 : :
170 : :
171 : : /* --- enumeration --- */
172 : :
173 : : /* The InitState enumeration is used to track the progress of initializing
174 : : * both classes and interface vtables. Keeping the state of initialization
175 : : * is necessary to handle new interfaces being added while we are initializing
176 : : * the class or other interfaces.
177 : : */
178 : : typedef enum
179 : : {
180 : : UNINITIALIZED,
181 : : BASE_CLASS_INIT,
182 : : BASE_IFACE_INIT,
183 : : CLASS_INIT,
184 : : IFACE_INIT,
185 : : INITIALIZED
186 : : } InitState;
187 : :
188 : : /* --- structures --- */
189 : : struct _TypeNode
190 : : {
191 : : #ifdef G_ENABLE_DEBUG
192 : : guint instance_count; /* (atomic) */
193 : : #endif
194 : : GTypePlugin *plugin;
195 : : guint n_children; /* writable with lock */
196 : : guint n_supers : 8;
197 : : guint n_prerequisites : 9;
198 : : guint is_abstract : 1;
199 : : guint is_classed : 1;
200 : : guint is_deprecated : 1;
201 : : guint is_instantiatable : 1;
202 : : guint is_final : 1;
203 : : guint mutatable_check_cache : 1; /* combines some common path checks */
204 : :
205 : : GType *children; /* writable with lock */
206 : : TypeData *data;
207 : : GQuark qname;
208 : : GData *global_gdata;
209 : : union {
210 : : GAtomicArray iface_entries; /* for !iface types */
211 : : GAtomicArray offsets;
212 : : } _prot;
213 : : GType *prerequisites;
214 : : GType supers[1]; /* flexible array */
215 : : };
216 : :
217 : : #define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers))
218 : : #define MAX_N_SUPERS (255)
219 : : #define MAX_N_CHILDREN (G_MAXUINT)
220 : : #define MAX_N_INTERFACES (255) /* Limited by offsets being 8 bits */
221 : : #define MAX_N_PREREQUISITES (511)
222 : : #define NODE_TYPE(node) (node->supers[0])
223 : : #define NODE_PARENT_TYPE(node) (node->supers[1])
224 : : #define NODE_FUNDAMENTAL_TYPE(node) (node->supers[node->n_supers])
225 : : #define NODE_NAME(node) (g_quark_to_string (node->qname))
226 : : #define NODE_IS_BOXED(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_BOXED)
227 : : #define NODE_IS_IFACE(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
228 : : #define CLASSED_NODE_IFACES_ENTRIES(node) (&(node)->_prot.iface_entries)
229 : : #define CLASSED_NODE_IFACES_ENTRIES_LOCKED(node)(G_ATOMIC_ARRAY_GET_LOCKED(CLASSED_NODE_IFACES_ENTRIES((node)), IFaceEntries))
230 : : #define IFACE_NODE_N_PREREQUISITES(node) ((node)->n_prerequisites)
231 : : #define IFACE_NODE_PREREQUISITES(node) ((node)->prerequisites)
232 : : #define iface_node_get_holders_L(node) ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
233 : : #define iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
234 : : #define iface_node_get_dependants_array_L(n) ((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
235 : : #define iface_node_set_dependants_array_W(n,d) (type_set_qdata_W ((n), static_quark_dependants_array, (d)))
236 : : #define TYPE_ID_MASK ((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1))
237 : :
238 : : #define NODE_IS_ANCESTOR(ancestor, node) \
239 : : ((ancestor)->n_supers <= (node)->n_supers && \
240 : : (node)->supers[(node)->n_supers - (ancestor)->n_supers] == NODE_TYPE (ancestor))
241 : :
242 : : struct _IFaceHolder
243 : : {
244 : : GType instance_type;
245 : : GInterfaceInfo *info;
246 : : GTypePlugin *plugin;
247 : : IFaceHolder *next;
248 : : };
249 : :
250 : : struct _IFaceEntry
251 : : {
252 : : GType iface_type;
253 : : GTypeInterface *vtable;
254 : : InitState init_state;
255 : : };
256 : :
257 : : struct _IFaceEntries {
258 : : gsize offset_index;
259 : : IFaceEntry entry[1];
260 : : };
261 : :
262 : : #define IFACE_ENTRIES_HEADER_SIZE (sizeof(IFaceEntries) - sizeof(IFaceEntry))
263 : : #define IFACE_ENTRIES_N_ENTRIES(_entries) ( (G_ATOMIC_ARRAY_DATA_SIZE((_entries)) - IFACE_ENTRIES_HEADER_SIZE) / sizeof(IFaceEntry) )
264 : :
265 : : struct _CommonData
266 : : {
267 : : GTypeValueTable *value_table;
268 : : };
269 : :
270 : : struct _BoxedData
271 : : {
272 : : CommonData data;
273 : : GBoxedCopyFunc copy_func;
274 : : GBoxedFreeFunc free_func;
275 : : };
276 : :
277 : : struct _IFaceData
278 : : {
279 : : CommonData common;
280 : : guint16 vtable_size;
281 : : GBaseInitFunc vtable_init_base;
282 : : GBaseFinalizeFunc vtable_finalize_base;
283 : : GClassInitFunc dflt_init;
284 : : GClassFinalizeFunc dflt_finalize;
285 : : gconstpointer dflt_data;
286 : : gpointer dflt_vtable;
287 : : };
288 : :
289 : : struct _ClassData
290 : : {
291 : : CommonData common;
292 : : guint16 class_size;
293 : : guint16 class_private_size;
294 : : int init_state; /* (atomic) - g_type_class_get reads it unlocked */
295 : : GBaseInitFunc class_init_base;
296 : : GBaseFinalizeFunc class_finalize_base;
297 : : GClassInitFunc class_init;
298 : : GClassFinalizeFunc class_finalize;
299 : : gconstpointer class_data;
300 : : gpointer class;
301 : : };
302 : :
303 : : struct _InstanceData
304 : : {
305 : : CommonData common;
306 : : guint16 class_size;
307 : : guint16 class_private_size;
308 : : int init_state; /* (atomic) - g_type_class_get reads it unlocked */
309 : : GBaseInitFunc class_init_base;
310 : : GBaseFinalizeFunc class_finalize_base;
311 : : GClassInitFunc class_init;
312 : : GClassFinalizeFunc class_finalize;
313 : : gconstpointer class_data;
314 : : gpointer class;
315 : : guint16 instance_size;
316 : : guint16 private_size;
317 : : GInstanceInitFunc instance_init;
318 : : };
319 : :
320 : : union _TypeData
321 : : {
322 : : CommonData common;
323 : : BoxedData boxed;
324 : : IFaceData iface;
325 : : ClassData class;
326 : : InstanceData instance;
327 : : };
328 : :
329 : : typedef struct {
330 : : gpointer cache_data;
331 : : GTypeClassCacheFunc cache_func;
332 : : } ClassCacheFunc;
333 : :
334 : : typedef struct {
335 : : gpointer check_data;
336 : : GTypeInterfaceCheckFunc check_func;
337 : : } IFaceCheckFunc;
338 : :
339 : :
340 : : /* --- variables --- */
341 : : static GRWLock type_rw_lock;
342 : : static GRecMutex class_init_rec_mutex;
343 : : static guint static_n_class_cache_funcs = 0;
344 : : static ClassCacheFunc *static_class_cache_funcs = NULL;
345 : : static guint static_n_iface_check_funcs = 0;
346 : : static IFaceCheckFunc *static_iface_check_funcs = NULL;
347 : : static GQuark static_quark_type_flags = 0;
348 : : static GQuark static_quark_iface_holder = 0;
349 : : static GQuark static_quark_dependants_array = 0;
350 : : static guint type_registration_serial = 0;
351 : :
352 : : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
353 : : GTypeDebugFlags _g_type_debug_flags = 0;
354 : : G_GNUC_END_IGNORE_DEPRECATIONS
355 : :
356 : : /* --- type nodes --- */
357 : : static GHashTable *static_type_nodes_ht = NULL;
358 : : static TypeNode *static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) + 1] = { NULL, };
359 : : static GType static_fundamental_next = G_TYPE_RESERVED_USER_FIRST;
360 : :
361 : : static inline TypeNode*
362 : 768877233 : lookup_type_node_I (GType utype)
363 : : {
364 : 768877233 : if (utype > G_TYPE_FUNDAMENTAL_MAX)
365 : 659116460 : return (TypeNode*) (utype & ~TYPE_ID_MASK);
366 : : else
367 : 109760773 : return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT];
368 : : }
369 : :
370 : : /**
371 : : * g_type_get_type_registration_serial:
372 : : *
373 : : * Returns an opaque serial number that represents the state of the set
374 : : * of registered types. Any time a type is registered this serial changes,
375 : : * which means you can cache information based on type lookups (such as
376 : : * g_type_from_name()) and know if the cache is still valid at a later
377 : : * time by comparing the current serial with the one at the type lookup.
378 : : *
379 : : * Since: 2.36
380 : : *
381 : : * Returns: An unsigned int, representing the state of type registrations
382 : : */
383 : : guint
384 : 3 : g_type_get_type_registration_serial (void)
385 : : {
386 : 3 : return (guint)g_atomic_int_get ((gint *)&type_registration_serial);
387 : : }
388 : :
389 : : static TypeNode*
390 : 44673 : type_node_any_new_W (TypeNode *pnode,
391 : : GType ftype,
392 : : const gchar *name,
393 : : GTypePlugin *plugin,
394 : : GTypeFundamentalFlags type_flags)
395 : : {
396 : : guint n_supers;
397 : : GType type;
398 : : TypeNode *node;
399 : 44673 : guint i, node_size = 0;
400 : :
401 : 44673 : n_supers = pnode ? pnode->n_supers + 1 : 0;
402 : :
403 : 44673 : if (!pnode)
404 : 12361 : node_size += SIZEOF_FUNDAMENTAL_INFO; /* fundamental type info */
405 : 44673 : node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */
406 : 44673 : node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */
407 : 44673 : node = g_malloc0 (node_size);
408 : 44673 : if (!pnode) /* offset fundamental types */
409 : : {
410 : 12361 : node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
411 : 12361 : static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;
412 : 12361 : type = ftype;
413 : :
414 : : #if ENABLE_VALGRIND
415 : 12361 : VALGRIND_MALLOCLIKE_BLOCK (node, node_size - SIZEOF_FUNDAMENTAL_INFO, FALSE, TRUE);
416 : : #endif
417 : : }
418 : : else
419 : 32312 : type = GPOINTER_TO_TYPE (node);
420 : :
421 : 44673 : g_assert ((type & TYPE_ID_MASK) == 0);
422 : :
423 : 44673 : node->n_supers = n_supers;
424 : 44673 : if (!pnode)
425 : : {
426 : 12361 : node->supers[0] = type;
427 : 12361 : node->supers[1] = 0;
428 : :
429 : 12361 : node->is_abstract = (type_flags & G_TYPE_FLAG_ABSTRACT) != 0;
430 : 12361 : node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
431 : 12361 : node->is_deprecated = (type_flags & G_TYPE_FLAG_DEPRECATED) != 0;
432 : 12361 : node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
433 : :
434 : 12361 : if (NODE_IS_IFACE (node))
435 : : {
436 : 588 : IFACE_NODE_N_PREREQUISITES (node) = 0;
437 : 588 : IFACE_NODE_PREREQUISITES (node) = NULL;
438 : : }
439 : : else
440 : 11773 : _g_atomic_array_init (CLASSED_NODE_IFACES_ENTRIES (node));
441 : : }
442 : : else
443 : : {
444 : 32312 : node->supers[0] = type;
445 : 32312 : memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1u + pnode->n_supers + 1u));
446 : :
447 : 32312 : node->is_abstract = (type_flags & G_TYPE_FLAG_ABSTRACT) != 0;
448 : 32312 : node->is_classed = pnode->is_classed;
449 : 32312 : node->is_deprecated = (type_flags & G_TYPE_FLAG_DEPRECATED) != 0;
450 : 32312 : node->is_instantiatable = pnode->is_instantiatable;
451 : :
452 : 32312 : node->is_deprecated |= pnode->is_deprecated;
453 : :
454 : 32312 : if (NODE_IS_IFACE (node))
455 : : {
456 : 3789 : IFACE_NODE_N_PREREQUISITES (node) = 0;
457 : 3789 : IFACE_NODE_PREREQUISITES (node) = NULL;
458 : : }
459 : : else
460 : : {
461 : : guint j;
462 : : IFaceEntries *entries;
463 : :
464 : 28523 : entries = _g_atomic_array_copy (CLASSED_NODE_IFACES_ENTRIES (pnode),
465 : : IFACE_ENTRIES_HEADER_SIZE,
466 : : 0);
467 : 28523 : if (entries)
468 : : {
469 : 4148 : for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (entries); j++)
470 : : {
471 : 2489 : entries->entry[j].vtable = NULL;
472 : 2489 : entries->entry[j].init_state = UNINITIALIZED;
473 : : }
474 : 1659 : _g_atomic_array_update (CLASSED_NODE_IFACES_ENTRIES (node),
475 : : entries);
476 : : }
477 : : }
478 : :
479 : 32312 : i = pnode->n_children++;
480 : 32312 : pnode->children = g_renew (GType, pnode->children, pnode->n_children);
481 : 32312 : pnode->children[i] = type;
482 : : }
483 : :
484 : 44673 : TRACE (GOBJECT_TYPE_NEW (name, node->supers[1], (uintmax_t) type));
485 : :
486 : 44673 : node->plugin = plugin;
487 : 44673 : node->n_children = 0;
488 : 44673 : node->children = NULL;
489 : 44673 : node->data = NULL;
490 : 44673 : node->qname = g_quark_from_string (name);
491 : 44673 : node->global_gdata = NULL;
492 : 44673 : g_hash_table_insert (static_type_nodes_ht,
493 : 44673 : (gpointer) g_quark_to_string (node->qname),
494 : : GTYPE_TO_POINTER (type));
495 : :
496 : 44673 : g_atomic_int_inc ((gint *)&type_registration_serial);
497 : :
498 : 44673 : return node;
499 : : }
500 : :
501 : : static inline GTypeFundamentalInfo*
502 : 88174 : type_node_fundamental_info_I (TypeNode *node)
503 : : {
504 : 88174 : GType ftype = NODE_FUNDAMENTAL_TYPE (node);
505 : :
506 : 88174 : if (ftype != NODE_TYPE (node))
507 : 5274 : node = lookup_type_node_I (ftype);
508 : :
509 : 88174 : return node ? G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO) : NULL;
510 : : }
511 : :
512 : : static TypeNode*
513 : 12361 : type_node_fundamental_new_W (GType ftype,
514 : : const gchar *name,
515 : : GTypeFundamentalFlags type_flags)
516 : : {
517 : : GTypeFundamentalInfo *finfo;
518 : : TypeNode *node;
519 : :
520 : 12361 : g_assert ((ftype & TYPE_ID_MASK) == 0);
521 : 12361 : g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX);
522 : :
523 : 12361 : if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next)
524 : 13 : static_fundamental_next++;
525 : :
526 : 12361 : node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
527 : :
528 : 12361 : finfo = type_node_fundamental_info_I (node);
529 : 12361 : finfo->type_flags = type_flags & TYPE_FUNDAMENTAL_FLAG_MASK;
530 : :
531 : 12361 : return node;
532 : : }
533 : :
534 : : static TypeNode*
535 : 32312 : type_node_new_W (TypeNode *pnode,
536 : : const gchar *name,
537 : : GTypePlugin *plugin)
538 : :
539 : : {
540 : 32312 : g_assert (pnode);
541 : 32312 : g_assert (pnode->n_supers < MAX_N_SUPERS);
542 : 32312 : g_assert (pnode->n_children < MAX_N_CHILDREN);
543 : :
544 : 32312 : return type_node_any_new_W (pnode, NODE_FUNDAMENTAL_TYPE (pnode), name, plugin, 0);
545 : : }
546 : :
547 : : static inline IFaceEntry*
548 : 13781704 : lookup_iface_entry_I (IFaceEntries *entries,
549 : : TypeNode *iface_node)
550 : : {
551 : : guint8 *offsets;
552 : : gsize offset_index;
553 : : IFaceEntry *check;
554 : : gsize index;
555 : : IFaceEntry *entry;
556 : :
557 : 13781704 : if (entries == NULL)
558 : 14712 : return NULL;
559 : :
560 : 13766992 : G_ATOMIC_ARRAY_DO_TRANSACTION
561 : : (&iface_node->_prot.offsets, guint8,
562 : :
563 : : entry = NULL;
564 : : offsets = transaction_data;
565 : : offset_index = entries->offset_index;
566 : : if (offsets != NULL &&
567 : : offset_index < G_ATOMIC_ARRAY_DATA_SIZE(offsets))
568 : : {
569 : : index = offsets[offset_index];
570 : : if (index > 0)
571 : : {
572 : : /* zero means unset, subtract one to get real index */
573 : : index -= 1;
574 : :
575 : : if (index < IFACE_ENTRIES_N_ENTRIES (entries))
576 : : {
577 : : check = (IFaceEntry *)&entries->entry[index];
578 : : if (check->iface_type == NODE_TYPE (iface_node))
579 : : entry = check;
580 : : }
581 : : }
582 : : }
583 : : );
584 : :
585 : 13766992 : return entry;
586 : : }
587 : :
588 : : static inline IFaceEntry*
589 : 31674 : type_lookup_iface_entry_L (TypeNode *node,
590 : : TypeNode *iface_node)
591 : : {
592 : 31674 : if (!NODE_IS_IFACE (iface_node))
593 : 0 : return NULL;
594 : :
595 : 31674 : return lookup_iface_entry_I (CLASSED_NODE_IFACES_ENTRIES_LOCKED (node),
596 : : iface_node);
597 : : }
598 : :
599 : :
600 : : static inline gboolean
601 : 13750030 : type_lookup_iface_vtable_I (TypeNode *node,
602 : : TypeNode *iface_node,
603 : : gpointer *vtable_ptr)
604 : : {
605 : : IFaceEntry *entry;
606 : : gboolean res;
607 : :
608 : 13750030 : if (!NODE_IS_IFACE (iface_node))
609 : : {
610 : 0 : if (vtable_ptr)
611 : 0 : *vtable_ptr = NULL;
612 : 0 : return FALSE;
613 : : }
614 : :
615 : 13750030 : G_ATOMIC_ARRAY_DO_TRANSACTION
616 : : (CLASSED_NODE_IFACES_ENTRIES (node), IFaceEntries,
617 : :
618 : : entry = lookup_iface_entry_I (transaction_data, iface_node);
619 : : res = entry != NULL;
620 : : if (vtable_ptr)
621 : : {
622 : : if (entry)
623 : : *vtable_ptr = entry->vtable;
624 : : else
625 : : *vtable_ptr = NULL;
626 : : }
627 : : );
628 : :
629 : 13750030 : return res;
630 : : }
631 : :
632 : : static inline gboolean
633 : 9596 : type_lookup_prerequisite_L (TypeNode *iface,
634 : : GType prerequisite_type)
635 : : {
636 : 9596 : if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface))
637 : : {
638 : 6412 : GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1;
639 : 6412 : guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface);
640 : :
641 : : do
642 : : {
643 : : guint i;
644 : : GType *check;
645 : :
646 : 6419 : i = (n_prerequisites + 1) >> 1;
647 : 6419 : check = prerequisites + i;
648 : 6419 : if (prerequisite_type == *check)
649 : 4312 : return TRUE;
650 : 2107 : else if (prerequisite_type > *check)
651 : : {
652 : 1212 : n_prerequisites -= i;
653 : 1212 : prerequisites = check;
654 : : }
655 : : else /* if (prerequisite_type < *check) */
656 : 895 : n_prerequisites = i - 1;
657 : : }
658 : 2107 : while (n_prerequisites);
659 : : }
660 : 5284 : return FALSE;
661 : : }
662 : :
663 : : static const gchar*
664 : 0 : type_descriptive_name_I (GType type)
665 : : {
666 : 0 : if (type)
667 : : {
668 : 0 : TypeNode *node = lookup_type_node_I (type);
669 : :
670 : 0 : return node ? NODE_NAME (node) : "<unknown>";
671 : : }
672 : : else
673 : 0 : return "<invalid>";
674 : : }
675 : :
676 : :
677 : : /* --- type consistency checks --- */
678 : : static gboolean
679 : 6 : check_plugin_U (GTypePlugin *plugin,
680 : : gboolean need_complete_type_info,
681 : : gboolean need_complete_interface_info,
682 : : const gchar *type_name)
683 : : {
684 : : /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U
685 : : */
686 : 6 : if (!plugin)
687 : : {
688 : 0 : g_critical ("plugin handle for type '%s' is NULL",
689 : : type_name);
690 : 0 : return FALSE;
691 : : }
692 : 6 : if (!G_IS_TYPE_PLUGIN (plugin))
693 : : {
694 : 0 : g_critical ("plugin pointer (%p) for type '%s' is invalid",
695 : : plugin, type_name);
696 : 0 : return FALSE;
697 : : }
698 : 6 : if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
699 : : {
700 : 0 : g_critical ("plugin for type '%s' has no complete_type_info() implementation",
701 : : type_name);
702 : 0 : return FALSE;
703 : : }
704 : 6 : if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
705 : : {
706 : 0 : g_critical ("plugin for type '%s' has no complete_interface_info() implementation",
707 : : type_name);
708 : 0 : return FALSE;
709 : : }
710 : 6 : return TRUE;
711 : : }
712 : :
713 : : static gboolean
714 : 43498 : check_type_name_I (const gchar *type_name)
715 : : {
716 : : static const gchar extra_chars[] = "-_+";
717 : 43498 : const gchar *p = type_name;
718 : : gboolean name_valid;
719 : :
720 : 43498 : if (!type_name[0] || !type_name[1] || !type_name[2])
721 : : {
722 : 0 : g_critical ("type name '%s' is too short", type_name);
723 : 0 : return FALSE;
724 : : }
725 : : /* check the first letter */
726 : 43498 : name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
727 : 513550 : for (p = type_name + 1; *p; p++)
728 : 934810 : name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
729 : 387953 : (p[0] >= 'a' && p[0] <= 'z') ||
730 : 940105 : (p[0] >= '0' && p[0] <= '9') ||
731 : 1 : strchr (extra_chars, p[0]));
732 : 43498 : if (!name_valid)
733 : : {
734 : 0 : g_critical ("type name '%s' contains invalid characters", type_name);
735 : 0 : return FALSE;
736 : : }
737 : 43498 : if (g_type_from_name (type_name))
738 : : {
739 : 0 : g_critical ("cannot register existing type '%s'", type_name);
740 : 0 : return FALSE;
741 : : }
742 : :
743 : 43498 : return TRUE;
744 : : }
745 : :
746 : : static gboolean
747 : 32313 : check_derivation_I (GType parent_type,
748 : : const gchar *type_name)
749 : : {
750 : : TypeNode *pnode;
751 : : GTypeFundamentalInfo* finfo;
752 : :
753 : 32313 : pnode = lookup_type_node_I (parent_type);
754 : 32313 : if (!pnode)
755 : : {
756 : 0 : g_critical ("cannot derive type '%s' from invalid parent type '%s'",
757 : : type_name,
758 : : type_descriptive_name_I (parent_type));
759 : 0 : return FALSE;
760 : : }
761 : 32313 : if (pnode->is_final)
762 : : {
763 : 1 : g_critical ("cannot derive '%s' from final parent type '%s'",
764 : : type_name,
765 : : NODE_NAME (pnode));
766 : 1 : return FALSE;
767 : : }
768 : 32312 : finfo = type_node_fundamental_info_I (pnode);
769 : : /* ensure flat derivability */
770 : 32312 : if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
771 : : {
772 : 0 : g_critical ("cannot derive '%s' from non-derivable parent type '%s'",
773 : : type_name,
774 : : NODE_NAME (pnode));
775 : 0 : return FALSE;
776 : : }
777 : : /* ensure deep derivability */
778 : 32312 : if (parent_type != NODE_FUNDAMENTAL_TYPE (pnode) &&
779 : 5270 : !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
780 : : {
781 : 0 : g_critical ("cannot derive '%s' from non-fundamental parent type '%s'",
782 : : type_name,
783 : : NODE_NAME (pnode));
784 : 0 : return FALSE;
785 : : }
786 : :
787 : 32312 : return TRUE;
788 : : }
789 : :
790 : : static gboolean
791 : 23986 : check_collect_format_I (const gchar *collect_format)
792 : : {
793 : 23986 : const gchar *p = collect_format;
794 : 23986 : gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
795 : : G_VALUE_COLLECT_INT64, G_VALUE_COLLECT_DOUBLE,
796 : : G_VALUE_COLLECT_POINTER, 0 };
797 : :
798 : 47972 : while (*p)
799 : 23986 : if (!strchr (valid_format, *p++))
800 : 0 : return FALSE;
801 : 23986 : return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
802 : : }
803 : :
804 : : static gboolean
805 : 43497 : check_value_table_I (const gchar *type_name,
806 : : const GTypeValueTable *value_table)
807 : : {
808 : 43497 : if (!value_table)
809 : 31500 : return FALSE;
810 : 11997 : else if (value_table->value_init == NULL)
811 : : {
812 : 4 : if (value_table->value_free || value_table->value_copy ||
813 : 4 : value_table->value_peek_pointer ||
814 : 4 : value_table->collect_format || value_table->collect_value ||
815 : 4 : value_table->lcopy_format || value_table->lcopy_value)
816 : 0 : g_critical ("cannot handle uninitializable values of type '%s'",
817 : : type_name);
818 : 4 : return FALSE;
819 : : }
820 : : else /* value_table->value_init != NULL */
821 : : {
822 : 11993 : if (!value_table->value_free)
823 : : {
824 : : /* +++ optional +++
825 : : * g_critical ("missing 'value_free()' for type '%s'", type_name);
826 : : * return FALSE;
827 : : */
828 : : }
829 : 11993 : if (!value_table->value_copy)
830 : : {
831 : 0 : g_critical ("missing 'value_copy()' for type '%s'", type_name);
832 : 0 : return FALSE;
833 : : }
834 : 11993 : if ((value_table->collect_format || value_table->collect_value) &&
835 : 11993 : (!value_table->collect_format || !value_table->collect_value))
836 : : {
837 : 0 : g_critical ("one of 'collect_format' and 'collect_value()' is unspecified for type '%s'",
838 : : type_name);
839 : 0 : return FALSE;
840 : : }
841 : 11993 : if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
842 : : {
843 : 0 : g_critical ("the '%s' specification for type '%s' is too long or invalid",
844 : : "collect_format",
845 : : type_name);
846 : 0 : return FALSE;
847 : : }
848 : 11993 : if ((value_table->lcopy_format || value_table->lcopy_value) &&
849 : 11993 : (!value_table->lcopy_format || !value_table->lcopy_value))
850 : : {
851 : 0 : g_critical ("one of 'lcopy_format' and 'lcopy_value()' is unspecified for type '%s'",
852 : : type_name);
853 : 0 : return FALSE;
854 : : }
855 : 11993 : if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
856 : : {
857 : 0 : g_critical ("the '%s' specification for type '%s' is too long or invalid",
858 : : "lcopy_format",
859 : : type_name);
860 : 0 : return FALSE;
861 : : }
862 : : }
863 : 11993 : return TRUE;
864 : : }
865 : :
866 : : static gboolean
867 : 43497 : check_type_info_I (TypeNode *pnode,
868 : : GType ftype,
869 : : const gchar *type_name,
870 : : const GTypeInfo *info)
871 : : {
872 : 43497 : GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (lookup_type_node_I (ftype));
873 : 43497 : gboolean is_interface = ftype == G_TYPE_INTERFACE;
874 : :
875 : 43497 : g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX && !(ftype & TYPE_ID_MASK));
876 : :
877 : : /* check instance members */
878 : 43497 : if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
879 : 17748 : (info->instance_size || info->instance_init))
880 : : {
881 : 0 : if (pnode)
882 : 0 : g_critical ("cannot instantiate '%s', derived from non-instantiatable parent type '%s'",
883 : : type_name,
884 : : NODE_NAME (pnode));
885 : : else
886 : 0 : g_critical ("cannot instantiate '%s' as non-instantiatable fundamental",
887 : : type_name);
888 : 0 : return FALSE;
889 : : }
890 : : /* check class & interface members */
891 : 43497 : if (!((finfo->type_flags & G_TYPE_FLAG_CLASSED) || is_interface) &&
892 : 10809 : (info->class_init || info->class_finalize || info->class_data ||
893 : 10809 : info->class_size || info->base_init || info->base_finalize))
894 : : {
895 : 0 : if (pnode)
896 : 0 : g_critical ("cannot create class for '%s', derived from non-classed parent type '%s'",
897 : : type_name,
898 : : NODE_NAME (pnode));
899 : : else
900 : 0 : g_critical ("cannot create class for '%s' as non-classed fundamental",
901 : : type_name);
902 : 0 : return FALSE;
903 : : }
904 : : /* check interface size */
905 : 43497 : if (is_interface && info->class_size < sizeof (GTypeInterface))
906 : : {
907 : 0 : g_critical ("specified interface size for type '%s' is smaller than 'GTypeInterface' size",
908 : : type_name);
909 : 0 : return FALSE;
910 : : }
911 : : /* check class size */
912 : 43497 : if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
913 : : {
914 : 28899 : if (info->class_size < sizeof (GTypeClass))
915 : : {
916 : 0 : g_critical ("specified class size for type '%s' is smaller than 'GTypeClass' size",
917 : : type_name);
918 : 0 : return FALSE;
919 : : }
920 : 28899 : if (pnode && info->class_size < pnode->data->class.class_size)
921 : : {
922 : 0 : g_critical ("specified class size for type '%s' is smaller "
923 : : "than the parent type's '%s' class size",
924 : : type_name,
925 : : NODE_NAME (pnode));
926 : 0 : return FALSE;
927 : : }
928 : : }
929 : : /* check instance size */
930 : 43497 : if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
931 : : {
932 : 25749 : if (info->instance_size < sizeof (GTypeInstance))
933 : : {
934 : 0 : g_critical ("specified instance size for type '%s' is smaller than 'GTypeInstance' size",
935 : : type_name);
936 : 0 : return FALSE;
937 : : }
938 : 25749 : if (pnode && info->instance_size < pnode->data->instance.instance_size)
939 : : {
940 : 0 : g_critical ("specified instance size for type '%s' is smaller "
941 : : "than the parent type's '%s' instance size",
942 : : type_name,
943 : : NODE_NAME (pnode));
944 : 0 : return FALSE;
945 : : }
946 : : }
947 : :
948 : 43497 : return TRUE;
949 : : }
950 : :
951 : : static TypeNode*
952 : 5850 : find_conforming_child_type_L (TypeNode *pnode,
953 : : TypeNode *iface)
954 : : {
955 : 5850 : TypeNode *node = NULL;
956 : : guint i;
957 : :
958 : 5850 : if (type_lookup_iface_entry_L (pnode, iface))
959 : 0 : return pnode;
960 : :
961 : 5850 : for (i = 0; i < pnode->n_children && !node; i++)
962 : 0 : node = find_conforming_child_type_L (lookup_type_node_I (pnode->children[i]), iface);
963 : :
964 : 5850 : return node;
965 : : }
966 : :
967 : : static gboolean
968 : 7645 : check_add_interface_L (GType instance_type,
969 : : GType iface_type)
970 : : {
971 : 7645 : TypeNode *node = lookup_type_node_I (instance_type);
972 : 7645 : TypeNode *iface = lookup_type_node_I (iface_type);
973 : : IFaceEntry *entry;
974 : : TypeNode *tnode;
975 : : GType *prerequisites;
976 : : guint i;
977 : :
978 : :
979 : 7645 : if (!node || !node->is_instantiatable)
980 : : {
981 : 0 : g_critical ("cannot add interfaces to invalid (non-instantiatable) type '%s'",
982 : : type_descriptive_name_I (instance_type));
983 : 0 : return FALSE;
984 : : }
985 : 7645 : if (!iface || !NODE_IS_IFACE (iface))
986 : : {
987 : 0 : g_critical ("cannot add invalid (non-interface) type '%s' to type '%s'",
988 : : type_descriptive_name_I (iface_type),
989 : : NODE_NAME (node));
990 : 0 : return FALSE;
991 : : }
992 : 7645 : if (node->data && node->data->class.class)
993 : : {
994 : 0 : g_critical ("attempting to add an interface (%s) to class (%s) after class_init",
995 : : NODE_NAME (iface), NODE_NAME (node));
996 : 0 : return FALSE;
997 : : }
998 : 7645 : tnode = lookup_type_node_I (NODE_PARENT_TYPE (iface));
999 : 7645 : if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
1000 : : {
1001 : : /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */
1002 : 0 : g_critical ("cannot add sub-interface '%s' to type '%s' which does not conform to super-interface '%s'",
1003 : : NODE_NAME (iface),
1004 : : NODE_NAME (node),
1005 : : NODE_NAME (tnode));
1006 : 0 : return FALSE;
1007 : : }
1008 : : /* allow overriding of interface type introduced for parent type */
1009 : 7645 : entry = type_lookup_iface_entry_L (node, iface);
1010 : 7645 : if (entry && entry->vtable == NULL && !type_iface_peek_holder_L (iface, NODE_TYPE (node)))
1011 : : {
1012 : : /* ok, we do conform to this interface already, but the interface vtable was not
1013 : : * yet initialized, and we just conform to the interface because it got added to
1014 : : * one of our parents. so we allow overriding of holder info here.
1015 : : */
1016 : 1795 : return TRUE;
1017 : : }
1018 : : /* check whether one of our children already conforms (or whether the interface
1019 : : * got added to this node already)
1020 : : */
1021 : 5850 : tnode = find_conforming_child_type_L (node, iface); /* tnode is_a node */
1022 : 5850 : if (tnode)
1023 : : {
1024 : 0 : g_critical ("cannot add interface type '%s' to type '%s', since type '%s' already conforms to interface",
1025 : : NODE_NAME (iface),
1026 : : NODE_NAME (node),
1027 : : NODE_NAME (tnode));
1028 : 0 : return FALSE;
1029 : : }
1030 : 5850 : prerequisites = IFACE_NODE_PREREQUISITES (iface);
1031 : 13097 : for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1032 : : {
1033 : 7247 : tnode = lookup_type_node_I (prerequisites[i]);
1034 : 7247 : if (!type_node_is_a_L (node, tnode))
1035 : : {
1036 : 0 : g_critical ("cannot add interface type '%s' to type '%s' which does not conform to prerequisite '%s'",
1037 : : NODE_NAME (iface),
1038 : : NODE_NAME (node),
1039 : : NODE_NAME (tnode));
1040 : 0 : return FALSE;
1041 : : }
1042 : : }
1043 : 5850 : return TRUE;
1044 : : }
1045 : :
1046 : : static gboolean
1047 : 7645 : check_interface_info_I (TypeNode *iface,
1048 : : GType instance_type,
1049 : : const GInterfaceInfo *info)
1050 : : {
1051 : 7645 : if ((info->interface_finalize || info->interface_data) && !info->interface_init)
1052 : : {
1053 : 0 : g_critical ("interface type '%s' for type '%s' comes without initializer",
1054 : : NODE_NAME (iface),
1055 : : type_descriptive_name_I (instance_type));
1056 : 0 : return FALSE;
1057 : : }
1058 : :
1059 : 7645 : return TRUE;
1060 : : }
1061 : :
1062 : : /* --- type info (type node data) --- */
1063 : : static void
1064 : 44085 : type_data_make_W (TypeNode *node,
1065 : : const GTypeInfo *info,
1066 : : const GTypeValueTable *value_table)
1067 : : {
1068 : : TypeData *data;
1069 : 44085 : GTypeValueTable *vtable = NULL;
1070 : 44085 : size_t vtable_size = 0;
1071 : :
1072 : 44085 : g_assert (node->data == NULL && info != NULL);
1073 : :
1074 : 44085 : if (!value_table)
1075 : : {
1076 : 32092 : TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1077 : :
1078 : 32092 : if (pnode)
1079 : 30914 : vtable = pnode->data->common.value_table;
1080 : : else
1081 : : {
1082 : : static const GTypeValueTable zero_vtable =
1083 : : { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
1084 : :
1085 : 1178 : value_table = &zero_vtable;
1086 : : }
1087 : : }
1088 : 44085 : if (value_table)
1089 : : {
1090 : : /* need to setup vtable_size since we have to allocate it with data in one chunk */
1091 : 13171 : vtable_size = sizeof (GTypeValueTable);
1092 : 13171 : if (value_table->collect_format)
1093 : 11993 : vtable_size += strlen (value_table->collect_format);
1094 : 13171 : if (value_table->lcopy_format)
1095 : 11993 : vtable_size += strlen (value_table->lcopy_format);
1096 : 13171 : vtable_size += 2;
1097 : : }
1098 : :
1099 : 44085 : if (node->is_instantiatable) /* careful, is_instantiatable is also is_classed */
1100 : : {
1101 : 25749 : TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1102 : :
1103 : 25749 : data = g_malloc0 (sizeof (InstanceData) + vtable_size);
1104 : 25749 : if (vtable_size)
1105 : 1187 : vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
1106 : 25749 : data->instance.class_size = info->class_size;
1107 : 25749 : data->instance.class_init_base = info->base_init;
1108 : 25749 : data->instance.class_finalize_base = info->base_finalize;
1109 : 25749 : data->instance.class_init = info->class_init;
1110 : 25749 : data->instance.class_finalize = info->class_finalize;
1111 : 25749 : data->instance.class_data = info->class_data;
1112 : 25749 : data->instance.class = NULL;
1113 : 25749 : data->instance.init_state = UNINITIALIZED;
1114 : 25749 : data->instance.instance_size = info->instance_size;
1115 : : /* We'll set the final value for data->instance.private size
1116 : : * after the parent class has been initialized
1117 : : */
1118 : 25749 : data->instance.private_size = 0;
1119 : 25749 : data->instance.class_private_size = 0;
1120 : 25749 : if (pnode)
1121 : 24562 : data->instance.class_private_size = pnode->data->instance.class_private_size;
1122 : 25749 : data->instance.instance_init = info->instance_init;
1123 : : }
1124 : 18336 : else if (node->is_classed) /* only classed */
1125 : : {
1126 : 3150 : TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1127 : :
1128 : 3150 : data = g_malloc0 (sizeof (ClassData) + vtable_size);
1129 : 3150 : if (vtable_size)
1130 : 1176 : vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
1131 : 3150 : data->class.class_size = info->class_size;
1132 : 3150 : data->class.class_init_base = info->base_init;
1133 : 3150 : data->class.class_finalize_base = info->base_finalize;
1134 : 3150 : data->class.class_init = info->class_init;
1135 : 3150 : data->class.class_finalize = info->class_finalize;
1136 : 3150 : data->class.class_data = info->class_data;
1137 : 3150 : data->class.class = NULL;
1138 : 3150 : data->class.class_private_size = 0;
1139 : 3150 : if (pnode)
1140 : 1974 : data->class.class_private_size = pnode->data->class.class_private_size;
1141 : 3150 : data->class.init_state = UNINITIALIZED;
1142 : : }
1143 : 15186 : else if (NODE_IS_IFACE (node))
1144 : : {
1145 : 4377 : data = g_malloc0 (sizeof (IFaceData) + vtable_size);
1146 : 4377 : if (vtable_size)
1147 : 588 : vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
1148 : 4377 : data->iface.vtable_size = info->class_size;
1149 : 4377 : data->iface.vtable_init_base = info->base_init;
1150 : 4377 : data->iface.vtable_finalize_base = info->base_finalize;
1151 : 4377 : data->iface.dflt_init = info->class_init;
1152 : 4377 : data->iface.dflt_finalize = info->class_finalize;
1153 : 4377 : data->iface.dflt_data = info->class_data;
1154 : 4377 : data->iface.dflt_vtable = NULL;
1155 : : }
1156 : 10809 : else if (NODE_IS_BOXED (node))
1157 : : {
1158 : 1986 : data = g_malloc0 (sizeof (BoxedData) + vtable_size);
1159 : 1986 : if (vtable_size)
1160 : 1986 : vtable = G_STRUCT_MEMBER_P (data, sizeof (BoxedData));
1161 : : }
1162 : : else
1163 : : {
1164 : 8823 : data = g_malloc0 (sizeof (CommonData) + vtable_size);
1165 : 8823 : if (vtable_size)
1166 : 8234 : vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
1167 : : }
1168 : :
1169 : 44085 : node->data = data;
1170 : :
1171 : 44085 : if (vtable_size)
1172 : : {
1173 : : gchar *p;
1174 : :
1175 : : /* we allocate the vtable and its strings together with the type data, so
1176 : : * children can take over their parent's vtable pointer, and we don't
1177 : : * need to worry freeing it or not when the child data is destroyed
1178 : : */
1179 : 13171 : *vtable = *value_table;
1180 : 13171 : p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable));
1181 : 13171 : p[0] = 0;
1182 : 13171 : vtable->collect_format = p;
1183 : 13171 : if (value_table->collect_format)
1184 : : {
1185 : 11993 : strcat (p, value_table->collect_format);
1186 : 11993 : p += strlen (value_table->collect_format);
1187 : : }
1188 : 13171 : p++;
1189 : 13171 : p[0] = 0;
1190 : 13171 : vtable->lcopy_format = p;
1191 : 13171 : if (value_table->lcopy_format)
1192 : 11993 : strcat (p, value_table->lcopy_format);
1193 : : }
1194 : :
1195 : 44085 : node->data->common.value_table = vtable;
1196 : 44085 : g_assert (node->data->common.value_table != NULL); /* paranoid */
1197 : 83203 : node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL &&
1198 : 39118 : !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) &
1199 : 39118 : GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))));
1200 : :
1201 : 44085 : g_assert (node->data->common.value_table != NULL); /* paranoid */
1202 : 44085 : }
1203 : :
1204 : : static inline void
1205 : 56063 : type_data_ref_Wm (TypeNode *node)
1206 : : {
1207 : 56063 : if (!node->data)
1208 : : {
1209 : 4 : TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
1210 : : GTypeInfo tmp_info;
1211 : : GTypeValueTable tmp_value_table;
1212 : :
1213 : 4 : g_assert (node->plugin != NULL);
1214 : :
1215 : 4 : if (pnode)
1216 : : {
1217 : 4 : type_data_ref_Wm (pnode);
1218 : 4 : if (node->data)
1219 : 0 : INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1220 : : }
1221 : :
1222 : 4 : memset (&tmp_info, 0, sizeof (tmp_info));
1223 : 4 : memset (&tmp_value_table, 0, sizeof (tmp_value_table));
1224 : :
1225 : 4 : G_WRITE_UNLOCK (&type_rw_lock);
1226 : 4 : g_type_plugin_use (node->plugin);
1227 : 4 : g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
1228 : 4 : G_WRITE_LOCK (&type_rw_lock);
1229 : 4 : if (node->data)
1230 : 0 : INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
1231 : :
1232 : 4 : check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (node), NODE_NAME (node), &tmp_info);
1233 : 4 : type_data_make_W (node, &tmp_info,
1234 : 4 : check_value_table_I (NODE_NAME (node),
1235 : : &tmp_value_table) ? &tmp_value_table : NULL);
1236 : : }
1237 : 56063 : }
1238 : :
1239 : : static gboolean
1240 : 6745 : iface_node_has_available_offset_L (TypeNode *iface_node,
1241 : : gsize offset,
1242 : : size_t for_index)
1243 : : {
1244 : : guint8 *offsets;
1245 : :
1246 : 6745 : offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->_prot.offsets, guint8);
1247 : 6745 : if (offsets == NULL)
1248 : 2848 : return TRUE;
1249 : :
1250 : 3897 : if (G_ATOMIC_ARRAY_DATA_SIZE (offsets) <= offset)
1251 : 561 : return TRUE;
1252 : :
1253 : 3336 : if (offsets[offset] == 0 ||
1254 : 3228 : offsets[offset] == for_index+1)
1255 : 2745 : return TRUE;
1256 : :
1257 : 591 : return FALSE;
1258 : : }
1259 : :
1260 : : static gsize
1261 : 295 : find_free_iface_offset_L (IFaceEntries *entries)
1262 : : {
1263 : : IFaceEntry *entry;
1264 : : TypeNode *iface_node;
1265 : : gsize offset;
1266 : : size_t i, n_entries;
1267 : :
1268 : 295 : n_entries = IFACE_ENTRIES_N_ENTRIES (entries);
1269 : 295 : offset = 0;
1270 : : do
1271 : : {
1272 : 1190 : for (i = 0; i < n_entries; i++)
1273 : : {
1274 : 895 : entry = &entries->entry[i];
1275 : 895 : iface_node = lookup_type_node_I (entry->iface_type);
1276 : :
1277 : 895 : if (!iface_node_has_available_offset_L (iface_node, offset, i))
1278 : : {
1279 : 296 : offset++;
1280 : 296 : break;
1281 : : }
1282 : : }
1283 : : }
1284 : 591 : while (i != n_entries);
1285 : :
1286 : 295 : return offset;
1287 : : }
1288 : :
1289 : : static void
1290 : 6002 : iface_node_set_offset_L (TypeNode *iface_node,
1291 : : gsize offset,
1292 : : size_t index)
1293 : : {
1294 : : guint8 *offsets, *old_offsets;
1295 : : gsize new_size, old_size;
1296 : : gsize i;
1297 : :
1298 : 6002 : old_offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->_prot.offsets, guint8);
1299 : 6002 : if (old_offsets == NULL)
1300 : 2848 : old_size = 0;
1301 : : else
1302 : : {
1303 : 3154 : old_size = G_ATOMIC_ARRAY_DATA_SIZE (old_offsets);
1304 : 3154 : if (offset < old_size &&
1305 : 2593 : old_offsets[offset] == index + 1)
1306 : 2485 : return; /* Already set to this index, return */
1307 : : }
1308 : 3517 : new_size = MAX (old_size, offset + 1);
1309 : :
1310 : 3517 : offsets = _g_atomic_array_copy (&iface_node->_prot.offsets,
1311 : : 0, new_size - old_size);
1312 : :
1313 : : /* Mark new area as unused */
1314 : 7085 : for (i = old_size; i < new_size; i++)
1315 : 3568 : offsets[i] = 0;
1316 : :
1317 : 3517 : offsets[offset] = index + 1;
1318 : :
1319 : 3517 : _g_atomic_array_update (&iface_node->_prot.offsets, offsets);
1320 : : }
1321 : :
1322 : : static void
1323 : 7645 : type_node_add_iface_entry_W (TypeNode *node,
1324 : : GType iface_type,
1325 : : IFaceEntry *parent_entry)
1326 : : {
1327 : : IFaceEntries *entries;
1328 : : IFaceEntry *entry;
1329 : : TypeNode *iface_node;
1330 : : size_t i, j;
1331 : : size_t num_entries;
1332 : :
1333 : 7645 : g_assert (node->is_instantiatable);
1334 : :
1335 : 7645 : entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node);
1336 : 7645 : if (entries != NULL)
1337 : : {
1338 : 3927 : num_entries = IFACE_ENTRIES_N_ENTRIES (entries);
1339 : :
1340 : 3927 : g_assert (num_entries < MAX_N_INTERFACES);
1341 : :
1342 : 7046 : for (i = 0; i < num_entries; i++)
1343 : : {
1344 : 4914 : entry = &entries->entry[i];
1345 : 4914 : if (entry->iface_type == iface_type)
1346 : : {
1347 : : /* this can happen in two cases:
1348 : : * - our parent type already conformed to iface_type and node
1349 : : * got its own holder info. here, our children already have
1350 : : * entries and NULL vtables, since this will only work for
1351 : : * uninitialized classes.
1352 : : * - an interface type is added to an ancestor after it was
1353 : : * added to a child type.
1354 : : */
1355 : 1795 : if (!parent_entry)
1356 : 1795 : g_assert (entry->vtable == NULL && entry->init_state == UNINITIALIZED);
1357 : : else
1358 : : {
1359 : : /* sick, interface is added to ancestor *after* child type;
1360 : : * nothing todo, the entry and our children were already setup correctly
1361 : : */
1362 : : }
1363 : 1795 : return;
1364 : : }
1365 : : }
1366 : : }
1367 : :
1368 : 5850 : entries = _g_atomic_array_copy (CLASSED_NODE_IFACES_ENTRIES (node),
1369 : : IFACE_ENTRIES_HEADER_SIZE,
1370 : : sizeof (IFaceEntry));
1371 : 5850 : num_entries = IFACE_ENTRIES_N_ENTRIES (entries);
1372 : 5850 : i = num_entries - 1;
1373 : 5850 : if (i == 0)
1374 : 3718 : entries->offset_index = 0;
1375 : 5850 : entries->entry[i].iface_type = iface_type;
1376 : 5850 : entries->entry[i].vtable = NULL;
1377 : 5850 : entries->entry[i].init_state = UNINITIALIZED;
1378 : :
1379 : 5850 : if (parent_entry)
1380 : : {
1381 : 0 : if (node->data && g_atomic_int_get (&node->data->class.init_state) >= BASE_IFACE_INIT)
1382 : : {
1383 : 0 : entries->entry[i].init_state = INITIALIZED;
1384 : 0 : entries->entry[i].vtable = parent_entry->vtable;
1385 : : }
1386 : : }
1387 : :
1388 : : /* Update offsets in iface */
1389 : 5850 : iface_node = lookup_type_node_I (iface_type);
1390 : :
1391 : 5850 : if (iface_node_has_available_offset_L (iface_node,
1392 : : entries->offset_index,
1393 : : i))
1394 : : {
1395 : 5555 : iface_node_set_offset_L (iface_node,
1396 : : entries->offset_index, i);
1397 : : }
1398 : : else
1399 : : {
1400 : 295 : entries->offset_index =
1401 : 295 : find_free_iface_offset_L (entries);
1402 : 742 : for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (entries); j++)
1403 : : {
1404 : 447 : entry = &entries->entry[j];
1405 : : iface_node =
1406 : 447 : lookup_type_node_I (entry->iface_type);
1407 : 447 : iface_node_set_offset_L (iface_node,
1408 : : entries->offset_index, j);
1409 : : }
1410 : : }
1411 : :
1412 : 5850 : _g_atomic_array_update (CLASSED_NODE_IFACES_ENTRIES (node), entries);
1413 : :
1414 : 5850 : if (parent_entry)
1415 : : {
1416 : 0 : for (i = 0; i < node->n_children; i++)
1417 : 0 : type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), iface_type, &entries->entry[i]);
1418 : : }
1419 : : }
1420 : :
1421 : : static void
1422 : 7645 : type_add_interface_Wm (TypeNode *node,
1423 : : TypeNode *iface,
1424 : : const GInterfaceInfo *info,
1425 : : GTypePlugin *plugin)
1426 : : {
1427 : 7645 : IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
1428 : : IFaceEntry *entry;
1429 : : guint i;
1430 : :
1431 : 7645 : g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin)));
1432 : :
1433 : 7645 : iholder->next = iface_node_get_holders_L (iface);
1434 : 7645 : iface_node_set_holders_W (iface, iholder);
1435 : 7645 : iholder->instance_type = NODE_TYPE (node);
1436 : 7645 : iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL;
1437 : 7645 : iholder->plugin = plugin;
1438 : :
1439 : : /* create an iface entry for this type */
1440 : 7645 : type_node_add_iface_entry_W (node, NODE_TYPE (iface), NULL);
1441 : :
1442 : : /* if the class is already (partly) initialized, we may need to base
1443 : : * initialize and/or initialize the new interface.
1444 : : */
1445 : 7645 : if (node->data)
1446 : : {
1447 : 7643 : InitState class_state = (InitState) g_atomic_int_get (&node->data->class.init_state);
1448 : :
1449 : 7643 : if (class_state >= BASE_IFACE_INIT)
1450 : 0 : type_iface_vtable_base_init_Wm (iface, node);
1451 : :
1452 : 7643 : if (class_state >= IFACE_INIT)
1453 : 0 : type_iface_vtable_iface_init_Wm (iface, node);
1454 : : }
1455 : :
1456 : : /* create iface entries for children of this type */
1457 : 7645 : entry = type_lookup_iface_entry_L (node, iface);
1458 : 7645 : for (i = 0; i < node->n_children; i++)
1459 : 0 : type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), NODE_TYPE (iface), entry);
1460 : 7645 : }
1461 : :
1462 : : static void
1463 : 4682 : type_iface_add_prerequisite_W (TypeNode *iface,
1464 : : TypeNode *prerequisite_node)
1465 : : {
1466 : 4682 : GType prerequisite_type = NODE_TYPE (prerequisite_node);
1467 : : GType *prerequisites, *dependants;
1468 : : size_t n_dependants, i;
1469 : :
1470 : 4682 : g_assert (NODE_IS_IFACE (iface) &&
1471 : : IFACE_NODE_N_PREREQUISITES (iface) < MAX_N_PREREQUISITES &&
1472 : : (prerequisite_node->is_instantiatable || NODE_IS_IFACE (prerequisite_node)));
1473 : :
1474 : 4682 : prerequisites = IFACE_NODE_PREREQUISITES (iface);
1475 : 5303 : for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1476 : 1509 : if (prerequisites[i] == prerequisite_type)
1477 : 581 : return; /* we already have that prerequisiste */
1478 : 928 : else if (prerequisites[i] > prerequisite_type)
1479 : 307 : break;
1480 : 4101 : IFACE_NODE_N_PREREQUISITES (iface) += 1;
1481 : 4101 : IFACE_NODE_PREREQUISITES (iface) = g_renew (GType,
1482 : : IFACE_NODE_PREREQUISITES (iface),
1483 : : IFACE_NODE_N_PREREQUISITES (iface));
1484 : 4101 : prerequisites = IFACE_NODE_PREREQUISITES (iface);
1485 : 4101 : memmove (prerequisites + i + 1, prerequisites + i,
1486 : 4101 : sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1));
1487 : 4101 : prerequisites[i] = prerequisite_type;
1488 : :
1489 : : /* we want to get notified when prerequisites get added to prerequisite_node */
1490 : 4101 : if (NODE_IS_IFACE (prerequisite_node))
1491 : : {
1492 : 613 : dependants = iface_node_get_dependants_array_L (prerequisite_node);
1493 : 613 : n_dependants = dependants ? dependants[0] : 0;
1494 : 613 : n_dependants += 1;
1495 : 613 : dependants = g_renew (GType, dependants, n_dependants + 1);
1496 : 613 : dependants[n_dependants] = NODE_TYPE (iface);
1497 : 613 : dependants[0] = n_dependants;
1498 : 613 : iface_node_set_dependants_array_W (prerequisite_node, dependants);
1499 : : }
1500 : :
1501 : : /* we need to notify all dependants */
1502 : 4101 : dependants = iface_node_get_dependants_array_L (iface);
1503 : 4101 : n_dependants = dependants ? dependants[0] : 0;
1504 : 4101 : for (i = 1; i <= n_dependants; i++)
1505 : 0 : type_iface_add_prerequisite_W (lookup_type_node_I (dependants[i]), prerequisite_node);
1506 : : }
1507 : :
1508 : : /**
1509 : : * g_type_interface_add_prerequisite:
1510 : : * @interface_type: #GType value of an interface type
1511 : : * @prerequisite_type: #GType value of an interface or instantiatable type
1512 : : *
1513 : : * Adds @prerequisite_type to the list of prerequisites of @interface_type.
1514 : : * This means that any type implementing @interface_type must also implement
1515 : : * @prerequisite_type. Prerequisites can be thought of as an alternative to
1516 : : * interface derivation (which GType doesn't support). An interface can have
1517 : : * at most one instantiatable prerequisite type.
1518 : : */
1519 : : void
1520 : 3764 : g_type_interface_add_prerequisite (GType interface_type,
1521 : : GType prerequisite_type)
1522 : : {
1523 : : TypeNode *iface, *prerequisite_node;
1524 : : IFaceHolder *holders;
1525 : :
1526 : 3764 : g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type)); /* G_TYPE_IS_INTERFACE() is an external call: _U */
1527 : 3764 : g_return_if_fail (!g_type_is_a (interface_type, prerequisite_type));
1528 : 3764 : g_return_if_fail (!g_type_is_a (prerequisite_type, interface_type));
1529 : :
1530 : 3764 : iface = lookup_type_node_I (interface_type);
1531 : 3764 : prerequisite_node = lookup_type_node_I (prerequisite_type);
1532 : 3764 : if (!iface || !prerequisite_node || !NODE_IS_IFACE (iface))
1533 : : {
1534 : 0 : g_critical ("interface type '%s' or prerequisite type '%s' invalid",
1535 : : type_descriptive_name_I (interface_type),
1536 : : type_descriptive_name_I (prerequisite_type));
1537 : 0 : return;
1538 : : }
1539 : 3764 : G_WRITE_LOCK (&type_rw_lock);
1540 : 3764 : holders = iface_node_get_holders_L (iface);
1541 : 3764 : if (holders)
1542 : : {
1543 : 0 : G_WRITE_UNLOCK (&type_rw_lock);
1544 : 0 : g_critical ("unable to add prerequisite '%s' to interface '%s' which is already in use for '%s'",
1545 : : type_descriptive_name_I (prerequisite_type),
1546 : : type_descriptive_name_I (interface_type),
1547 : : type_descriptive_name_I (holders->instance_type));
1548 : 0 : return;
1549 : : }
1550 : 3764 : if (prerequisite_node->is_instantiatable)
1551 : : {
1552 : : guint i;
1553 : :
1554 : : /* can have at most one publicly installable instantiatable prerequisite */
1555 : 3156 : for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1556 : : {
1557 : 0 : TypeNode *prnode = lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface)[i]);
1558 : :
1559 : 0 : if (prnode->is_instantiatable)
1560 : : {
1561 : 0 : G_WRITE_UNLOCK (&type_rw_lock);
1562 : 0 : g_critical ("adding prerequisite '%s' to interface '%s' conflicts with existing prerequisite '%s'",
1563 : : type_descriptive_name_I (prerequisite_type),
1564 : : type_descriptive_name_I (interface_type),
1565 : : type_descriptive_name_I (NODE_TYPE (prnode)));
1566 : 0 : return;
1567 : : }
1568 : : }
1569 : :
1570 : 6617 : for (i = 0; i < prerequisite_node->n_supers + 1u; i++)
1571 : 3461 : type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisite_node->supers[i]));
1572 : 3156 : G_WRITE_UNLOCK (&type_rw_lock);
1573 : : }
1574 : 608 : else if (NODE_IS_IFACE (prerequisite_node))
1575 : : {
1576 : : GType *prerequisites;
1577 : : guint i;
1578 : :
1579 : 608 : prerequisites = IFACE_NODE_PREREQUISITES (prerequisite_node);
1580 : 1221 : for (i = 0; i < IFACE_NODE_N_PREREQUISITES (prerequisite_node); i++)
1581 : 613 : type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisites[i]));
1582 : 608 : type_iface_add_prerequisite_W (iface, prerequisite_node);
1583 : 608 : G_WRITE_UNLOCK (&type_rw_lock);
1584 : : }
1585 : : else
1586 : : {
1587 : 0 : G_WRITE_UNLOCK (&type_rw_lock);
1588 : 0 : g_critical ("prerequisite '%s' for interface '%s' is neither instantiatable nor interface",
1589 : : type_descriptive_name_I (prerequisite_type),
1590 : : type_descriptive_name_I (interface_type));
1591 : : }
1592 : : }
1593 : :
1594 : : /**
1595 : : * g_type_interface_prerequisites:
1596 : : * @interface_type: an interface type
1597 : : * @n_prerequisites: (out) (optional): location to return the number
1598 : : * of prerequisites, or %NULL
1599 : : *
1600 : : * Returns the prerequisites of an interfaces type.
1601 : : *
1602 : : * Since: 2.2
1603 : : *
1604 : : * Returns: (array length=n_prerequisites) (transfer full): a
1605 : : * newly-allocated zero-terminated array of #GType containing
1606 : : * the prerequisites of @interface_type
1607 : : */
1608 : : GType*
1609 : 43 : g_type_interface_prerequisites (GType interface_type,
1610 : : guint *n_prerequisites)
1611 : : {
1612 : : TypeNode *iface;
1613 : :
1614 : 43 : g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
1615 : :
1616 : 43 : iface = lookup_type_node_I (interface_type);
1617 : 43 : if (iface)
1618 : : {
1619 : : GType *types;
1620 : 43 : TypeNode *inode = NULL;
1621 : 43 : guint i, n = 0;
1622 : :
1623 : 43 : G_READ_LOCK (&type_rw_lock);
1624 : 43 : types = g_new0 (GType, IFACE_NODE_N_PREREQUISITES (iface) + 1);
1625 : 104 : for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1626 : : {
1627 : 61 : GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
1628 : 61 : TypeNode *node = lookup_type_node_I (prerequisite);
1629 : 61 : if (node->is_instantiatable)
1630 : : {
1631 : 49 : if (!inode || type_node_is_a_L (node, inode))
1632 : 49 : inode = node;
1633 : : }
1634 : : else
1635 : 12 : types[n++] = NODE_TYPE (node);
1636 : : }
1637 : 43 : if (inode)
1638 : 42 : types[n++] = NODE_TYPE (inode);
1639 : :
1640 : 43 : if (n_prerequisites)
1641 : 43 : *n_prerequisites = n;
1642 : 43 : G_READ_UNLOCK (&type_rw_lock);
1643 : :
1644 : 43 : return types;
1645 : : }
1646 : : else
1647 : : {
1648 : 0 : if (n_prerequisites)
1649 : 0 : *n_prerequisites = 0;
1650 : :
1651 : 0 : return NULL;
1652 : : }
1653 : : }
1654 : :
1655 : : /**
1656 : : * g_type_interface_instantiatable_prerequisite:
1657 : : * @interface_type: an interface type
1658 : : *
1659 : : * Returns the most specific instantiatable prerequisite of an
1660 : : * interface type. If the interface type has no instantiatable
1661 : : * prerequisite, %G_TYPE_INVALID is returned.
1662 : : *
1663 : : * See g_type_interface_add_prerequisite() for more information
1664 : : * about prerequisites.
1665 : : *
1666 : : * Returns: the instantiatable prerequisite type or %G_TYPE_INVALID if none
1667 : : *
1668 : : * Since: 2.68
1669 : : **/
1670 : : GType
1671 : 65 : g_type_interface_instantiatable_prerequisite (GType interface_type)
1672 : : {
1673 : 65 : TypeNode *inode = NULL;
1674 : : TypeNode *iface;
1675 : : guint i;
1676 : :
1677 : 65 : g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), G_TYPE_INVALID);
1678 : :
1679 : 65 : iface = lookup_type_node_I (interface_type);
1680 : 65 : if (iface == NULL)
1681 : 0 : return G_TYPE_INVALID;
1682 : :
1683 : 65 : G_READ_LOCK (&type_rw_lock);
1684 : :
1685 : 134 : for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
1686 : : {
1687 : 69 : GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
1688 : 69 : TypeNode *node = lookup_type_node_I (prerequisite);
1689 : 69 : if (node->is_instantiatable)
1690 : : {
1691 : 64 : if (!inode || type_node_is_a_L (node, inode))
1692 : 64 : inode = node;
1693 : : }
1694 : : }
1695 : :
1696 : 65 : G_READ_UNLOCK (&type_rw_lock);
1697 : :
1698 : 65 : if (inode)
1699 : 63 : return NODE_TYPE (inode);
1700 : : else
1701 : 2 : return G_TYPE_INVALID;
1702 : : }
1703 : :
1704 : : static IFaceHolder*
1705 : 8476 : type_iface_peek_holder_L (TypeNode *iface,
1706 : : GType instance_type)
1707 : : {
1708 : : IFaceHolder *iholder;
1709 : :
1710 : 8476 : g_assert (NODE_IS_IFACE (iface));
1711 : :
1712 : 8476 : iholder = iface_node_get_holders_L (iface);
1713 : 17660 : while (iholder && iholder->instance_type != instance_type)
1714 : 9184 : iholder = iholder->next;
1715 : 8476 : return iholder;
1716 : : }
1717 : :
1718 : : static IFaceHolder*
1719 : 3505 : type_iface_retrieve_holder_info_Wm (TypeNode *iface,
1720 : : GType instance_type,
1721 : : gboolean need_info)
1722 : : {
1723 : 3505 : IFaceHolder *iholder = type_iface_peek_holder_L (iface, instance_type);
1724 : :
1725 : 3505 : if (iholder && !iholder->info && need_info)
1726 : : {
1727 : : GInterfaceInfo tmp_info;
1728 : :
1729 : 2 : g_assert (iholder->plugin != NULL);
1730 : :
1731 : 2 : type_data_ref_Wm (iface);
1732 : 2 : if (iholder->info)
1733 : 0 : INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface));
1734 : :
1735 : 2 : memset (&tmp_info, 0, sizeof (tmp_info));
1736 : :
1737 : 2 : G_WRITE_UNLOCK (&type_rw_lock);
1738 : 2 : g_type_plugin_use (iholder->plugin);
1739 : 2 : g_type_plugin_complete_interface_info (iholder->plugin, instance_type, NODE_TYPE (iface), &tmp_info);
1740 : 2 : G_WRITE_LOCK (&type_rw_lock);
1741 : 2 : if (iholder->info)
1742 : 0 : INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
1743 : :
1744 : 2 : check_interface_info_I (iface, instance_type, &tmp_info);
1745 : 2 : iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info));
1746 : : }
1747 : :
1748 : 3505 : return iholder; /* we don't modify write lock upon returning NULL */
1749 : : }
1750 : :
1751 : : static void
1752 : 2 : maybe_issue_deprecation_warning (GType type)
1753 : : {
1754 : : static GHashTable *already_warned_table;
1755 : : static const gchar *enable_diagnostic;
1756 : : static GMutex already_warned_lock;
1757 : : gboolean already;
1758 : : const char *name;
1759 : :
1760 : 2 : if (g_once_init_enter_pointer (&enable_diagnostic))
1761 : : {
1762 : 1 : const gchar *value = g_getenv ("G_ENABLE_DIAGNOSTIC");
1763 : :
1764 : 1 : if (!value)
1765 : 0 : value = "0";
1766 : :
1767 : 1 : g_once_init_leave_pointer (&enable_diagnostic, value);
1768 : : }
1769 : :
1770 : 2 : if (enable_diagnostic[0] == '0')
1771 : 0 : return;
1772 : :
1773 : 2 : g_mutex_lock (&already_warned_lock);
1774 : :
1775 : 2 : if (already_warned_table == NULL)
1776 : 1 : already_warned_table = g_hash_table_new (NULL, NULL);
1777 : :
1778 : 2 : name = g_type_name (type);
1779 : :
1780 : 2 : already = g_hash_table_contains (already_warned_table, (gpointer) name);
1781 : 2 : if (!already)
1782 : 1 : g_hash_table_add (already_warned_table, (gpointer) name);
1783 : :
1784 : 2 : g_mutex_unlock (&already_warned_lock);
1785 : :
1786 : 2 : if (!already)
1787 : 1 : g_warning ("The type %s is deprecated and shouldnāt be used "
1788 : : "any more. It may be removed in a future version.",
1789 : : name);
1790 : : }
1791 : :
1792 : : /**
1793 : : * g_type_create_instance: (skip)
1794 : : * @type: an instantiatable type to create an instance for
1795 : : *
1796 : : * Creates and initializes an instance of @type if @type is valid and
1797 : : * can be instantiated. The type system only performs basic allocation
1798 : : * and structure setups for instances: actual instance creation should
1799 : : * happen through functions supplied by the type's fundamental type
1800 : : * implementation. So use of g_type_create_instance() is reserved for
1801 : : * implementers of fundamental types only. E.g. instances of the
1802 : : * #GObject hierarchy should be created via g_object_new() and never
1803 : : * directly through g_type_create_instance() which doesn't handle things
1804 : : * like singleton objects or object construction.
1805 : : *
1806 : : * The extended members of the returned instance are guaranteed to be filled
1807 : : * with zeros.
1808 : : *
1809 : : * Note: Do not use this function, unless you're implementing a
1810 : : * fundamental type. Also language bindings should not use this
1811 : : * function, but g_object_new() instead.
1812 : : *
1813 : : * Returns: an allocated and initialized instance, subject to further
1814 : : * treatment by the fundamental type implementation
1815 : : */
1816 : : GTypeInstance*
1817 : 7916909 : g_type_create_instance (GType type)
1818 : : {
1819 : : TypeNode *node;
1820 : : GTypeInstance *instance;
1821 : : GTypeClass *class;
1822 : : gchar *allocated;
1823 : : size_t private_size;
1824 : : size_t ivar_size;
1825 : : guint i;
1826 : :
1827 : 7916909 : node = lookup_type_node_I (type);
1828 : 7916909 : if (G_UNLIKELY (!node || !node->is_instantiatable))
1829 : : {
1830 : 0 : g_error ("cannot create new instance of invalid (non-instantiatable) type '%s'",
1831 : : type_descriptive_name_I (type));
1832 : : }
1833 : : /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1834 : 7916909 : if (G_UNLIKELY (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (type)))
1835 : : {
1836 : 0 : g_error ("cannot create instance of abstract (non-instantiatable) type '%s'",
1837 : : type_descriptive_name_I (type));
1838 : : }
1839 : 7916909 : if (G_UNLIKELY (G_TYPE_IS_DEPRECATED (type)))
1840 : : {
1841 : 2 : maybe_issue_deprecation_warning (type);
1842 : : }
1843 : :
1844 : 7916909 : class = g_type_class_get (type);
1845 : :
1846 : : /* We allocate the 'private' areas before the normal instance data, in
1847 : : * reverse order. This allows the private area of a particular class
1848 : : * to always be at a constant relative address to the instance data.
1849 : : * If we stored the private data after the instance data this would
1850 : : * not be the case (since a subclass that added more instance
1851 : : * variables would push the private data further along).
1852 : : *
1853 : : * This presents problems for valgrindability, of course, so we do a
1854 : : * workaround for that case. We identify the start of the object to
1855 : : * valgrind as an allocated block (so that pointers to objects show up
1856 : : * as 'reachable' instead of 'possibly lost'). We then add an extra
1857 : : * pointer at the end of the object, after all instance data, back to
1858 : : * the start of the private area so that it is also recorded as
1859 : : * reachable. We also add extra private space at the start because
1860 : : * valgrind doesn't seem to like us claiming to have allocated an
1861 : : * address that it saw allocated by malloc().
1862 : : */
1863 : 7916909 : private_size = node->data->instance.private_size;
1864 : 7916909 : ivar_size = node->data->instance.instance_size;
1865 : :
1866 : : #ifdef ENABLE_VALGRIND
1867 : 7916909 : if (G_UNLIKELY (private_size && RUNNING_ON_VALGRIND))
1868 : : {
1869 : 0 : private_size += ALIGN_STRUCT (1);
1870 : :
1871 : : /* Allocate one extra pointer size... */
1872 : 0 : allocated = g_malloc0 (private_size + ivar_size + sizeof (gpointer));
1873 : : /* ... and point it back to the start of the private data. */
1874 : 0 : *(gpointer *) (allocated + private_size + ivar_size) = allocated + ALIGN_STRUCT (1);
1875 : :
1876 : : /* Tell valgrind that it should treat the object itself as such */
1877 : 0 : VALGRIND_MALLOCLIKE_BLOCK (allocated + private_size, ivar_size + sizeof (gpointer), 0, TRUE);
1878 : 0 : VALGRIND_MALLOCLIKE_BLOCK (allocated + ALIGN_STRUCT (1), private_size - ALIGN_STRUCT (1), 0, TRUE);
1879 : : }
1880 : : else
1881 : : #endif
1882 : 7916909 : allocated = g_malloc0 (private_size + ivar_size);
1883 : :
1884 : 7916909 : instance = (GTypeInstance *) (allocated + private_size);
1885 : :
1886 : 17725094 : for (i = node->n_supers; i > 0; i--)
1887 : : {
1888 : : TypeNode *pnode;
1889 : :
1890 : 9808185 : pnode = lookup_type_node_I (node->supers[i]);
1891 : 9808185 : if (pnode->data->instance.instance_init)
1892 : : {
1893 : 9806335 : instance->g_class = pnode->data->instance.class;
1894 : 9806335 : pnode->data->instance.instance_init (instance, class);
1895 : : }
1896 : : }
1897 : :
1898 : 7916909 : instance->g_class = class;
1899 : 7916909 : if (node->data->instance.instance_init)
1900 : 7911285 : node->data->instance.instance_init (instance, class);
1901 : :
1902 : : #ifdef G_ENABLE_DEBUG
1903 : 7916909 : IF_DEBUG (INSTANCE_COUNT)
1904 : : {
1905 : 0 : g_atomic_int_inc ((int *) &node->instance_count);
1906 : : }
1907 : : #endif
1908 : :
1909 : 7916909 : TRACE (GOBJECT_OBJECT_NEW (instance, (uintmax_t) type));
1910 : :
1911 : 7916909 : return instance;
1912 : : }
1913 : :
1914 : : /**
1915 : : * g_type_free_instance:
1916 : : * @instance: an instance of a type
1917 : : *
1918 : : * Frees an instance of a type, returning it to the instance pool for
1919 : : * the type, if there is one.
1920 : : *
1921 : : * Like g_type_create_instance(), this function is reserved for
1922 : : * implementors of fundamental types.
1923 : : */
1924 : : void
1925 : 7901873 : g_type_free_instance (GTypeInstance *instance)
1926 : : {
1927 : : TypeNode *node;
1928 : : GTypeClass *class;
1929 : : gchar *allocated;
1930 : : size_t private_size;
1931 : : size_t ivar_size;
1932 : :
1933 : 7901873 : g_return_if_fail (instance != NULL && instance->g_class != NULL);
1934 : :
1935 : 7901873 : class = instance->g_class;
1936 : 7901873 : node = lookup_type_node_I (class->g_type);
1937 : 7901873 : if (G_UNLIKELY (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class))
1938 : : {
1939 : 0 : g_critical ("cannot free instance of invalid (non-instantiatable) type '%s'",
1940 : : type_descriptive_name_I (class->g_type));
1941 : 0 : return;
1942 : : }
1943 : : /* G_TYPE_IS_ABSTRACT() is an external call: _U */
1944 : 7901873 : if (G_UNLIKELY (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (NODE_TYPE (node))))
1945 : : {
1946 : 0 : g_critical ("cannot free instance of abstract (non-instantiatable) type '%s'",
1947 : : NODE_NAME (node));
1948 : 0 : return;
1949 : : }
1950 : :
1951 : 7901873 : instance->g_class = NULL;
1952 : 7901873 : private_size = node->data->instance.private_size;
1953 : 7901873 : ivar_size = node->data->instance.instance_size;
1954 : 7901873 : allocated = ((gchar *) instance) - private_size;
1955 : :
1956 : : #ifdef G_ENABLE_DEBUG
1957 : 7901873 : memset (allocated, 0xaa, ivar_size + private_size);
1958 : : #endif
1959 : :
1960 : : #ifdef ENABLE_VALGRIND
1961 : : /* See comment in g_type_create_instance() about what's going on here.
1962 : : * We're basically unwinding what we put into motion there.
1963 : : */
1964 : 7901873 : if (G_UNLIKELY (private_size && RUNNING_ON_VALGRIND))
1965 : : {
1966 : 0 : private_size += ALIGN_STRUCT (1);
1967 : 0 : allocated -= ALIGN_STRUCT (1);
1968 : :
1969 : : /* Clear out the extra pointer... */
1970 : 0 : *(gpointer *) (allocated + private_size + ivar_size) = NULL;
1971 : : /* ... and ensure we include it in the size we free. */
1972 : 0 : g_free_sized (allocated, private_size + ivar_size + sizeof (gpointer));
1973 : :
1974 : 0 : VALGRIND_FREELIKE_BLOCK (allocated + ALIGN_STRUCT (1), 0);
1975 : 0 : VALGRIND_FREELIKE_BLOCK (instance, 0);
1976 : : }
1977 : : else
1978 : : #endif
1979 : 7901873 : g_free_sized (allocated, private_size + ivar_size);
1980 : :
1981 : : #ifdef G_ENABLE_DEBUG
1982 : 7901873 : IF_DEBUG (INSTANCE_COUNT)
1983 : : {
1984 : 0 : g_atomic_int_add ((int *) &node->instance_count, -1);
1985 : : }
1986 : : #endif
1987 : : }
1988 : :
1989 : : static void
1990 : 3215 : type_iface_ensure_dflt_vtable_Wm (TypeNode *iface)
1991 : : {
1992 : 3215 : g_assert (iface->data);
1993 : :
1994 : 3215 : if (!iface->data->iface.dflt_vtable)
1995 : : {
1996 : 1799 : GTypeInterface *vtable = g_malloc0 (iface->data->iface.vtable_size);
1997 : 1799 : iface->data->iface.dflt_vtable = vtable;
1998 : 1799 : vtable->g_type = NODE_TYPE (iface);
1999 : 1799 : vtable->g_instance_type = 0;
2000 : 1799 : if (iface->data->iface.vtable_init_base ||
2001 : 1797 : iface->data->iface.dflt_init)
2002 : : {
2003 : 1780 : G_WRITE_UNLOCK (&type_rw_lock);
2004 : 1780 : if (iface->data->iface.vtable_init_base)
2005 : 2 : iface->data->iface.vtable_init_base (vtable);
2006 : 1780 : if (iface->data->iface.dflt_init)
2007 : 1779 : iface->data->iface.dflt_init (vtable, (gpointer) iface->data->iface.dflt_data);
2008 : 1780 : G_WRITE_LOCK (&type_rw_lock);
2009 : : }
2010 : : }
2011 : 3215 : }
2012 : :
2013 : :
2014 : : /* This is called to allocate and do the first part of initializing
2015 : : * the interface vtable; type_iface_vtable_iface_init_Wm() does the remainder.
2016 : : *
2017 : : * A FALSE return indicates that we didn't find an init function for
2018 : : * this type/iface pair, so the vtable from the parent type should
2019 : : * be used. Note that the write lock is not modified upon a FALSE
2020 : : * return.
2021 : : */
2022 : : static gboolean
2023 : 3505 : type_iface_vtable_base_init_Wm (TypeNode *iface,
2024 : : TypeNode *node)
2025 : : {
2026 : : IFaceEntry *entry;
2027 : : IFaceHolder *iholder;
2028 : 3505 : GTypeInterface *vtable = NULL;
2029 : : TypeNode *pnode;
2030 : :
2031 : : /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
2032 : 3505 : iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), TRUE);
2033 : 3505 : if (!iholder)
2034 : 329 : return FALSE; /* we don't modify write lock upon FALSE */
2035 : :
2036 : 3176 : type_iface_ensure_dflt_vtable_Wm (iface);
2037 : :
2038 : 3176 : entry = type_lookup_iface_entry_L (node, iface);
2039 : :
2040 : 3176 : g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
2041 : :
2042 : 3176 : entry->init_state = IFACE_INIT;
2043 : :
2044 : 3176 : pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
2045 : 3176 : if (pnode) /* want to copy over parent iface contents */
2046 : : {
2047 : 3176 : IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
2048 : :
2049 : 3176 : if (pentry)
2050 : 283 : vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size);
2051 : : }
2052 : 3176 : if (!vtable)
2053 : 2893 : vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
2054 : 3176 : entry->vtable = vtable;
2055 : 3176 : vtable->g_type = NODE_TYPE (iface);
2056 : 3176 : vtable->g_instance_type = NODE_TYPE (node);
2057 : :
2058 : 3176 : if (iface->data->iface.vtable_init_base)
2059 : : {
2060 : 3 : G_WRITE_UNLOCK (&type_rw_lock);
2061 : 3 : iface->data->iface.vtable_init_base (vtable);
2062 : 3 : G_WRITE_LOCK (&type_rw_lock);
2063 : : }
2064 : 3176 : return TRUE; /* initialized the vtable */
2065 : : }
2066 : :
2067 : : /* Finishes what type_iface_vtable_base_init_Wm started by
2068 : : * calling the interface init function.
2069 : : * this function may only be called for types with their
2070 : : * own interface holder info, i.e. types for which
2071 : : * g_type_add_interface*() was called and not children thereof.
2072 : : */
2073 : : static void
2074 : 3176 : type_iface_vtable_iface_init_Wm (TypeNode *iface,
2075 : : TypeNode *node)
2076 : : {
2077 : 3176 : IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
2078 : 3176 : IFaceHolder *iholder = type_iface_peek_holder_L (iface, NODE_TYPE (node));
2079 : 3176 : GTypeInterface *vtable = NULL;
2080 : : guint i;
2081 : :
2082 : : /* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */
2083 : 3176 : g_assert (iface->data && entry && iholder && iholder->info);
2084 : 3176 : g_assert (entry->init_state == IFACE_INIT); /* assert prior base_init() */
2085 : :
2086 : 3176 : entry->init_state = INITIALIZED;
2087 : :
2088 : 3176 : vtable = entry->vtable;
2089 : :
2090 : 3176 : if (iholder->info->interface_init)
2091 : : {
2092 : 3162 : G_WRITE_UNLOCK (&type_rw_lock);
2093 : 3162 : if (iholder->info->interface_init)
2094 : 3162 : iholder->info->interface_init (vtable, iholder->info->interface_data);
2095 : 3162 : G_WRITE_LOCK (&type_rw_lock);
2096 : : }
2097 : :
2098 : 6353 : for (i = 0; i < static_n_iface_check_funcs; i++)
2099 : : {
2100 : 3177 : GTypeInterfaceCheckFunc check_func = static_iface_check_funcs[i].check_func;
2101 : 3177 : gpointer check_data = static_iface_check_funcs[i].check_data;
2102 : :
2103 : 3177 : G_WRITE_UNLOCK (&type_rw_lock);
2104 : 3177 : check_func (check_data, (gpointer)vtable);
2105 : 3177 : G_WRITE_LOCK (&type_rw_lock);
2106 : : }
2107 : 3176 : }
2108 : :
2109 : : static void
2110 : 20512 : type_class_init_Wm (TypeNode *node,
2111 : : GTypeClass *pclass)
2112 : : {
2113 : 20512 : GSList *slist, *init_slist = NULL;
2114 : : GTypeClass *class;
2115 : : IFaceEntries *entries;
2116 : : IFaceEntry *entry;
2117 : : TypeNode *bnode, *pnode;
2118 : : guint i;
2119 : :
2120 : : /* Accessing data->class will work for instantiatable types
2121 : : * too because ClassData is a subset of InstanceData
2122 : : */
2123 : 20512 : g_assert (node->is_classed && node->data &&
2124 : : node->data->class.class_size &&
2125 : : !node->data->class.class &&
2126 : : g_atomic_int_get (&node->data->class.init_state) == UNINITIALIZED);
2127 : 20512 : if (node->data->class.class_private_size)
2128 : 1 : class = g_malloc0 (ALIGN_STRUCT (node->data->class.class_size) + node->data->class.class_private_size);
2129 : : else
2130 : 20511 : class = g_malloc0 (node->data->class.class_size);
2131 : 20512 : node->data->class.class = class;
2132 : 20512 : g_atomic_int_set (&node->data->class.init_state, BASE_CLASS_INIT);
2133 : :
2134 : 20512 : if (pclass)
2135 : : {
2136 : 19197 : pnode = lookup_type_node_I (pclass->g_type);
2137 : :
2138 : 19197 : memcpy (class, pclass, pnode->data->class.class_size);
2139 : 19197 : memcpy (G_STRUCT_MEMBER_P (class, ALIGN_STRUCT (node->data->class.class_size)), G_STRUCT_MEMBER_P (pclass, ALIGN_STRUCT (pnode->data->class.class_size)), pnode->data->class.class_private_size);
2140 : :
2141 : 19197 : if (node->is_instantiatable)
2142 : : {
2143 : : /* We need to initialize the private_size here rather than in
2144 : : * type_data_make_W() since the class init for the parent
2145 : : * class may have changed pnode->data->instance.private_size.
2146 : : */
2147 : 17521 : node->data->instance.private_size = pnode->data->instance.private_size;
2148 : : }
2149 : : }
2150 : 20512 : class->g_type = NODE_TYPE (node);
2151 : :
2152 : 20512 : G_WRITE_UNLOCK (&type_rw_lock);
2153 : :
2154 : : /* stack all base class initialization functions, so we
2155 : : * call them in ascending order.
2156 : : */
2157 : 63445 : for (bnode = node; bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
2158 : 42933 : if (bnode->data->class.class_init_base)
2159 : 18397 : init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
2160 : 38909 : for (slist = init_slist; slist; slist = slist->next)
2161 : : {
2162 : 18397 : GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
2163 : :
2164 : 18397 : class_init_base (class);
2165 : : }
2166 : 20512 : g_slist_free (init_slist);
2167 : :
2168 : 20512 : G_WRITE_LOCK (&type_rw_lock);
2169 : :
2170 : 20512 : g_atomic_int_set (&node->data->class.init_state, BASE_IFACE_INIT);
2171 : :
2172 : : /* Before we initialize the class, base initialize all interfaces, either
2173 : : * from parent, or through our holder info
2174 : : */
2175 : 20512 : pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
2176 : :
2177 : 20512 : i = 0;
2178 : 24017 : while ((entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node)) != NULL &&
2179 : 5739 : i < IFACE_ENTRIES_N_ENTRIES (entries))
2180 : : {
2181 : 3505 : entry = &entries->entry[i];
2182 : 3505 : while (i < IFACE_ENTRIES_N_ENTRIES (entries) &&
2183 : 3505 : entry->init_state == IFACE_INIT)
2184 : : {
2185 : 0 : entry++;
2186 : 0 : i++;
2187 : : }
2188 : :
2189 : 3505 : if (i == IFACE_ENTRIES_N_ENTRIES (entries))
2190 : 0 : break;
2191 : :
2192 : 3505 : if (!type_iface_vtable_base_init_Wm (lookup_type_node_I (entry->iface_type), node))
2193 : : {
2194 : : guint j;
2195 : 329 : IFaceEntries *pentries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (pnode);
2196 : :
2197 : : /* need to get this interface from parent, type_iface_vtable_base_init_Wm()
2198 : : * doesn't modify write lock upon FALSE, so entry is still valid;
2199 : : */
2200 : 329 : g_assert (pnode != NULL);
2201 : :
2202 : 329 : if (pentries)
2203 : 423 : for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (pentries); j++)
2204 : : {
2205 : 423 : IFaceEntry *pentry = &pentries->entry[j];
2206 : :
2207 : 423 : if (pentry->iface_type == entry->iface_type)
2208 : : {
2209 : 329 : entry->vtable = pentry->vtable;
2210 : 329 : entry->init_state = INITIALIZED;
2211 : 329 : break;
2212 : : }
2213 : : }
2214 : 329 : g_assert (entry->vtable != NULL);
2215 : : }
2216 : :
2217 : : /* If the write lock was released, additional interface entries might
2218 : : * have been inserted into CLASSED_NODE_IFACES_ENTRIES (node); they'll
2219 : : * be base-initialized when inserted, so we don't have to worry that
2220 : : * we might miss them. Uninitialized entries can only be moved higher
2221 : : * when new ones are inserted.
2222 : : */
2223 : 3505 : i++;
2224 : : }
2225 : :
2226 : 20512 : g_atomic_int_set (&node->data->class.init_state, CLASS_INIT);
2227 : :
2228 : 20512 : G_WRITE_UNLOCK (&type_rw_lock);
2229 : :
2230 : 20512 : if (node->data->class.class_init)
2231 : 20167 : node->data->class.class_init (class, (gpointer) node->data->class.class_data);
2232 : :
2233 : 20512 : G_WRITE_LOCK (&type_rw_lock);
2234 : :
2235 : 20512 : g_atomic_int_set (&node->data->class.init_state, IFACE_INIT);
2236 : :
2237 : : /* finish initializing the interfaces through our holder info.
2238 : : * inherited interfaces are already init_state == INITIALIZED, because
2239 : : * they either got setup in the above base_init loop, or during
2240 : : * class_init from within type_add_interface_Wm() for this or
2241 : : * an ancestor type.
2242 : : */
2243 : 20512 : i = 0;
2244 : 23688 : while ((entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node)) != NULL)
2245 : : {
2246 : 5410 : entry = &entries->entry[i];
2247 : 5739 : while (i < IFACE_ENTRIES_N_ENTRIES (entries) &&
2248 : 3505 : entry->init_state == INITIALIZED)
2249 : : {
2250 : 329 : entry++;
2251 : 329 : i++;
2252 : : }
2253 : :
2254 : 5410 : if (i == IFACE_ENTRIES_N_ENTRIES (entries))
2255 : 2234 : break;
2256 : :
2257 : 3176 : type_iface_vtable_iface_init_Wm (lookup_type_node_I (entry->iface_type), node);
2258 : :
2259 : : /* As in the loop above, additional initialized entries might be inserted
2260 : : * if the write lock is released, but that's harmless because the entries
2261 : : * we need to initialize only move higher in the list.
2262 : : */
2263 : 3176 : i++;
2264 : : }
2265 : :
2266 : 20512 : g_atomic_int_set (&node->data->class.init_state, INITIALIZED);
2267 : 20512 : }
2268 : :
2269 : : /**
2270 : : * g_type_add_class_cache_func: (skip)
2271 : : * @cache_data: data to be passed to @cache_func
2272 : : * @cache_func: a #GTypeClassCacheFunc
2273 : : *
2274 : : * Adds a #GTypeClassCacheFunc to be called before the reference count of a
2275 : : * class goes from one to zero. This can be used to prevent premature class
2276 : : * destruction. All installed #GTypeClassCacheFunc functions will be chained
2277 : : * until one of them returns %TRUE. The functions have to check the class id
2278 : : * passed in to figure whether they actually want to cache the class of this
2279 : : * type, since all classes are routed through the same #GTypeClassCacheFunc
2280 : : * chain.
2281 : : */
2282 : : void
2283 : 0 : g_type_add_class_cache_func (gpointer cache_data,
2284 : : GTypeClassCacheFunc cache_func)
2285 : : {
2286 : : guint i;
2287 : :
2288 : 0 : g_return_if_fail (cache_func != NULL);
2289 : :
2290 : 0 : G_WRITE_LOCK (&type_rw_lock);
2291 : 0 : i = static_n_class_cache_funcs++;
2292 : 0 : static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
2293 : 0 : static_class_cache_funcs[i].cache_data = cache_data;
2294 : 0 : static_class_cache_funcs[i].cache_func = cache_func;
2295 : 0 : G_WRITE_UNLOCK (&type_rw_lock);
2296 : : }
2297 : :
2298 : : /**
2299 : : * g_type_remove_class_cache_func: (skip)
2300 : : * @cache_data: data that was given when adding @cache_func
2301 : : * @cache_func: a #GTypeClassCacheFunc
2302 : : *
2303 : : * Removes a previously installed #GTypeClassCacheFunc. The cache
2304 : : * maintained by @cache_func has to be empty when calling
2305 : : * g_type_remove_class_cache_func() to avoid leaks.
2306 : : */
2307 : : void
2308 : 0 : g_type_remove_class_cache_func (gpointer cache_data,
2309 : : GTypeClassCacheFunc cache_func)
2310 : : {
2311 : 0 : gboolean found_it = FALSE;
2312 : : guint i;
2313 : :
2314 : 0 : g_return_if_fail (cache_func != NULL);
2315 : :
2316 : 0 : G_WRITE_LOCK (&type_rw_lock);
2317 : 0 : for (i = 0; i < static_n_class_cache_funcs; i++)
2318 : 0 : if (static_class_cache_funcs[i].cache_data == cache_data &&
2319 : 0 : static_class_cache_funcs[i].cache_func == cache_func)
2320 : : {
2321 : 0 : static_n_class_cache_funcs--;
2322 : 0 : memmove (static_class_cache_funcs + i,
2323 : 0 : static_class_cache_funcs + i + 1,
2324 : 0 : sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
2325 : 0 : static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
2326 : 0 : found_it = TRUE;
2327 : 0 : break;
2328 : : }
2329 : 0 : G_WRITE_UNLOCK (&type_rw_lock);
2330 : :
2331 : 0 : if (!found_it)
2332 : 0 : g_critical (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
2333 : : cache_func, cache_data);
2334 : : }
2335 : :
2336 : :
2337 : : /**
2338 : : * g_type_add_interface_check: (skip)
2339 : : * @check_data: data to pass to @check_func
2340 : : * @check_func: function to be called after each interface
2341 : : * is initialized
2342 : : *
2343 : : * Adds a function to be called after an interface vtable is
2344 : : * initialized for any class (i.e. after the @interface_init
2345 : : * member of #GInterfaceInfo has been called).
2346 : : *
2347 : : * This function is useful when you want to check an invariant
2348 : : * that depends on the interfaces of a class. For instance, the
2349 : : * implementation of #GObject uses this facility to check that an
2350 : : * object implements all of the properties that are defined on its
2351 : : * interfaces.
2352 : : *
2353 : : * Since: 2.4
2354 : : */
2355 : : void
2356 : 374 : g_type_add_interface_check (gpointer check_data,
2357 : : GTypeInterfaceCheckFunc check_func)
2358 : : {
2359 : : guint i;
2360 : :
2361 : 374 : g_return_if_fail (check_func != NULL);
2362 : :
2363 : 374 : G_WRITE_LOCK (&type_rw_lock);
2364 : 374 : i = static_n_iface_check_funcs++;
2365 : 374 : static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
2366 : 374 : static_iface_check_funcs[i].check_data = check_data;
2367 : 374 : static_iface_check_funcs[i].check_func = check_func;
2368 : 374 : G_WRITE_UNLOCK (&type_rw_lock);
2369 : : }
2370 : :
2371 : : /**
2372 : : * g_type_remove_interface_check: (skip)
2373 : : * @check_data: callback data passed to g_type_add_interface_check()
2374 : : * @check_func: callback function passed to g_type_add_interface_check()
2375 : : *
2376 : : * Removes an interface check function added with
2377 : : * g_type_add_interface_check().
2378 : : *
2379 : : * Since: 2.4
2380 : : */
2381 : : void
2382 : 1 : g_type_remove_interface_check (gpointer check_data,
2383 : : GTypeInterfaceCheckFunc check_func)
2384 : : {
2385 : 1 : gboolean found_it = FALSE;
2386 : : guint i;
2387 : :
2388 : 1 : g_return_if_fail (check_func != NULL);
2389 : :
2390 : 1 : G_WRITE_LOCK (&type_rw_lock);
2391 : 1 : for (i = 0; i < static_n_iface_check_funcs; i++)
2392 : 1 : if (static_iface_check_funcs[i].check_data == check_data &&
2393 : 1 : static_iface_check_funcs[i].check_func == check_func)
2394 : : {
2395 : 1 : static_n_iface_check_funcs--;
2396 : 1 : memmove (static_iface_check_funcs + i,
2397 : 1 : static_iface_check_funcs + i + 1,
2398 : 1 : sizeof (static_iface_check_funcs[0]) * (static_n_iface_check_funcs - i));
2399 : 1 : static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs);
2400 : 1 : found_it = TRUE;
2401 : 1 : break;
2402 : : }
2403 : 1 : G_WRITE_UNLOCK (&type_rw_lock);
2404 : :
2405 : 1 : if (!found_it)
2406 : 0 : g_critical (G_STRLOC ": cannot remove unregistered class check func %p with data %p",
2407 : : check_func, check_data);
2408 : : }
2409 : :
2410 : : /* --- type registration --- */
2411 : : /**
2412 : : * g_type_register_fundamental:
2413 : : * @type_id: a predefined type identifier
2414 : : * @type_name: 0-terminated string used as the name of the new type
2415 : : * @info: #GTypeInfo structure for this type
2416 : : * @finfo: #GTypeFundamentalInfo structure for this type
2417 : : * @flags: bitwise combination of #GTypeFlags values
2418 : : *
2419 : : * Registers @type_id as the predefined identifier and @type_name as the
2420 : : * name of a fundamental type. If @type_id is already registered, or a
2421 : : * type named @type_name is already registered, the behaviour is undefined.
2422 : : * The type system uses the information contained in the #GTypeInfo structure
2423 : : * pointed to by @info and the #GTypeFundamentalInfo structure pointed to by
2424 : : * @finfo to manage the type and its instances. The value of @flags determines
2425 : : * additional characteristics of the fundamental type.
2426 : : *
2427 : : * Returns: the predefined type identifier
2428 : : */
2429 : : GType
2430 : 11185 : g_type_register_fundamental (GType type_id,
2431 : : const gchar *type_name,
2432 : : const GTypeInfo *info,
2433 : : const GTypeFundamentalInfo *finfo,
2434 : : GTypeFlags flags)
2435 : : {
2436 : : TypeNode *node;
2437 : :
2438 : 11185 : g_assert_type_system_initialized ();
2439 : 11185 : g_return_val_if_fail (type_id > 0, 0);
2440 : 11185 : g_return_val_if_fail (type_name != NULL, 0);
2441 : 11185 : g_return_val_if_fail (info != NULL, 0);
2442 : 11185 : g_return_val_if_fail (finfo != NULL, 0);
2443 : :
2444 : 11185 : if (!check_type_name_I (type_name))
2445 : 0 : return 0;
2446 : 11185 : if ((type_id & TYPE_ID_MASK) ||
2447 : : type_id > G_TYPE_FUNDAMENTAL_MAX)
2448 : : {
2449 : 0 : g_critical ("attempt to register fundamental type '%s' with invalid type id (%" G_GUINTPTR_FORMAT ")",
2450 : : type_name,
2451 : : (guintptr) type_id);
2452 : 0 : return 0;
2453 : : }
2454 : 11185 : if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
2455 : 1187 : !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
2456 : : {
2457 : 0 : g_critical ("cannot register instantiatable fundamental type '%s' as non-classed",
2458 : : type_name);
2459 : 0 : return 0;
2460 : : }
2461 : 11185 : if (lookup_type_node_I (type_id))
2462 : : {
2463 : 0 : g_critical ("cannot register existing fundamental type '%s' (as '%s')",
2464 : : type_descriptive_name_I (type_id),
2465 : : type_name);
2466 : 0 : return 0;
2467 : : }
2468 : :
2469 : 11185 : G_WRITE_LOCK (&type_rw_lock);
2470 : 11185 : node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
2471 : 11185 : type_add_flags_W (node, flags);
2472 : :
2473 : 11185 : if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info))
2474 : 11185 : type_data_make_W (node, info,
2475 : 11185 : check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
2476 : 11185 : G_WRITE_UNLOCK (&type_rw_lock);
2477 : :
2478 : 11185 : return NODE_TYPE (node);
2479 : : }
2480 : :
2481 : : /**
2482 : : * g_type_register_static_simple: (skip)
2483 : : * @parent_type: type from which this type will be derived
2484 : : * @type_name: 0-terminated string used as the name of the new type
2485 : : * @class_size: size of the class structure (see #GTypeInfo)
2486 : : * @class_init: location of the class initialization function (see #GTypeInfo)
2487 : : * @instance_size: size of the instance structure (see #GTypeInfo)
2488 : : * @instance_init: location of the instance initialization function (see #GTypeInfo)
2489 : : * @flags: bitwise combination of #GTypeFlags values
2490 : : *
2491 : : * Registers @type_name as the name of a new static type derived from
2492 : : * @parent_type. The value of @flags determines the nature (e.g.
2493 : : * abstract or not) of the type. It works by filling a #GTypeInfo
2494 : : * struct and calling g_type_register_static().
2495 : : *
2496 : : * Since: 2.12
2497 : : *
2498 : : * Returns: the new type identifier
2499 : : */
2500 : : GType
2501 : 13987 : g_type_register_static_simple (GType parent_type,
2502 : : const gchar *type_name,
2503 : : guint class_size,
2504 : : GClassInitFunc class_init,
2505 : : guint instance_size,
2506 : : GInstanceInitFunc instance_init,
2507 : : GTypeFlags flags)
2508 : : {
2509 : : GTypeInfo info;
2510 : :
2511 : : /* Instances are not allowed to be larger than this. If you have a big
2512 : : * fixed-length array or something, point to it instead.
2513 : : */
2514 : 13987 : g_return_val_if_fail (class_size <= G_MAXUINT16, G_TYPE_INVALID);
2515 : 13987 : g_return_val_if_fail (instance_size <= G_MAXUINT16, G_TYPE_INVALID);
2516 : :
2517 : 13987 : info.class_size = class_size;
2518 : 13987 : info.base_init = NULL;
2519 : 13987 : info.base_finalize = NULL;
2520 : 13987 : info.class_init = class_init;
2521 : 13987 : info.class_finalize = NULL;
2522 : 13987 : info.class_data = NULL;
2523 : 13987 : info.instance_size = instance_size;
2524 : 13987 : info.n_preallocs = 0;
2525 : 13987 : info.instance_init = instance_init;
2526 : 13987 : info.value_table = NULL;
2527 : :
2528 : 13987 : return g_type_register_static (parent_type, type_name, &info, flags);
2529 : : }
2530 : :
2531 : : /**
2532 : : * g_type_register_static:
2533 : : * @parent_type: type from which this type will be derived
2534 : : * @type_name: 0-terminated string used as the name of the new type
2535 : : * @info: #GTypeInfo structure for this type
2536 : : * @flags: bitwise combination of #GTypeFlags values
2537 : : *
2538 : : * Registers @type_name as the name of a new static type derived from
2539 : : * @parent_type. The type system uses the information contained in the
2540 : : * #GTypeInfo structure pointed to by @info to manage the type and its
2541 : : * instances (if not abstract). The value of @flags determines the nature
2542 : : * (e.g. abstract or not) of the type.
2543 : : *
2544 : : * Returns: the new type identifier
2545 : : */
2546 : : GType
2547 : 32309 : g_type_register_static (GType parent_type,
2548 : : const gchar *type_name,
2549 : : const GTypeInfo *info,
2550 : : GTypeFlags flags)
2551 : : {
2552 : : TypeNode *pnode, *node;
2553 : 32309 : GType type = 0;
2554 : :
2555 : 32309 : g_assert_type_system_initialized ();
2556 : 32309 : g_return_val_if_fail (parent_type > 0, 0);
2557 : 32309 : g_return_val_if_fail (type_name != NULL, 0);
2558 : 32309 : g_return_val_if_fail (info != NULL, 0);
2559 : :
2560 : 64618 : if (!check_type_name_I (type_name) ||
2561 : 32309 : !check_derivation_I (parent_type, type_name))
2562 : 1 : return 0;
2563 : 32308 : if (info->class_finalize)
2564 : : {
2565 : 0 : g_critical ("class finalizer specified for static type '%s'",
2566 : : type_name);
2567 : 0 : return 0;
2568 : : }
2569 : :
2570 : 32308 : pnode = lookup_type_node_I (parent_type);
2571 : 32308 : G_WRITE_LOCK (&type_rw_lock);
2572 : 32308 : type_data_ref_Wm (pnode);
2573 : 32308 : if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info))
2574 : : {
2575 : 32308 : node = type_node_new_W (pnode, type_name, NULL);
2576 : 32308 : type_add_flags_W (node, flags);
2577 : 32308 : type = NODE_TYPE (node);
2578 : 32308 : type_data_make_W (node, info,
2579 : 32308 : check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
2580 : : }
2581 : 32308 : G_WRITE_UNLOCK (&type_rw_lock);
2582 : :
2583 : 32308 : return type;
2584 : : }
2585 : :
2586 : : /**
2587 : : * g_type_register_dynamic:
2588 : : * @parent_type: type from which this type will be derived
2589 : : * @type_name: 0-terminated string used as the name of the new type
2590 : : * @plugin: #GTypePlugin structure to retrieve the #GTypeInfo from
2591 : : * @flags: bitwise combination of #GTypeFlags values
2592 : : *
2593 : : * Registers @type_name as the name of a new dynamic type derived from
2594 : : * @parent_type. The type system uses the information contained in the
2595 : : * #GTypePlugin structure pointed to by @plugin to manage the type and its
2596 : : * instances (if not abstract). The value of @flags determines the nature
2597 : : * (e.g. abstract or not) of the type.
2598 : : *
2599 : : * Returns: the new type identifier or %G_TYPE_INVALID if registration failed
2600 : : */
2601 : : GType
2602 : 4 : g_type_register_dynamic (GType parent_type,
2603 : : const gchar *type_name,
2604 : : GTypePlugin *plugin,
2605 : : GTypeFlags flags)
2606 : : {
2607 : : TypeNode *pnode, *node;
2608 : : GType type;
2609 : :
2610 : 4 : g_assert_type_system_initialized ();
2611 : 4 : g_return_val_if_fail (parent_type > 0, 0);
2612 : 4 : g_return_val_if_fail (type_name != NULL, 0);
2613 : 4 : g_return_val_if_fail (plugin != NULL, 0);
2614 : :
2615 : 8 : if (!check_type_name_I (type_name) ||
2616 : 8 : !check_derivation_I (parent_type, type_name) ||
2617 : 4 : !check_plugin_U (plugin, TRUE, FALSE, type_name))
2618 : 0 : return 0;
2619 : :
2620 : 4 : G_WRITE_LOCK (&type_rw_lock);
2621 : 4 : pnode = lookup_type_node_I (parent_type);
2622 : 4 : node = type_node_new_W (pnode, type_name, plugin);
2623 : 4 : type_add_flags_W (node, flags);
2624 : 4 : type = NODE_TYPE (node);
2625 : 4 : G_WRITE_UNLOCK (&type_rw_lock);
2626 : :
2627 : 4 : return type;
2628 : : }
2629 : :
2630 : : /**
2631 : : * g_type_add_interface_static:
2632 : : * @instance_type: #GType value of an instantiatable type
2633 : : * @interface_type: #GType value of an interface type
2634 : : * @info: #GInterfaceInfo structure for this
2635 : : * (@instance_type, @interface_type) combination
2636 : : *
2637 : : * Adds @interface_type to the static @instance_type.
2638 : : * The information contained in the #GInterfaceInfo structure
2639 : : * pointed to by @info is used to manage the relationship.
2640 : : */
2641 : : void
2642 : 7643 : g_type_add_interface_static (GType instance_type,
2643 : : GType interface_type,
2644 : : const GInterfaceInfo *info)
2645 : : {
2646 : : /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2647 : 7643 : g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2648 : 7643 : g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2649 : :
2650 : : /* we only need to lock class_init_rec_mutex if instance_type already has its
2651 : : * class initialized, however this function is rarely enough called to take
2652 : : * the simple route and always acquire class_init_rec_mutex.
2653 : : */
2654 : 7643 : g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2655 : 7643 : G_WRITE_LOCK (&type_rw_lock);
2656 : 7643 : if (check_add_interface_L (instance_type, interface_type))
2657 : : {
2658 : 7643 : TypeNode *node = lookup_type_node_I (instance_type);
2659 : 7643 : TypeNode *iface = lookup_type_node_I (interface_type);
2660 : 7643 : if (check_interface_info_I (iface, NODE_TYPE (node), info))
2661 : 7643 : type_add_interface_Wm (node, iface, info, NULL);
2662 : : }
2663 : 7643 : G_WRITE_UNLOCK (&type_rw_lock);
2664 : 7643 : g_rec_mutex_unlock (&class_init_rec_mutex);
2665 : : }
2666 : :
2667 : : /**
2668 : : * g_type_add_interface_dynamic:
2669 : : * @instance_type: #GType value of an instantiatable type
2670 : : * @interface_type: #GType value of an interface type
2671 : : * @plugin: #GTypePlugin structure to retrieve the #GInterfaceInfo from
2672 : : *
2673 : : * Adds @interface_type to the dynamic @instance_type. The information
2674 : : * contained in the #GTypePlugin structure pointed to by @plugin
2675 : : * is used to manage the relationship.
2676 : : */
2677 : : void
2678 : 2 : g_type_add_interface_dynamic (GType instance_type,
2679 : : GType interface_type,
2680 : : GTypePlugin *plugin)
2681 : : {
2682 : : TypeNode *node;
2683 : : /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
2684 : 2 : g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
2685 : 2 : g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
2686 : :
2687 : 2 : node = lookup_type_node_I (instance_type);
2688 : 2 : if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
2689 : 0 : return;
2690 : :
2691 : : /* see comment in g_type_add_interface_static() about class_init_rec_mutex */
2692 : 2 : g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2693 : 2 : G_WRITE_LOCK (&type_rw_lock);
2694 : 2 : if (check_add_interface_L (instance_type, interface_type))
2695 : : {
2696 : 2 : TypeNode *iface = lookup_type_node_I (interface_type);
2697 : 2 : type_add_interface_Wm (node, iface, NULL, plugin);
2698 : : }
2699 : 2 : G_WRITE_UNLOCK (&type_rw_lock);
2700 : 2 : g_rec_mutex_unlock (&class_init_rec_mutex);
2701 : : }
2702 : :
2703 : :
2704 : : /* --- public API functions --- */
2705 : :
2706 : : /**
2707 : : * g_type_class_get:
2708 : : * @type: type ID of a classed type
2709 : : *
2710 : : * Retrieves the type class of the given @type.
2711 : : *
2712 : : * This function will create the class on demand if it does not exist
2713 : : * already.
2714 : : *
2715 : : * If you don't want to create the class, use g_type_class_peek() instead.
2716 : : *
2717 : : * Returns: (transfer none) (type GObject.TypeClass): the class structure
2718 : : * for the type
2719 : : *
2720 : : * Since: 2.84
2721 : : */
2722 : : gpointer
2723 : 8988047 : g_type_class_get (GType type)
2724 : : {
2725 : : TypeNode *node;
2726 : : GType ptype;
2727 : : GTypeClass *pclass;
2728 : :
2729 : : /* optimize for common code path */
2730 : 8988047 : node = lookup_type_node_I (type);
2731 : 8988047 : if (!node || !node->is_classed)
2732 : : {
2733 : 0 : g_critical ("cannot retrieve class for invalid (unclassed) type '%s'",
2734 : : type_descriptive_name_I (type));
2735 : 0 : return NULL;
2736 : : }
2737 : :
2738 : 8988047 : if (G_LIKELY (node->data != NULL))
2739 : : {
2740 : 8988027 : if (G_LIKELY (g_atomic_int_get (&node->data->class.init_state) == INITIALIZED))
2741 : 8964337 : return node->data->class.class;
2742 : : }
2743 : :
2744 : : /* here, we either have node->data->class.class == NULL, or a recursive
2745 : : * call to g_type_class_ref() with a partly initialized class, or
2746 : : * node->data->class.init_state == INITIALIZED, because any
2747 : : * concurrently running initialization was guarded by class_init_rec_mutex.
2748 : : */
2749 : 23710 : g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
2750 : :
2751 : : /* we need an initialized parent class for initializing derived classes */
2752 : 23710 : ptype = NODE_PARENT_TYPE (node);
2753 : 23710 : pclass = ptype ? g_type_class_get (ptype) : NULL;
2754 : :
2755 : 23710 : G_WRITE_LOCK (&type_rw_lock);
2756 : :
2757 : 23710 : type_data_ref_Wm (node);
2758 : :
2759 : 23710 : if (!node->data->class.class) /* class uninitialized */
2760 : 20512 : type_class_init_Wm (node, pclass);
2761 : :
2762 : 23710 : G_WRITE_UNLOCK (&type_rw_lock);
2763 : :
2764 : 23710 : g_rec_mutex_unlock (&class_init_rec_mutex);
2765 : :
2766 : 23710 : return node->data->class.class;
2767 : : }
2768 : :
2769 : : /**
2770 : : * g_type_class_ref:
2771 : : * @type: type ID of a classed type
2772 : : *
2773 : : * Increments the reference count of the class structure belonging to
2774 : : * @type.
2775 : : *
2776 : : * This function will demand-create the class if it doesn't exist already.
2777 : : *
2778 : : * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
2779 : : * structure for the given type ID
2780 : : *
2781 : : * Deprecated: 2.84: Use g_type_class_get() instead
2782 : : */
2783 : : gpointer
2784 : 1048743 : g_type_class_ref (GType type)
2785 : : {
2786 : 1048743 : return g_type_class_get (type);
2787 : : }
2788 : :
2789 : : /**
2790 : : * g_type_class_unref:
2791 : : * @g_class: (type GObject.TypeClass): a #GTypeClass structure to unref
2792 : : *
2793 : : * Decrements the reference count of the class structure being passed in.
2794 : : *
2795 : : * Once the last reference count of a class has been released, classes
2796 : : * may be finalized by the type system, so further dereferencing of a
2797 : : * class pointer after g_type_class_unref() are invalid.
2798 : : *
2799 : : * Deprecated: 2.84: Type class reference counting has been removed and type
2800 : : * classes now cannot be finalized. This function no longer does anything.
2801 : : */
2802 : : void
2803 : 1018123 : g_type_class_unref (gpointer g_class)
2804 : : {
2805 : 1018123 : }
2806 : :
2807 : : /**
2808 : : * g_type_class_unref_uncached: (skip)
2809 : : * @g_class: (type GObject.TypeClass): a #GTypeClass structure to unref
2810 : : *
2811 : : * A variant of g_type_class_unref() for use in #GTypeClassCacheFunc
2812 : : * implementations.
2813 : : *
2814 : : * It unreferences a class without consulting the chain
2815 : : * of #GTypeClassCacheFuncs, avoiding the recursion which would occur
2816 : : * otherwise.
2817 : : *
2818 : : * Deprecated: 2.84: Type class reference counting has been removed and type
2819 : : * classes now cannot be finalized. This function no longer does anything.
2820 : : */
2821 : : void
2822 : 0 : g_type_class_unref_uncached (gpointer g_class)
2823 : : {
2824 : 0 : }
2825 : :
2826 : : /**
2827 : : * g_type_class_peek:
2828 : : * @type: type ID of a classed type
2829 : : *
2830 : : * Retrieves the class for a give type.
2831 : : *
2832 : : * This function is essentially the same as g_type_class_get(),
2833 : : * except that the class may have not been instantiated yet.
2834 : : *
2835 : : * As a consequence, this function may return %NULL if the class
2836 : : * of the type passed in does not currently exist (hasn't been
2837 : : * referenced before).
2838 : : *
2839 : : * Returns: (type GObject.TypeClass) (transfer none) (nullable): the
2840 : : * #GTypeClass structure for the given type ID or %NULL if the class
2841 : : * does not currently exist
2842 : : */
2843 : : gpointer
2844 : 27937 : g_type_class_peek (GType type)
2845 : : {
2846 : : TypeNode *node;
2847 : :
2848 : 27937 : node = lookup_type_node_I (type);
2849 : 27937 : if (node && node->is_classed)
2850 : : {
2851 : 27937 : if (node->data == NULL)
2852 : 2 : return NULL;
2853 : :
2854 : 27935 : if (G_LIKELY (g_atomic_int_get (&node->data->class.init_state) == INITIALIZED))
2855 : 27933 : return node->data->class.class;
2856 : : }
2857 : :
2858 : 2 : return NULL;
2859 : : }
2860 : :
2861 : : /**
2862 : : * g_type_class_peek_static:
2863 : : * @type: type ID of a classed type
2864 : : *
2865 : : * A more efficient version of g_type_class_peek() which works only for
2866 : : * static types.
2867 : : *
2868 : : * Returns: (type GObject.TypeClass) (transfer none) (nullable): the
2869 : : * #GTypeClass structure for the given type ID or %NULL if the class
2870 : : * does not currently exist or is dynamically loaded
2871 : : *
2872 : : * Since: 2.4
2873 : : */
2874 : : gpointer
2875 : 7902290 : g_type_class_peek_static (GType type)
2876 : : {
2877 : : TypeNode *node;
2878 : :
2879 : 7902290 : node = lookup_type_node_I (type);
2880 : 7902290 : if (node && node->is_classed)
2881 : : {
2882 : 7902290 : if (node->data == NULL)
2883 : 1 : return NULL;
2884 : :
2885 : : /* peek only static types */
2886 : 7902289 : if (node->plugin != NULL)
2887 : 0 : return NULL;
2888 : :
2889 : 7902289 : if (G_LIKELY (g_atomic_int_get (&node->data->class.init_state) == INITIALIZED))
2890 : 7899870 : return node->data->class.class;
2891 : : }
2892 : :
2893 : 2419 : return NULL;
2894 : : }
2895 : :
2896 : : /**
2897 : : * g_type_class_peek_parent:
2898 : : * @g_class: (type GObject.TypeClass): the #GTypeClass structure to
2899 : : * retrieve the parent class for
2900 : : *
2901 : : * Retrieves the class structure of the immediate parent type of the
2902 : : * class passed in.
2903 : : *
2904 : : * This is a convenience function often needed in class initializers.
2905 : : *
2906 : : * Since derived classes hold a reference on their parent classes as
2907 : : * long as they are instantiated, the returned class will always exist.
2908 : : *
2909 : : * This function is essentially equivalent to:
2910 : : * g_type_class_peek (g_type_parent (G_TYPE_FROM_CLASS (g_class)))
2911 : : *
2912 : : * Returns: (type GObject.TypeClass) (transfer none): the parent class
2913 : : * of @g_class
2914 : : */
2915 : : gpointer
2916 : 11243 : g_type_class_peek_parent (gpointer g_class)
2917 : : {
2918 : : TypeNode *node;
2919 : 11243 : gpointer class = NULL;
2920 : :
2921 : 11243 : g_return_val_if_fail (g_class != NULL, NULL);
2922 : :
2923 : 11243 : node = lookup_type_node_I (G_TYPE_FROM_CLASS (g_class));
2924 : :
2925 : 11243 : g_return_val_if_fail (node != NULL, NULL);
2926 : :
2927 : : /* We used to acquire a read lock here. That is not necessary, since
2928 : : * parent->data->class.class is constant as long as the derived class
2929 : : * exists.
2930 : : */
2931 : 11243 : if (node->is_classed && node->data && NODE_PARENT_TYPE (node))
2932 : : {
2933 : 10870 : node = lookup_type_node_I (NODE_PARENT_TYPE (node));
2934 : 10870 : class = node->data->class.class;
2935 : : }
2936 : 373 : else if (NODE_PARENT_TYPE (node))
2937 : 0 : g_critical (G_STRLOC ": invalid class pointer '%p'", g_class);
2938 : :
2939 : 11243 : return class;
2940 : : }
2941 : :
2942 : : /**
2943 : : * g_type_interface_peek:
2944 : : * @instance_class: (type GObject.TypeClass): a #GTypeClass structure
2945 : : * @iface_type: an interface ID which this class conforms to
2946 : : *
2947 : : * Returns the #GTypeInterface structure of an interface to which the
2948 : : * passed in class conforms.
2949 : : *
2950 : : * Returns: (type GObject.TypeInterface) (transfer none) (nullable): the #GTypeInterface
2951 : : * structure of @iface_type if implemented by @instance_class, %NULL
2952 : : * otherwise
2953 : : */
2954 : : gpointer
2955 : 779593 : g_type_interface_peek (gpointer instance_class,
2956 : : GType iface_type)
2957 : : {
2958 : : TypeNode *node;
2959 : : TypeNode *iface;
2960 : 779593 : gpointer vtable = NULL;
2961 : 779593 : GTypeClass *class = instance_class;
2962 : :
2963 : 779593 : g_return_val_if_fail (instance_class != NULL, NULL);
2964 : :
2965 : 779593 : node = lookup_type_node_I (class->g_type);
2966 : 779593 : iface = lookup_type_node_I (iface_type);
2967 : 779593 : if (node && node->is_instantiatable && iface)
2968 : 779593 : type_lookup_iface_vtable_I (node, iface, &vtable);
2969 : : else
2970 : 0 : g_critical (G_STRLOC ": invalid class pointer '%p'", class);
2971 : :
2972 : 779593 : return vtable;
2973 : : }
2974 : :
2975 : : /**
2976 : : * g_type_interface_peek_parent:
2977 : : * @g_iface: (type GObject.TypeInterface): a #GTypeInterface structure
2978 : : *
2979 : : * Returns the corresponding #GTypeInterface structure of the parent type
2980 : : * of the instance type to which @g_iface belongs.
2981 : : *
2982 : : * This is useful when deriving the implementation of an interface from the
2983 : : * parent type and then possibly overriding some methods.
2984 : : *
2985 : : * Returns: (transfer none) (type GObject.TypeInterface) (nullable): the
2986 : : * corresponding #GTypeInterface structure of the parent type of the
2987 : : * instance type to which @g_iface belongs, or %NULL if the parent
2988 : : * type doesn't conform to the interface
2989 : : */
2990 : : gpointer
2991 : 208 : g_type_interface_peek_parent (gpointer g_iface)
2992 : : {
2993 : : TypeNode *node;
2994 : : TypeNode *iface;
2995 : 208 : gpointer vtable = NULL;
2996 : 208 : GTypeInterface *iface_class = g_iface;
2997 : :
2998 : 208 : g_return_val_if_fail (g_iface != NULL, NULL);
2999 : :
3000 : 208 : iface = lookup_type_node_I (iface_class->g_type);
3001 : 208 : node = lookup_type_node_I (iface_class->g_instance_type);
3002 : 208 : if (node)
3003 : 207 : node = lookup_type_node_I (NODE_PARENT_TYPE (node));
3004 : 208 : if (node && node->is_instantiatable && iface)
3005 : 207 : type_lookup_iface_vtable_I (node, iface, &vtable);
3006 : 1 : else if (node)
3007 : 0 : g_critical (G_STRLOC ": invalid interface pointer '%p'", g_iface);
3008 : :
3009 : 208 : return vtable;
3010 : : }
3011 : :
3012 : : /**
3013 : : * g_type_default_interface_ref:
3014 : : * @g_type: an interface type
3015 : : *
3016 : : * Increments the reference count for the interface type @g_type,
3017 : : * and returns the default interface vtable for the type.
3018 : : *
3019 : : * If the type is not currently in use, then the default vtable
3020 : : * for the type will be created and initialized by calling
3021 : : * the base interface init and default vtable init functions for
3022 : : * the type (the @base_init and @class_init members of #GTypeInfo).
3023 : : * Calling g_type_default_interface_ref() is useful when you
3024 : : * want to make sure that signals and properties for an interface
3025 : : * have been installed.
3026 : : *
3027 : : * Since: 2.4
3028 : : *
3029 : : * Deprecated: 2.84: Use g_type_default_interface_get() instead
3030 : : *
3031 : : * Returns: (type GObject.TypeInterface) (transfer none): the default
3032 : : * vtable for the interface; call g_type_default_interface_unref()
3033 : : * when you are done using the interface.
3034 : : */
3035 : : gpointer
3036 : 58 : g_type_default_interface_ref (GType g_type)
3037 : : {
3038 : 58 : return g_type_default_interface_get (g_type);
3039 : : }
3040 : :
3041 : : /**
3042 : : * g_type_default_interface_get:
3043 : : * @g_type: an interface type
3044 : : *
3045 : : * Returns the default interface vtable for the given @g_type.
3046 : : *
3047 : : * If the type is not currently in use, then the default vtable
3048 : : * for the type will be created and initialized by calling
3049 : : * the base interface init and default vtable init functions for
3050 : : * the type (the @base_init and @class_init members of #GTypeInfo).
3051 : : *
3052 : : * If you don't want to create the interface vtable, you should use
3053 : : * g_type_default_interface_peek() instead.
3054 : : *
3055 : : * Calling g_type_default_interface_get() is useful when you
3056 : : * want to make sure that signals and properties for an interface
3057 : : * have been installed.
3058 : : *
3059 : : * Returns: (type GObject.TypeInterface) (transfer none): the default
3060 : : * vtable for the interface.
3061 : : *
3062 : : * Since: 2.84
3063 : : */
3064 : : gpointer
3065 : 58 : g_type_default_interface_get (GType g_type)
3066 : : {
3067 : : TypeNode *node;
3068 : : gpointer dflt_vtable;
3069 : :
3070 : 58 : G_WRITE_LOCK (&type_rw_lock);
3071 : :
3072 : 58 : node = lookup_type_node_I (g_type);
3073 : 58 : if (!node || !NODE_IS_IFACE (node))
3074 : : {
3075 : 0 : G_WRITE_UNLOCK (&type_rw_lock);
3076 : 0 : g_critical ("cannot retrieve default vtable for invalid or non-interface type '%s'",
3077 : : type_descriptive_name_I (g_type));
3078 : 0 : return NULL;
3079 : : }
3080 : :
3081 : 58 : if (!node->data || !node->data->iface.dflt_vtable)
3082 : : {
3083 : 39 : G_WRITE_UNLOCK (&type_rw_lock);
3084 : 39 : g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
3085 : 39 : G_WRITE_LOCK (&type_rw_lock);
3086 : 39 : node = lookup_type_node_I (g_type);
3087 : 39 : type_data_ref_Wm (node);
3088 : 39 : type_iface_ensure_dflt_vtable_Wm (node);
3089 : 39 : g_rec_mutex_unlock (&class_init_rec_mutex);
3090 : : }
3091 : :
3092 : 58 : dflt_vtable = node->data->iface.dflt_vtable;
3093 : 58 : G_WRITE_UNLOCK (&type_rw_lock);
3094 : :
3095 : 58 : return dflt_vtable;
3096 : : }
3097 : :
3098 : : /**
3099 : : * g_type_default_interface_peek:
3100 : : * @g_type: an interface type
3101 : : *
3102 : : * If the interface type @g_type is currently in use, returns its
3103 : : * default interface vtable.
3104 : : *
3105 : : * Since: 2.4
3106 : : *
3107 : : * Returns: (type GObject.TypeInterface) (transfer none): the default
3108 : : * vtable for the interface, or %NULL if the type is not currently
3109 : : * in use
3110 : : */
3111 : : gpointer
3112 : 45 : g_type_default_interface_peek (GType g_type)
3113 : : {
3114 : : TypeNode *node;
3115 : : gpointer vtable;
3116 : :
3117 : 45 : node = lookup_type_node_I (g_type);
3118 : 45 : if (node && NODE_IS_IFACE (node) && node->data)
3119 : 44 : vtable = node->data->iface.dflt_vtable;
3120 : : else
3121 : 1 : vtable = NULL;
3122 : :
3123 : 45 : return vtable;
3124 : : }
3125 : :
3126 : : /**
3127 : : * g_type_default_interface_unref:
3128 : : * @g_iface: (type GObject.TypeInterface): the default vtable
3129 : : * structure for an interface, as returned by g_type_default_interface_ref()
3130 : : *
3131 : : * Decrements the reference count for the type corresponding to the
3132 : : * interface default vtable @g_iface.
3133 : : *
3134 : : * If the type is dynamic, then when no one is using the interface and all
3135 : : * references have been released, the finalize function for the interface's
3136 : : * default vtable (the @class_finalize member of #GTypeInfo) will be called.
3137 : : *
3138 : : * Since: 2.4
3139 : : *
3140 : : * Deprecated: 2.84: Interface reference counting has been removed and
3141 : : * interface types now cannot be finalized. This function no longer does
3142 : : * anything.
3143 : : */
3144 : : void
3145 : 16 : g_type_default_interface_unref (gpointer g_iface)
3146 : : {
3147 : 16 : }
3148 : :
3149 : : /**
3150 : : * g_type_name:
3151 : : * @type: type to return name for
3152 : : *
3153 : : * Get the unique name that is assigned to a type ID.
3154 : : *
3155 : : * Note that this function (like all other GType API) cannot cope with
3156 : : * invalid type IDs. %G_TYPE_INVALID may be passed to this function, as
3157 : : * may be any other validly registered type ID, but randomized type IDs
3158 : : * should not be passed in and will most likely lead to a crash.
3159 : : *
3160 : : * Returns: (nullable): static type name or %NULL
3161 : : */
3162 : : const gchar *
3163 : 17853 : g_type_name (GType type)
3164 : : {
3165 : : TypeNode *node;
3166 : :
3167 : 17853 : g_assert_type_system_initialized ();
3168 : :
3169 : 17853 : node = lookup_type_node_I (type);
3170 : :
3171 : 17853 : return node ? NODE_NAME (node) : NULL;
3172 : : }
3173 : :
3174 : : /**
3175 : : * g_type_qname:
3176 : : * @type: type to return quark of type name for
3177 : : *
3178 : : * Get the corresponding quark of the type IDs name.
3179 : : *
3180 : : * Returns: the type names quark or 0
3181 : : */
3182 : : GQuark
3183 : 1 : g_type_qname (GType type)
3184 : : {
3185 : : TypeNode *node;
3186 : :
3187 : 1 : node = lookup_type_node_I (type);
3188 : :
3189 : 1 : return node ? node->qname : 0;
3190 : : }
3191 : :
3192 : : /**
3193 : : * g_type_from_name:
3194 : : * @name: type name to look up
3195 : : *
3196 : : * Look up the type ID from a given type name, returning 0 if no type
3197 : : * has been registered under this name (this is the preferred method
3198 : : * to find out by name whether a specific type has been registered
3199 : : * yet).
3200 : : *
3201 : : * Returns: corresponding type ID or 0
3202 : : */
3203 : : GType
3204 : 59143 : g_type_from_name (const gchar *name)
3205 : : {
3206 : 59143 : GType type = 0;
3207 : :
3208 : 59143 : g_return_val_if_fail (name != NULL, 0);
3209 : :
3210 : 59143 : G_READ_LOCK (&type_rw_lock);
3211 : 59143 : type = GPOINTER_TO_TYPE (g_hash_table_lookup (static_type_nodes_ht, name));
3212 : 59143 : G_READ_UNLOCK (&type_rw_lock);
3213 : :
3214 : 59143 : return type;
3215 : : }
3216 : :
3217 : : /**
3218 : : * g_type_parent:
3219 : : * @type: the derived type
3220 : : *
3221 : : * Return the direct parent type of the passed in type. If the passed
3222 : : * in type has no parent, i.e. is a fundamental type, 0 is returned.
3223 : : *
3224 : : * Returns: the parent type
3225 : : */
3226 : : GType
3227 : 888143 : g_type_parent (GType type)
3228 : : {
3229 : : TypeNode *node;
3230 : :
3231 : 888143 : node = lookup_type_node_I (type);
3232 : :
3233 : 888143 : return node ? NODE_PARENT_TYPE (node) : 0;
3234 : : }
3235 : :
3236 : : /**
3237 : : * g_type_depth:
3238 : : * @type: a #GType
3239 : : *
3240 : : * Returns the length of the ancestry of the passed in type. This
3241 : : * includes the type itself, so that e.g. a fundamental type has depth 1.
3242 : : *
3243 : : * Returns: the depth of @type
3244 : : */
3245 : : guint
3246 : 3792 : g_type_depth (GType type)
3247 : : {
3248 : : TypeNode *node;
3249 : :
3250 : 3792 : node = lookup_type_node_I (type);
3251 : :
3252 : 3792 : return node ? node->n_supers + 1 : 0;
3253 : : }
3254 : :
3255 : : /**
3256 : : * g_type_next_base:
3257 : : * @leaf_type: descendant of @root_type and the type to be returned
3258 : : * @root_type: immediate parent of the returned type
3259 : : *
3260 : : * Given a @leaf_type and a @root_type which is contained in its
3261 : : * ancestry, return the type that @root_type is the immediate parent
3262 : : * of. In other words, this function determines the type that is
3263 : : * derived directly from @root_type which is also a base class of
3264 : : * @leaf_type. Given a root type and a leaf type, this function can
3265 : : * be used to determine the types and order in which the leaf type is
3266 : : * descended from the root type.
3267 : : *
3268 : : * Returns: immediate child of @root_type and ancestor of @leaf_type
3269 : : */
3270 : : GType
3271 : 1 : g_type_next_base (GType type,
3272 : : GType base_type)
3273 : : {
3274 : 1 : GType atype = 0;
3275 : : TypeNode *node;
3276 : :
3277 : 1 : node = lookup_type_node_I (type);
3278 : 1 : if (node)
3279 : : {
3280 : 1 : TypeNode *base_node = lookup_type_node_I (base_type);
3281 : :
3282 : 1 : if (base_node && base_node->n_supers < node->n_supers)
3283 : : {
3284 : 1 : guint n = node->n_supers - base_node->n_supers;
3285 : :
3286 : 1 : if (node->supers[n] == base_type)
3287 : 1 : atype = node->supers[n - 1];
3288 : : }
3289 : : }
3290 : :
3291 : 1 : return atype;
3292 : : }
3293 : :
3294 : : static inline gboolean
3295 : 98256488 : type_node_check_conformities_UorL (TypeNode *node,
3296 : : TypeNode *iface_node,
3297 : : /* support_inheritance */
3298 : : gboolean support_interfaces,
3299 : : gboolean support_prerequisites,
3300 : : gboolean have_lock)
3301 : : {
3302 : : gboolean match;
3303 : :
3304 : 98256488 : if (/* support_inheritance && */
3305 : 98256488 : NODE_IS_ANCESTOR (iface_node, node))
3306 : 85215002 : return TRUE;
3307 : :
3308 : 13041486 : support_interfaces = support_interfaces && node->is_instantiatable && NODE_IS_IFACE (iface_node);
3309 : 13041486 : support_prerequisites = support_prerequisites && NODE_IS_IFACE (node);
3310 : 13041486 : match = FALSE;
3311 : 13041486 : if (support_interfaces)
3312 : : {
3313 : 12971236 : if (have_lock)
3314 : : {
3315 : 1006 : if (type_lookup_iface_entry_L (node, iface_node))
3316 : 1006 : match = TRUE;
3317 : : }
3318 : : else
3319 : : {
3320 : 12970230 : if (type_lookup_iface_vtable_I (node, iface_node, NULL))
3321 : 12963853 : match = TRUE;
3322 : : }
3323 : : }
3324 : 13041486 : if (!match &&
3325 : : support_prerequisites)
3326 : : {
3327 : 9596 : if (!have_lock)
3328 : 9596 : G_READ_LOCK (&type_rw_lock);
3329 : 9596 : if (support_prerequisites && type_lookup_prerequisite_L (node, NODE_TYPE (iface_node)))
3330 : 4312 : match = TRUE;
3331 : 9596 : if (!have_lock)
3332 : 9596 : G_READ_UNLOCK (&type_rw_lock);
3333 : : }
3334 : 13041486 : return match;
3335 : : }
3336 : :
3337 : : static gboolean
3338 : 7255 : type_node_is_a_L (TypeNode *node,
3339 : : TypeNode *iface_node)
3340 : : {
3341 : 7255 : return type_node_check_conformities_UorL (node, iface_node, TRUE, TRUE, TRUE);
3342 : : }
3343 : :
3344 : : static inline gboolean
3345 : 98249233 : type_node_conforms_to_U (TypeNode *node,
3346 : : TypeNode *iface_node,
3347 : : gboolean support_interfaces,
3348 : : gboolean support_prerequisites)
3349 : : {
3350 : 98249233 : return type_node_check_conformities_UorL (node, iface_node, support_interfaces, support_prerequisites, FALSE);
3351 : : }
3352 : :
3353 : : /**
3354 : : * g_type_is_a:
3355 : : * @type: type to check ancestry for
3356 : : * @is_a_type: possible ancestor of @type or interface that @type
3357 : : * could conform to
3358 : : *
3359 : : * If @is_a_type is a derivable type, check whether @type is a
3360 : : * descendant of @is_a_type. If @is_a_type is an interface, check
3361 : : * whether @type conforms to it.
3362 : : *
3363 : : * Returns: %TRUE if @type is a @is_a_type
3364 : : */
3365 : : gboolean
3366 : 6843192 : (g_type_is_a) (GType type,
3367 : : GType iface_type)
3368 : : {
3369 : : TypeNode *node, *iface_node;
3370 : : gboolean is_a;
3371 : :
3372 : 6843192 : if (type == iface_type)
3373 : 1 : return TRUE;
3374 : :
3375 : 6843191 : node = lookup_type_node_I (type);
3376 : 6843191 : iface_node = lookup_type_node_I (iface_type);
3377 : 6843191 : is_a = node && iface_node && type_node_conforms_to_U (node, iface_node, TRUE, TRUE);
3378 : :
3379 : 6843191 : return is_a;
3380 : : }
3381 : :
3382 : : /**
3383 : : * g_type_children:
3384 : : * @type: the parent type
3385 : : * @n_children: (out) (optional): location to store the length of
3386 : : * the returned array, or %NULL
3387 : : *
3388 : : * Return a newly allocated and 0-terminated array of type IDs, listing
3389 : : * the child types of @type.
3390 : : *
3391 : : * Returns: (array length=n_children) (transfer full): Newly allocated
3392 : : * and 0-terminated array of child types, free with g_free()
3393 : : */
3394 : : GType*
3395 : 76 : g_type_children (GType type,
3396 : : guint *n_children)
3397 : : {
3398 : : TypeNode *node;
3399 : :
3400 : 76 : node = lookup_type_node_I (type);
3401 : 76 : if (node)
3402 : : {
3403 : : GType *children;
3404 : :
3405 : 76 : G_READ_LOCK (&type_rw_lock); /* ->children is relocatable */
3406 : 76 : children = g_new (GType, node->n_children + 1);
3407 : 76 : if (node->n_children != 0)
3408 : 32 : memcpy (children, node->children, sizeof (GType) * node->n_children);
3409 : 76 : children[node->n_children] = 0;
3410 : :
3411 : 76 : if (n_children)
3412 : 28 : *n_children = node->n_children;
3413 : 76 : G_READ_UNLOCK (&type_rw_lock);
3414 : :
3415 : 76 : return children;
3416 : : }
3417 : : else
3418 : : {
3419 : 0 : if (n_children)
3420 : 0 : *n_children = 0;
3421 : :
3422 : 0 : return NULL;
3423 : : }
3424 : : }
3425 : :
3426 : : /**
3427 : : * g_type_interfaces:
3428 : : * @type: the type to list interface types for
3429 : : * @n_interfaces: (out) (optional): location to store the length of
3430 : : * the returned array, or %NULL
3431 : : *
3432 : : * Return a newly allocated and 0-terminated array of type IDs, listing
3433 : : * the interface types that @type conforms to.
3434 : : *
3435 : : * Returns: (array length=n_interfaces) (transfer full): Newly allocated
3436 : : * and 0-terminated array of interface types, free with g_free()
3437 : : */
3438 : : GType*
3439 : 403303 : g_type_interfaces (GType type,
3440 : : guint *n_interfaces)
3441 : : {
3442 : : TypeNode *node;
3443 : :
3444 : 403303 : node = lookup_type_node_I (type);
3445 : 403303 : if (node && node->is_instantiatable)
3446 : : {
3447 : : IFaceEntries *entries;
3448 : : GType *ifaces;
3449 : : guint i;
3450 : :
3451 : 403027 : G_READ_LOCK (&type_rw_lock);
3452 : 403027 : entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node);
3453 : 403027 : if (entries)
3454 : : {
3455 : 401750 : ifaces = g_new (GType, IFACE_ENTRIES_N_ENTRIES (entries) + 1);
3456 : 1206162 : for (i = 0; i < IFACE_ENTRIES_N_ENTRIES (entries); i++)
3457 : 804412 : ifaces[i] = entries->entry[i].iface_type;
3458 : : }
3459 : : else
3460 : : {
3461 : 1277 : ifaces = g_new (GType, 1);
3462 : 1277 : i = 0;
3463 : : }
3464 : 403027 : ifaces[i] = 0;
3465 : :
3466 : 403027 : if (n_interfaces)
3467 : 403027 : *n_interfaces = i;
3468 : 403027 : G_READ_UNLOCK (&type_rw_lock);
3469 : :
3470 : 403027 : return ifaces;
3471 : : }
3472 : : else
3473 : : {
3474 : 276 : if (n_interfaces)
3475 : 276 : *n_interfaces = 0;
3476 : :
3477 : 276 : return NULL;
3478 : : }
3479 : : }
3480 : :
3481 : : typedef struct _QData QData;
3482 : : struct _GData
3483 : : {
3484 : : guint n_qdatas;
3485 : : QData *qdatas;
3486 : : };
3487 : : struct _QData
3488 : : {
3489 : : GQuark quark;
3490 : : gpointer data;
3491 : : };
3492 : :
3493 : : static inline gpointer
3494 : 139643 : type_get_qdata_L (TypeNode *node,
3495 : : GQuark quark)
3496 : : {
3497 : 139643 : GData *gdata = node->global_gdata;
3498 : :
3499 : 139643 : if (quark && gdata && gdata->n_qdatas)
3500 : : {
3501 : 96128 : QData *qdatas = gdata->qdatas - 1;
3502 : 96128 : guint n_qdatas = gdata->n_qdatas;
3503 : :
3504 : : do
3505 : : {
3506 : : guint i;
3507 : : QData *check;
3508 : :
3509 : 107175 : i = (n_qdatas + 1) / 2;
3510 : 107175 : check = qdatas + i;
3511 : 107175 : if (quark == check->quark)
3512 : 85081 : return check->data;
3513 : 22094 : else if (quark > check->quark)
3514 : : {
3515 : 21951 : n_qdatas -= i;
3516 : 21951 : qdatas = check;
3517 : : }
3518 : : else /* if (quark < check->quark) */
3519 : 143 : n_qdatas = i - 1;
3520 : : }
3521 : 22094 : while (n_qdatas);
3522 : : }
3523 : 54562 : return NULL;
3524 : : }
3525 : :
3526 : : /**
3527 : : * g_type_get_qdata:
3528 : : * @type: a #GType
3529 : : * @quark: a #GQuark id to identify the data
3530 : : *
3531 : : * Obtains data which has previously been attached to @type
3532 : : * with g_type_set_qdata().
3533 : : *
3534 : : * Note that this does not take subtyping into account; data
3535 : : * attached to one type with g_type_set_qdata() cannot
3536 : : * be retrieved from a subtype using g_type_get_qdata().
3537 : : *
3538 : : * Returns: (transfer none): the data, or %NULL if no data was found
3539 : : */
3540 : : gpointer
3541 : 274 : g_type_get_qdata (GType type,
3542 : : GQuark quark)
3543 : : {
3544 : : TypeNode *node;
3545 : : gpointer data;
3546 : :
3547 : 274 : node = lookup_type_node_I (type);
3548 : 274 : if (node)
3549 : : {
3550 : 274 : G_READ_LOCK (&type_rw_lock);
3551 : 274 : data = type_get_qdata_L (node, quark);
3552 : 274 : G_READ_UNLOCK (&type_rw_lock);
3553 : : }
3554 : : else
3555 : : {
3556 : 0 : g_return_val_if_fail (node != NULL, NULL);
3557 : 0 : data = NULL;
3558 : : }
3559 : 274 : return data;
3560 : : }
3561 : :
3562 : : static inline void
3563 : 51918 : type_set_qdata_W (TypeNode *node,
3564 : : GQuark quark,
3565 : : gpointer data)
3566 : : {
3567 : : GData *gdata;
3568 : : QData *qdata;
3569 : : guint i;
3570 : :
3571 : : /* setup qdata list if necessary */
3572 : 51918 : if (!node->global_gdata)
3573 : 43497 : node->global_gdata = g_new0 (GData, 1);
3574 : 51918 : gdata = node->global_gdata;
3575 : :
3576 : : /* try resetting old data */
3577 : 51918 : qdata = gdata->qdatas;
3578 : 60590 : for (i = 0; i < gdata->n_qdatas; i++)
3579 : 13960 : if (qdata[i].quark == quark)
3580 : : {
3581 : 5288 : qdata[i].data = data;
3582 : 5288 : return;
3583 : : }
3584 : :
3585 : : /* add new entry */
3586 : 46630 : gdata->n_qdatas++;
3587 : 46630 : gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
3588 : 46630 : qdata = gdata->qdatas;
3589 : 49822 : for (i = 0; i < gdata->n_qdatas - 1; i++)
3590 : 3335 : if (qdata[i].quark > quark)
3591 : 143 : break;
3592 : 46630 : memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1));
3593 : 46630 : qdata[i].quark = quark;
3594 : 46630 : qdata[i].data = data;
3595 : : }
3596 : :
3597 : : /**
3598 : : * g_type_set_qdata:
3599 : : * @type: a #GType
3600 : : * @quark: a #GQuark id to identify the data
3601 : : * @data: the data
3602 : : *
3603 : : * Attaches arbitrary data to a type.
3604 : : */
3605 : : void
3606 : 163 : g_type_set_qdata (GType type,
3607 : : GQuark quark,
3608 : : gpointer data)
3609 : : {
3610 : : TypeNode *node;
3611 : :
3612 : 163 : g_return_if_fail (quark != 0);
3613 : :
3614 : 163 : node = lookup_type_node_I (type);
3615 : 163 : if (node)
3616 : : {
3617 : 163 : G_WRITE_LOCK (&type_rw_lock);
3618 : 163 : type_set_qdata_W (node, quark, data);
3619 : 163 : G_WRITE_UNLOCK (&type_rw_lock);
3620 : : }
3621 : : else
3622 : 0 : g_return_if_fail (node != NULL);
3623 : : }
3624 : :
3625 : : static void
3626 : 43497 : type_add_flags_W (TypeNode *node,
3627 : : GTypeFlags flags)
3628 : : {
3629 : : guint dflags;
3630 : :
3631 : 43497 : g_return_if_fail ((flags & (unsigned) ~TYPE_FLAG_MASK) == 0);
3632 : 43497 : g_return_if_fail (node != NULL);
3633 : :
3634 : 43497 : if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class)
3635 : 0 : g_critical ("tagging type '%s' as abstract after class initialization", NODE_NAME (node));
3636 : 43497 : dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
3637 : 43497 : dflags |= flags;
3638 : 43497 : type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
3639 : :
3640 : 43497 : node->is_abstract = (flags & G_TYPE_FLAG_ABSTRACT) != 0;
3641 : 43497 : node->is_deprecated |= (flags & G_TYPE_FLAG_DEPRECATED) != 0;
3642 : 43497 : node->is_final = (flags & G_TYPE_FLAG_FINAL) != 0;
3643 : : }
3644 : :
3645 : : /**
3646 : : * g_type_query:
3647 : : * @type: #GType of a static, classed type
3648 : : * @query: (out caller-allocates): a user provided structure that is
3649 : : * filled in with constant values upon success
3650 : : *
3651 : : * Queries the type system for information about a specific type.
3652 : : *
3653 : : * This function will fill in a user-provided structure to hold
3654 : : * type-specific information. If an invalid #GType is passed in, the
3655 : : * @type member of the #GTypeQuery is 0. All members filled into the
3656 : : * #GTypeQuery structure should be considered constant and have to be
3657 : : * left untouched.
3658 : : *
3659 : : * Since GLib 2.78, this function allows queries on dynamic types. Previously
3660 : : * it only supported static types.
3661 : : */
3662 : : void
3663 : 4 : g_type_query (GType type,
3664 : : GTypeQuery *query)
3665 : : {
3666 : : TypeNode *node;
3667 : :
3668 : 4 : g_return_if_fail (query != NULL);
3669 : :
3670 : : /* if node is not classed, we won't allow query */
3671 : 4 : query->type = 0;
3672 : 4 : node = lookup_type_node_I (type);
3673 : 4 : if (node && node->is_classed)
3674 : : {
3675 : : /* type is classed and probably even instantiatable */
3676 : 2 : G_READ_LOCK (&type_rw_lock);
3677 : 2 : if (node->data) /* type is static or referenced */
3678 : : {
3679 : 2 : query->type = NODE_TYPE (node);
3680 : 2 : query->type_name = NODE_NAME (node);
3681 : 2 : query->class_size = node->data->class.class_size;
3682 : 2 : query->instance_size = node->is_instantiatable ? node->data->instance.instance_size : 0;
3683 : : }
3684 : 2 : G_READ_UNLOCK (&type_rw_lock);
3685 : : }
3686 : : }
3687 : :
3688 : : /**
3689 : : * g_type_get_instance_count:
3690 : : * @type: a #GType
3691 : : *
3692 : : * Returns the number of instances allocated of the particular type;
3693 : : * this is only available if GLib is built with debugging support and
3694 : : * the `instance-count` debug flag is set (by setting the `GOBJECT_DEBUG`
3695 : : * variable to include `instance-count`).
3696 : : *
3697 : : * Returns: the number of instances allocated of the given type;
3698 : : * if instance counts are not available, returns 0.
3699 : : *
3700 : : * Since: 2.44
3701 : : */
3702 : : int
3703 : 0 : g_type_get_instance_count (GType type)
3704 : : {
3705 : : #ifdef G_ENABLE_DEBUG
3706 : : TypeNode *node;
3707 : :
3708 : 0 : node = lookup_type_node_I (type);
3709 : 0 : g_return_val_if_fail (node != NULL, 0);
3710 : :
3711 : 0 : return g_atomic_int_get (&node->instance_count);
3712 : : #else
3713 : : return 0;
3714 : : #endif
3715 : : }
3716 : :
3717 : : /* --- implementation details --- */
3718 : : static inline gboolean
3719 : 7933148 : _g_type_test_flags (GType type,
3720 : : guint flags)
3721 : : {
3722 : : TypeNode *node;
3723 : 7933148 : gboolean result = FALSE;
3724 : :
3725 : 7933148 : node = lookup_type_node_I (type);
3726 : 7933148 : if (node)
3727 : : {
3728 : 7933148 : if ((flags & (unsigned) ~NODE_FLAG_MASK) == 0)
3729 : : {
3730 : 7933144 : if ((flags & G_TYPE_FLAG_CLASSED) && !node->is_classed)
3731 : 365 : return FALSE;
3732 : :
3733 : 7932779 : if ((flags & G_TYPE_FLAG_INSTANTIATABLE) && !node->is_instantiatable)
3734 : 411 : return FALSE;
3735 : :
3736 : 7932368 : if ((flags & G_TYPE_FLAG_FINAL) && !node->is_final)
3737 : 140 : return FALSE;
3738 : :
3739 : 7932228 : if ((flags & G_TYPE_FLAG_ABSTRACT) && !node->is_abstract)
3740 : 1595 : return FALSE;
3741 : :
3742 : 7930633 : if ((flags & G_TYPE_FLAG_DEPRECATED) && !node->is_deprecated)
3743 : 7916908 : return FALSE;
3744 : :
3745 : 13725 : return TRUE;
3746 : : }
3747 : :
3748 : 4 : guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
3749 : 4 : guint tflags = flags & TYPE_FLAG_MASK;
3750 : :
3751 : 4 : if (fflags)
3752 : : {
3753 : 4 : GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (node);
3754 : :
3755 : 4 : fflags = (finfo->type_flags & fflags) == fflags;
3756 : : }
3757 : : else
3758 : 0 : fflags = TRUE;
3759 : :
3760 : 4 : if (tflags)
3761 : : {
3762 : 0 : G_READ_LOCK (&type_rw_lock);
3763 : 0 : tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
3764 : 0 : G_READ_UNLOCK (&type_rw_lock);
3765 : : }
3766 : : else
3767 : 4 : tflags = TRUE;
3768 : :
3769 : 4 : result = tflags && fflags;
3770 : : }
3771 : :
3772 : 4 : return result;
3773 : : }
3774 : :
3775 : : gboolean
3776 : 8594 : (g_type_test_flags) (GType type,
3777 : : guint flags)
3778 : : {
3779 : 8594 : return _g_type_test_flags (type, flags);
3780 : : }
3781 : :
3782 : : /**
3783 : : * g_type_get_plugin:
3784 : : * @type: #GType to retrieve the plugin for
3785 : : *
3786 : : * Returns the #GTypePlugin structure for @type.
3787 : : *
3788 : : * Returns: (transfer none): the corresponding plugin
3789 : : * if @type is a dynamic type, %NULL otherwise
3790 : : */
3791 : : GTypePlugin*
3792 : 4 : g_type_get_plugin (GType type)
3793 : : {
3794 : : TypeNode *node;
3795 : :
3796 : 4 : node = lookup_type_node_I (type);
3797 : :
3798 : 4 : return node ? node->plugin : NULL;
3799 : : }
3800 : :
3801 : : /**
3802 : : * g_type_interface_get_plugin:
3803 : : * @instance_type: #GType of an instantiatable type
3804 : : * @interface_type: #GType of an interface type
3805 : : *
3806 : : * Returns the #GTypePlugin structure for the dynamic interface
3807 : : * @interface_type which has been added to @instance_type, or %NULL
3808 : : * if @interface_type has not been added to @instance_type or does
3809 : : * not have a #GTypePlugin structure. See g_type_add_interface_dynamic().
3810 : : *
3811 : : * Returns: (transfer none): the #GTypePlugin for the dynamic
3812 : : * interface @interface_type of @instance_type
3813 : : */
3814 : : GTypePlugin*
3815 : 2 : g_type_interface_get_plugin (GType instance_type,
3816 : : GType interface_type)
3817 : : {
3818 : : TypeNode *node;
3819 : : TypeNode *iface;
3820 : :
3821 : 2 : g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL); /* G_TYPE_IS_INTERFACE() is an external call: _U */
3822 : :
3823 : 2 : node = lookup_type_node_I (instance_type);
3824 : 2 : iface = lookup_type_node_I (interface_type);
3825 : 2 : if (node && iface)
3826 : : {
3827 : : IFaceHolder *iholder;
3828 : : GTypePlugin *plugin;
3829 : :
3830 : 2 : G_READ_LOCK (&type_rw_lock);
3831 : :
3832 : 2 : iholder = iface_node_get_holders_L (iface);
3833 : 2 : while (iholder && iholder->instance_type != instance_type)
3834 : 0 : iholder = iholder->next;
3835 : 2 : plugin = iholder ? iholder->plugin : NULL;
3836 : :
3837 : 2 : G_READ_UNLOCK (&type_rw_lock);
3838 : :
3839 : 2 : return plugin;
3840 : : }
3841 : :
3842 : 0 : g_return_val_if_fail (node == NULL, NULL);
3843 : 0 : g_return_val_if_fail (iface == NULL, NULL);
3844 : :
3845 : 0 : g_critical (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
3846 : :
3847 : 0 : return NULL;
3848 : : }
3849 : :
3850 : : /**
3851 : : * g_type_fundamental_next:
3852 : : *
3853 : : * Returns the next free fundamental type id which can be used to
3854 : : * register a new fundamental type with g_type_register_fundamental().
3855 : : * The returned type ID represents the highest currently registered
3856 : : * fundamental type identifier.
3857 : : *
3858 : : * Returns: the next available fundamental type ID to be registered,
3859 : : * or 0 if the type system ran out of fundamental type IDs
3860 : : */
3861 : : GType
3862 : 17 : g_type_fundamental_next (void)
3863 : : {
3864 : : GType type;
3865 : :
3866 : 17 : G_READ_LOCK (&type_rw_lock);
3867 : 17 : type = static_fundamental_next;
3868 : 17 : G_READ_UNLOCK (&type_rw_lock);
3869 : 17 : type = G_TYPE_MAKE_FUNDAMENTAL (type);
3870 : 17 : return type <= G_TYPE_FUNDAMENTAL_MAX ? type : 0;
3871 : : }
3872 : :
3873 : : /**
3874 : : * g_type_fundamental:
3875 : : * @type_id: valid type ID
3876 : : *
3877 : : * Internal function, used to extract the fundamental type ID portion.
3878 : : * Use G_TYPE_FUNDAMENTAL() instead.
3879 : : *
3880 : : * Returns: fundamental type ID
3881 : : */
3882 : : GType
3883 : 12225816 : g_type_fundamental (GType type_id)
3884 : : {
3885 : 12225816 : TypeNode *node = lookup_type_node_I (type_id);
3886 : :
3887 : 12225816 : return node ? NODE_FUNDAMENTAL_TYPE (node) : 0;
3888 : : }
3889 : :
3890 : : gboolean
3891 : 19644882 : g_type_check_instance_is_a (GTypeInstance *type_instance,
3892 : : GType iface_type)
3893 : : {
3894 : : TypeNode *node, *iface;
3895 : : gboolean check;
3896 : :
3897 : 19644882 : if (!type_instance || !type_instance->g_class)
3898 : 0 : return FALSE;
3899 : :
3900 : 19644882 : iface = lookup_type_node_I (iface_type);
3901 : 19644882 : if (iface && iface->is_final)
3902 : 4 : return type_instance->g_class->g_type == iface_type;
3903 : :
3904 : 19644878 : node = lookup_type_node_I (type_instance->g_class->g_type);
3905 : 19644878 : check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
3906 : :
3907 : 19644878 : return check;
3908 : : }
3909 : :
3910 : : gboolean
3911 : 377873267 : g_type_check_instance_is_fundamentally_a (GTypeInstance *type_instance,
3912 : : GType fundamental_type)
3913 : : {
3914 : : TypeNode *node;
3915 : 377873267 : if (!type_instance || !type_instance->g_class)
3916 : 0 : return FALSE;
3917 : 377873267 : node = lookup_type_node_I (type_instance->g_class->g_type);
3918 : 377873267 : return node && (NODE_FUNDAMENTAL_TYPE(node) == fundamental_type);
3919 : : }
3920 : :
3921 : : gboolean
3922 : 40339 : g_type_check_class_is_a (GTypeClass *type_class,
3923 : : GType is_a_type)
3924 : : {
3925 : : TypeNode *node, *iface;
3926 : : gboolean check;
3927 : :
3928 : 40339 : if (!type_class)
3929 : 0 : return FALSE;
3930 : :
3931 : 40339 : node = lookup_type_node_I (type_class->g_type);
3932 : 40339 : iface = lookup_type_node_I (is_a_type);
3933 : 40339 : check = node && node->is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
3934 : :
3935 : 40339 : return check;
3936 : : }
3937 : :
3938 : : GTypeInstance*
3939 : 61970418 : g_type_check_instance_cast (GTypeInstance *type_instance,
3940 : : GType iface_type)
3941 : : {
3942 : 61970418 : if (type_instance)
3943 : : {
3944 : 61970370 : if (type_instance->g_class)
3945 : : {
3946 : : TypeNode *node, *iface;
3947 : : gboolean is_instantiatable, check;
3948 : :
3949 : 61970370 : node = lookup_type_node_I (type_instance->g_class->g_type);
3950 : 61970370 : is_instantiatable = node && node->is_instantiatable;
3951 : 61970370 : iface = lookup_type_node_I (iface_type);
3952 : 61970370 : check = is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
3953 : 61970370 : if (check)
3954 : 61970370 : return type_instance;
3955 : :
3956 : 0 : if (is_instantiatable)
3957 : 0 : g_critical ("invalid cast from '%s' to '%s'",
3958 : : type_descriptive_name_I (type_instance->g_class->g_type),
3959 : : type_descriptive_name_I (iface_type));
3960 : : else
3961 : 0 : g_critical ("invalid uninstantiatable type '%s' in cast to '%s'",
3962 : : type_descriptive_name_I (type_instance->g_class->g_type),
3963 : : type_descriptive_name_I (iface_type));
3964 : : }
3965 : : else
3966 : 0 : g_critical ("invalid unclassed pointer in cast to '%s'",
3967 : : type_descriptive_name_I (iface_type));
3968 : : }
3969 : :
3970 : 48 : return type_instance;
3971 : : }
3972 : :
3973 : : GTypeClass*
3974 : 9750457 : g_type_check_class_cast (GTypeClass *type_class,
3975 : : GType is_a_type)
3976 : : {
3977 : 9750457 : if (type_class)
3978 : : {
3979 : : TypeNode *node, *iface;
3980 : : gboolean is_classed, check;
3981 : :
3982 : 9750457 : node = lookup_type_node_I (type_class->g_type);
3983 : 9750457 : is_classed = node && node->is_classed;
3984 : 9750457 : iface = lookup_type_node_I (is_a_type);
3985 : 9750457 : check = is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
3986 : 9750457 : if (check)
3987 : 9750457 : return type_class;
3988 : :
3989 : 0 : if (is_classed)
3990 : 0 : g_critical ("invalid class cast from '%s' to '%s'",
3991 : : type_descriptive_name_I (type_class->g_type),
3992 : : type_descriptive_name_I (is_a_type));
3993 : : else
3994 : 0 : g_critical ("invalid unclassed type '%s' in class cast to '%s'",
3995 : : type_descriptive_name_I (type_class->g_type),
3996 : : type_descriptive_name_I (is_a_type));
3997 : : }
3998 : : else
3999 : 0 : g_critical ("invalid class cast from (NULL) pointer to '%s'",
4000 : : type_descriptive_name_I (is_a_type));
4001 : 0 : return type_class;
4002 : : }
4003 : :
4004 : : /**
4005 : : * g_type_check_instance:
4006 : : * @instance: a valid #GTypeInstance structure
4007 : : *
4008 : : * Private helper function to aid implementation of the
4009 : : * G_TYPE_CHECK_INSTANCE() macro.
4010 : : *
4011 : : * Returns: %TRUE if @instance is valid, %FALSE otherwise
4012 : : */
4013 : : gboolean
4014 : 37426006 : g_type_check_instance (GTypeInstance *type_instance)
4015 : : {
4016 : : /* this function is just here to make the signal system
4017 : : * conveniently elaborated on instance checks
4018 : : */
4019 : 37426006 : if (type_instance)
4020 : : {
4021 : 37426006 : if (type_instance->g_class)
4022 : : {
4023 : 37426006 : TypeNode *node = lookup_type_node_I (type_instance->g_class->g_type);
4024 : :
4025 : 37426006 : if (node && node->is_instantiatable)
4026 : 37426006 : return TRUE;
4027 : :
4028 : 0 : g_critical ("instance of invalid non-instantiatable type '%s'",
4029 : : type_descriptive_name_I (type_instance->g_class->g_type));
4030 : : }
4031 : : else
4032 : 0 : g_critical ("instance with invalid (NULL) class pointer");
4033 : : }
4034 : : else
4035 : 0 : g_critical ("invalid (NULL) pointer instance");
4036 : :
4037 : 0 : return FALSE;
4038 : : }
4039 : :
4040 : : static inline gboolean
4041 : 120998 : type_check_is_value_type_U (GType type)
4042 : : {
4043 : 120998 : GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT;
4044 : : TypeNode *node;
4045 : :
4046 : : /* common path speed up */
4047 : 120998 : node = lookup_type_node_I (type);
4048 : 120998 : if (node && node->mutatable_check_cache)
4049 : 88839 : return TRUE;
4050 : :
4051 : 32159 : G_READ_LOCK (&type_rw_lock);
4052 : 39741 : restart_check:
4053 : 39741 : if (node)
4054 : : {
4055 : 39735 : if (node->data &&
4056 : 39735 : node->data->common.value_table->value_init)
4057 : 32153 : tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
4058 : 7582 : else if (NODE_IS_IFACE (node))
4059 : : {
4060 : : guint i;
4061 : :
4062 : 7582 : for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
4063 : : {
4064 : 7582 : GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
4065 : 7582 : TypeNode *prnode = lookup_type_node_I (prtype);
4066 : :
4067 : 7582 : if (prnode->is_instantiatable)
4068 : : {
4069 : 7582 : type = prtype;
4070 : 7582 : node = lookup_type_node_I (type);
4071 : 7582 : goto restart_check;
4072 : : }
4073 : : }
4074 : : }
4075 : : }
4076 : 32159 : G_READ_UNLOCK (&type_rw_lock);
4077 : :
4078 : 32159 : return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT);
4079 : : }
4080 : :
4081 : : gboolean
4082 : 8331 : g_type_check_is_value_type (GType type)
4083 : : {
4084 : 8331 : return type_check_is_value_type_U (type);
4085 : : }
4086 : :
4087 : : gboolean
4088 : 15030 : g_type_check_value (const GValue *value)
4089 : : {
4090 : 15030 : return value && type_check_is_value_type_U (value->g_type);
4091 : : }
4092 : :
4093 : : gboolean
4094 : 97637 : g_type_check_value_holds (const GValue *value,
4095 : : GType type)
4096 : : {
4097 : 97637 : return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type);
4098 : : }
4099 : :
4100 : : /**
4101 : : * g_type_value_table_peek: (skip)
4102 : : * @type: a #GType
4103 : : *
4104 : : * Returns the location of the #GTypeValueTable associated with @type.
4105 : : *
4106 : : * Note that this function should only be used from source code
4107 : : * that implements or has internal knowledge of the implementation of
4108 : : * @type.
4109 : : *
4110 : : * Returns: (nullable) (transfer none): location of the #GTypeValueTable
4111 : : * associated with @type or %NULL if there is no #GTypeValueTable
4112 : : * associated with @type
4113 : : */
4114 : : GTypeValueTable *
4115 : 90959117 : g_type_value_table_peek (GType type)
4116 : : {
4117 : 90959117 : GTypeValueTable *vtable = NULL;
4118 : 90959117 : TypeNode *node = lookup_type_node_I (type);
4119 : : gboolean has_data, has_table;
4120 : :
4121 : 90959117 : if (node != NULL && node->mutatable_check_cache)
4122 : 82571768 : return node->data->common.value_table;
4123 : :
4124 : 8387349 : G_READ_LOCK (&type_rw_lock);
4125 : :
4126 : 8400135 : restart_table_peek:
4127 : 8400135 : has_data = node != NULL && node->data != NULL;
4128 : 8400135 : has_table = has_data && node->data->common.value_table->value_init;
4129 : 8400135 : if (has_data)
4130 : : {
4131 : 8400135 : if (has_table)
4132 : 8387349 : vtable = node->data->common.value_table;
4133 : 12786 : else if (NODE_IS_IFACE (node))
4134 : : {
4135 : : guint i;
4136 : :
4137 : 12786 : for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++)
4138 : : {
4139 : 12786 : GType prtype = IFACE_NODE_PREREQUISITES (node)[i];
4140 : 12786 : TypeNode *prnode = lookup_type_node_I (prtype);
4141 : :
4142 : 12786 : if (prnode->is_instantiatable)
4143 : : {
4144 : 12786 : type = prtype;
4145 : 12786 : node = lookup_type_node_I (type);
4146 : 12786 : goto restart_table_peek;
4147 : : }
4148 : : }
4149 : : }
4150 : : }
4151 : :
4152 : 8387349 : G_READ_UNLOCK (&type_rw_lock);
4153 : :
4154 : 8387349 : if (vtable)
4155 : 8387349 : return vtable;
4156 : :
4157 : 0 : if (!node)
4158 : 0 : g_critical (G_STRLOC ": type id '%" G_GUINTPTR_FORMAT "' is invalid", (guintptr) type);
4159 : 0 : if (!has_data)
4160 : 0 : g_critical ("can't peek value table for type '%s' which is not currently referenced",
4161 : : type_descriptive_name_I (type));
4162 : :
4163 : 0 : return NULL;
4164 : : }
4165 : :
4166 : : const gchar *
4167 : 26 : g_type_name_from_instance (GTypeInstance *instance)
4168 : : {
4169 : 26 : if (!instance)
4170 : 0 : return "<NULL-instance>";
4171 : : else
4172 : 26 : return g_type_name_from_class (instance->g_class);
4173 : : }
4174 : :
4175 : : const gchar *
4176 : 26 : g_type_name_from_class (GTypeClass *g_class)
4177 : : {
4178 : 26 : if (!g_class)
4179 : 0 : return "<NULL-class>";
4180 : : else
4181 : 26 : return g_type_name (g_class->g_type);
4182 : : }
4183 : :
4184 : :
4185 : : /* --- private api for gboxed.c --- */
4186 : : gpointer
4187 : 946 : _g_type_boxed_copy (GType type, gpointer value)
4188 : : {
4189 : 946 : TypeNode *node = lookup_type_node_I (type);
4190 : :
4191 : 946 : return node->data->boxed.copy_func (value);
4192 : : }
4193 : :
4194 : : void
4195 : 623 : _g_type_boxed_free (GType type, gpointer value)
4196 : : {
4197 : 623 : TypeNode *node = lookup_type_node_I (type);
4198 : :
4199 : 623 : node->data->boxed.free_func (value);
4200 : 623 : }
4201 : :
4202 : : void
4203 : 1398 : _g_type_boxed_init (GType type,
4204 : : GBoxedCopyFunc copy_func,
4205 : : GBoxedFreeFunc free_func)
4206 : : {
4207 : 1398 : TypeNode *node = lookup_type_node_I (type);
4208 : :
4209 : 1398 : node->data->boxed.copy_func = copy_func;
4210 : 1398 : node->data->boxed.free_func = free_func;
4211 : 1398 : }
4212 : :
4213 : : /* --- initialization --- */
4214 : : /**
4215 : : * g_type_init_with_debug_flags:
4216 : : * @debug_flags: bitwise combination of #GTypeDebugFlags values for
4217 : : * debugging purposes
4218 : : *
4219 : : * This function used to initialise the type system with debugging
4220 : : * flags. Since GLib 2.36, the type system is initialised automatically
4221 : : * and this function does nothing.
4222 : : *
4223 : : * If you need to enable debugging features, use the `GOBJECT_DEBUG`
4224 : : * environment variable.
4225 : : *
4226 : : * Deprecated: 2.36: the type system is now initialised automatically
4227 : : */
4228 : : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
4229 : : void
4230 : 0 : g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
4231 : : {
4232 : 0 : g_assert_type_system_initialized ();
4233 : :
4234 : 0 : if (debug_flags)
4235 : 0 : g_message ("g_type_init_with_debug_flags() is no longer supported. Use the GOBJECT_DEBUG environment variable.");
4236 : 0 : }
4237 : : G_GNUC_END_IGNORE_DEPRECATIONS
4238 : :
4239 : : /**
4240 : : * g_type_init:
4241 : : *
4242 : : * This function used to initialise the type system. Since GLib 2.36,
4243 : : * the type system is initialised automatically and this function does
4244 : : * nothing.
4245 : : *
4246 : : * Deprecated: 2.36: the type system is now initialised automatically
4247 : : */
4248 : : void
4249 : 0 : g_type_init (void)
4250 : : {
4251 : 0 : g_assert_type_system_initialized ();
4252 : 0 : }
4253 : :
4254 : : static void
4255 : 588 : gobject_init (void)
4256 : : {
4257 : : const gchar *env_string;
4258 : : GTypeInfo info;
4259 : : TypeNode *node;
4260 : : GType type G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */;
4261 : :
4262 : : /* Ensure GLib is initialized first, see
4263 : : * https://bugzilla.gnome.org/show_bug.cgi?id=756139
4264 : : */
4265 : 588 : GLIB_PRIVATE_CALL (glib_init) ();
4266 : :
4267 : 588 : G_WRITE_LOCK (&type_rw_lock);
4268 : :
4269 : : /* setup GObject library wide debugging flags */
4270 : 588 : env_string = g_getenv ("GOBJECT_DEBUG");
4271 : 588 : if (env_string != NULL)
4272 : : {
4273 : 0 : GDebugKey debug_keys[] = {
4274 : : { "objects", G_TYPE_DEBUG_OBJECTS },
4275 : : { "instance-count", G_TYPE_DEBUG_INSTANCE_COUNT },
4276 : : { "signals", G_TYPE_DEBUG_SIGNALS },
4277 : : };
4278 : :
4279 : 0 : _g_type_debug_flags = g_parse_debug_string (env_string, debug_keys, G_N_ELEMENTS (debug_keys));
4280 : : }
4281 : :
4282 : : /* quarks */
4283 : 588 : static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
4284 : 588 : static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
4285 : 588 : static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
4286 : :
4287 : : /* type qname hash table */
4288 : 588 : static_type_nodes_ht = g_hash_table_new (g_str_hash, g_str_equal);
4289 : :
4290 : : /* invalid type G_TYPE_INVALID (0)
4291 : : */
4292 : 588 : static_fundamental_type_nodes[0] = NULL;
4293 : :
4294 : : /* void type G_TYPE_NONE
4295 : : */
4296 : 588 : node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0);
4297 : 588 : type = NODE_TYPE (node);
4298 : 588 : g_assert (type == G_TYPE_NONE);
4299 : :
4300 : : /* interface fundamental type G_TYPE_INTERFACE (!classed)
4301 : : */
4302 : 588 : memset (&info, 0, sizeof (info));
4303 : 588 : node = type_node_fundamental_new_W (G_TYPE_INTERFACE, g_intern_static_string ("GInterface"), G_TYPE_FLAG_DERIVABLE);
4304 : 588 : type = NODE_TYPE (node);
4305 : 588 : type_data_make_W (node, &info, NULL);
4306 : 588 : g_assert (type == G_TYPE_INTERFACE);
4307 : :
4308 : 588 : G_WRITE_UNLOCK (&type_rw_lock);
4309 : :
4310 : 588 : _g_value_c_init ();
4311 : :
4312 : : /* G_TYPE_TYPE_PLUGIN
4313 : : */
4314 : 588 : g_type_ensure (g_type_plugin_get_type ());
4315 : :
4316 : : /* G_TYPE_* value types
4317 : : */
4318 : 588 : _g_value_types_init ();
4319 : :
4320 : : /* G_TYPE_ENUM & G_TYPE_FLAGS
4321 : : */
4322 : 588 : _g_enum_types_init ();
4323 : :
4324 : : /* G_TYPE_BOXED
4325 : : */
4326 : 588 : _g_boxed_type_init ();
4327 : :
4328 : : /* G_TYPE_PARAM
4329 : : */
4330 : 588 : _g_param_type_init ();
4331 : :
4332 : : /* G_TYPE_OBJECT
4333 : : */
4334 : 588 : _g_object_type_init ();
4335 : :
4336 : : /* G_TYPE_PARAM_* pspec types
4337 : : */
4338 : 588 : _g_param_spec_types_init ();
4339 : :
4340 : : /* Value Transformations
4341 : : */
4342 : 588 : _g_value_transforms_init ();
4343 : :
4344 : : /* Signal system
4345 : : */
4346 : 588 : _g_signal_init ();
4347 : 588 : }
4348 : :
4349 : : #ifdef G_PLATFORM_WIN32
4350 : :
4351 : : void gobject_win32_init (void);
4352 : :
4353 : : void
4354 : : gobject_win32_init (void)
4355 : : {
4356 : : /* May be called more than once in static compilation mode */
4357 : : static gboolean win32_already_init = FALSE;
4358 : : if (!win32_already_init)
4359 : : {
4360 : : win32_already_init = TRUE;
4361 : : gobject_init ();
4362 : : }
4363 : : }
4364 : :
4365 : : #ifndef GLIB_STATIC_COMPILATION
4366 : :
4367 : : BOOL WINAPI DllMain (HINSTANCE hinstDLL,
4368 : : DWORD fdwReason,
4369 : : LPVOID lpvReserved);
4370 : :
4371 : : BOOL WINAPI
4372 : : DllMain (HINSTANCE hinstDLL,
4373 : : DWORD fdwReason,
4374 : : LPVOID lpvReserved)
4375 : : {
4376 : : switch (fdwReason)
4377 : : {
4378 : : case DLL_PROCESS_ATTACH:
4379 : : gobject_win32_init ();
4380 : : break;
4381 : :
4382 : : default:
4383 : : /* do nothing */
4384 : : ;
4385 : : }
4386 : :
4387 : : return TRUE;
4388 : : }
4389 : :
4390 : : #elif defined(G_HAS_CONSTRUCTORS) /* && G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION */
4391 : : extern void glib_win32_init (void);
4392 : :
4393 : : #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
4394 : : #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(gobject_init_ctor)
4395 : : #endif
4396 : :
4397 : : G_DEFINE_CONSTRUCTOR(gobject_init_ctor)
4398 : :
4399 : : static void
4400 : : gobject_init_ctor (void)
4401 : : {
4402 : : /* When built dynamically, module initialization is done through DllMain
4403 : : * function which is called when the dynamic library is loaded by the glib
4404 : : * module. So, in dynamic configuration glib is always initialized BEFORE
4405 : : * gobject.
4406 : : *
4407 : : * When built statically, initialization mechanism relies on hooking
4408 : : * functions to the CRT section directly at compilation time. As we don't
4409 : : * control how each compilation unit will be built and in which order, we
4410 : : * obtain the same kind of issue as the "static initialization order fiasco".
4411 : : * In this case, we must ensure explicitly that glib is always well
4412 : : * initialized BEFORE gobject.
4413 : : */
4414 : : glib_win32_init ();
4415 : : gobject_win32_init ();
4416 : : }
4417 : :
4418 : : #else /* G_PLATFORM_WIN32 && GLIB_STATIC_COMPILATION && !G_HAS_CONSTRUCTORS */
4419 : : # error Your platform/compiler is missing constructor support
4420 : : #endif /* GLIB_STATIC_COMPILATION */
4421 : :
4422 : : #elif defined(G_HAS_CONSTRUCTORS) /* && !G_PLATFORM_WIN32 */
4423 : :
4424 : : #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
4425 : : #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(gobject_init_ctor)
4426 : : #endif
4427 : :
4428 : : G_DEFINE_CONSTRUCTOR (gobject_init_ctor)
4429 : :
4430 : : static void
4431 : 588 : gobject_init_ctor (void)
4432 : : {
4433 : 588 : gobject_init ();
4434 : 588 : }
4435 : :
4436 : : #else /* !G_PLATFORM_WIN32 && !G_HAS_CONSTRUCTORS */
4437 : : #error Your platform/compiler is missing constructor support
4438 : : #endif /* G_PLATFORM_WIN32 */
4439 : :
4440 : : /**
4441 : : * g_type_class_add_private:
4442 : : * @g_class: (type GObject.TypeClass): class structure for an instantiatable
4443 : : * type
4444 : : * @private_size: size of private structure
4445 : : *
4446 : : * Registers a private structure for an instantiatable type.
4447 : : *
4448 : : * When an object is allocated, the private structures for
4449 : : * the type and all of its parent types are allocated
4450 : : * sequentially in the same memory block as the public
4451 : : * structures, and are zero-filled.
4452 : : *
4453 : : * Note that the accumulated size of the private structures of
4454 : : * a type and all its parent types cannot exceed 64 KiB.
4455 : : *
4456 : : * This function should be called in the type's class_init() function.
4457 : : * The private structure can be retrieved using the
4458 : : * G_TYPE_INSTANCE_GET_PRIVATE() macro.
4459 : : *
4460 : : * The following example shows attaching a private structure
4461 : : * MyObjectPrivate to an object MyObject defined in the standard
4462 : : * GObject fashion in the type's class_init() function.
4463 : : *
4464 : : * Note the use of a structure member "priv" to avoid the overhead
4465 : : * of repeatedly calling MY_OBJECT_GET_PRIVATE().
4466 : : *
4467 : : * |[<!-- language="C" -->
4468 : : * typedef struct _MyObject MyObject;
4469 : : * typedef struct _MyObjectPrivate MyObjectPrivate;
4470 : : *
4471 : : * struct _MyObject {
4472 : : * GObject parent;
4473 : : *
4474 : : * MyObjectPrivate *priv;
4475 : : * };
4476 : : *
4477 : : * struct _MyObjectPrivate {
4478 : : * int some_field;
4479 : : * };
4480 : : *
4481 : : * static void
4482 : : * my_object_class_init (MyObjectClass *klass)
4483 : : * {
4484 : : * g_type_class_add_private (klass, sizeof (MyObjectPrivate));
4485 : : * }
4486 : : *
4487 : : * static void
4488 : : * my_object_init (MyObject *my_object)
4489 : : * {
4490 : : * my_object->priv = G_TYPE_INSTANCE_GET_PRIVATE (my_object,
4491 : : * MY_TYPE_OBJECT,
4492 : : * MyObjectPrivate);
4493 : : * // my_object->priv->some_field will be automatically initialised to 0
4494 : : * }
4495 : : *
4496 : : * static int
4497 : : * my_object_get_some_field (MyObject *my_object)
4498 : : * {
4499 : : * MyObjectPrivate *priv;
4500 : : *
4501 : : * g_return_val_if_fail (MY_IS_OBJECT (my_object), 0);
4502 : : *
4503 : : * priv = my_object->priv;
4504 : : *
4505 : : * return priv->some_field;
4506 : : * }
4507 : : * ]|
4508 : : *
4509 : : * Since: 2.4
4510 : : * Deprecated: 2.58: Use the G_ADD_PRIVATE() macro with the `G_DEFINE_*`
4511 : : * family of macros to add instance private data to a type
4512 : : */
4513 : : void
4514 : 15 : g_type_class_add_private (gpointer g_class,
4515 : : gsize private_size)
4516 : : {
4517 : 15 : GType instance_type = ((GTypeClass *)g_class)->g_type;
4518 : 15 : TypeNode *node = lookup_type_node_I (instance_type);
4519 : :
4520 : 15 : g_return_if_fail (private_size > 0);
4521 : 15 : g_return_if_fail (private_size <= 0xffff);
4522 : :
4523 : 15 : if (!node || !node->is_instantiatable || !node->data || node->data->class.class != g_class)
4524 : : {
4525 : 0 : g_critical ("cannot add private field to invalid (non-instantiatable) type '%s'",
4526 : : type_descriptive_name_I (instance_type));
4527 : 0 : return;
4528 : : }
4529 : :
4530 : 15 : if (NODE_PARENT_TYPE (node))
4531 : : {
4532 : 15 : TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
4533 : 15 : if (node->data->instance.private_size != pnode->data->instance.private_size)
4534 : : {
4535 : 0 : g_critical ("g_type_class_add_private() called multiple times for the same type");
4536 : 0 : return;
4537 : : }
4538 : : }
4539 : :
4540 : 15 : G_WRITE_LOCK (&type_rw_lock);
4541 : :
4542 : 15 : private_size = ALIGN_STRUCT (node->data->instance.private_size + private_size);
4543 : 15 : g_assert (private_size <= 0xffff);
4544 : 15 : node->data->instance.private_size = private_size;
4545 : :
4546 : 15 : G_WRITE_UNLOCK (&type_rw_lock);
4547 : : }
4548 : :
4549 : : /* semi-private, called only by the G_ADD_PRIVATE macro */
4550 : : gint
4551 : 5631 : g_type_add_instance_private (GType class_gtype,
4552 : : gsize private_size)
4553 : : {
4554 : 5631 : TypeNode *node = lookup_type_node_I (class_gtype);
4555 : :
4556 : 5631 : g_return_val_if_fail (private_size > 0, 0);
4557 : 5631 : g_return_val_if_fail (private_size <= 0xffff, 0);
4558 : :
4559 : 5631 : if (!node || !node->is_classed || !node->is_instantiatable || !node->data)
4560 : : {
4561 : 0 : g_critical ("cannot add private field to invalid (non-instantiatable) type '%s'",
4562 : : type_descriptive_name_I (class_gtype));
4563 : 0 : return 0;
4564 : : }
4565 : :
4566 : 5631 : if (node->plugin != NULL)
4567 : : {
4568 : 0 : g_critical ("cannot use g_type_add_instance_private() with dynamic type '%s'",
4569 : : type_descriptive_name_I (class_gtype));
4570 : 0 : return 0;
4571 : : }
4572 : :
4573 : : /* in the future, we want to register the private data size of a type
4574 : : * directly from the get_type() implementation so that we can take full
4575 : : * advantage of the type definition macros that we already have.
4576 : : *
4577 : : * unfortunately, this does not behave correctly if a class in the middle
4578 : : * of the type hierarchy uses the "old style" of private data registration
4579 : : * from the class_init() implementation, as the private data offset is not
4580 : : * going to be known until the full class hierarchy is initialized.
4581 : : *
4582 : : * in order to transition our code to the Glorious New Futureā¢, we proceed
4583 : : * with a two-step implementation: first, we provide this new function to
4584 : : * register the private data size in the get_type() implementation and we
4585 : : * hide it behind a macro. the function will return the private size, instead
4586 : : * of the offset, which will be stored inside a static variable defined by
4587 : : * the G_DEFINE_TYPE_EXTENDED() macro. the G_DEFINE_TYPE_EXTENDED() macro will
4588 : : * check the variable and call g_type_class_adjust_private_offset(), which
4589 : : * will use the data size and actually register the private data, then
4590 : : * return the computed offset of the private data, which will be stored
4591 : : * inside the static variable, so we can use it to retrieve the pointer
4592 : : * to the private data structure.
4593 : : *
4594 : : * once all our code has been migrated to the new idiomatic form of private
4595 : : * data registration, we will change the g_type_add_instance_private()
4596 : : * function to actually perform the registration and return the offset
4597 : : * of the private data; g_type_class_adjust_private_offset() already checks
4598 : : * if the passed argument is negative (meaning that it's an offset in the
4599 : : * GTypeInstance allocation) and becomes a no-op if that's the case. this
4600 : : * should make the migration fully transparent even if we're effectively
4601 : : * copying this macro into everybody's code.
4602 : : */
4603 : 5631 : return (gint) private_size;
4604 : : }
4605 : :
4606 : : /* semi-private function, should only be used by G_DEFINE_TYPE_EXTENDED */
4607 : : void
4608 : 4044 : g_type_class_adjust_private_offset (gpointer g_class,
4609 : : gint *private_size_or_offset)
4610 : : {
4611 : 4044 : GType class_gtype = ((GTypeClass *) g_class)->g_type;
4612 : 4044 : TypeNode *node = lookup_type_node_I (class_gtype);
4613 : : size_t private_size;
4614 : :
4615 : 4044 : g_return_if_fail (private_size_or_offset != NULL);
4616 : :
4617 : : /* if we have been passed the offset instead of the private data size,
4618 : : * then we consider this as a no-op, and just return the value. see the
4619 : : * comment in g_type_add_instance_private() for the full explanation.
4620 : : */
4621 : 4044 : if (*private_size_or_offset > 0)
4622 : 4044 : g_return_if_fail (*private_size_or_offset <= 0xffff);
4623 : : else
4624 : 0 : return;
4625 : :
4626 : 4044 : if (!node || !node->is_classed || !node->is_instantiatable || !node->data)
4627 : : {
4628 : 0 : g_critical ("cannot add private field to invalid (non-instantiatable) type '%s'",
4629 : : type_descriptive_name_I (class_gtype));
4630 : 0 : *private_size_or_offset = 0;
4631 : 0 : return;
4632 : : }
4633 : :
4634 : 4044 : if (NODE_PARENT_TYPE (node))
4635 : : {
4636 : 3456 : TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
4637 : 3456 : if (node->data->instance.private_size != pnode->data->instance.private_size)
4638 : : {
4639 : 0 : g_critical ("g_type_add_instance_private() called multiple times for the same type");
4640 : 0 : *private_size_or_offset = 0;
4641 : 0 : return;
4642 : : }
4643 : : }
4644 : :
4645 : 4044 : G_WRITE_LOCK (&type_rw_lock);
4646 : :
4647 : 4044 : private_size = ALIGN_STRUCT (node->data->instance.private_size + *private_size_or_offset);
4648 : 4044 : g_assert (private_size <= 0xffff);
4649 : 4044 : node->data->instance.private_size = private_size;
4650 : :
4651 : 4044 : *private_size_or_offset = -(gint) node->data->instance.private_size;
4652 : :
4653 : 4044 : G_WRITE_UNLOCK (&type_rw_lock);
4654 : : }
4655 : :
4656 : : gpointer
4657 : 33 : g_type_instance_get_private (GTypeInstance *instance,
4658 : : GType private_type)
4659 : : {
4660 : : TypeNode *node;
4661 : :
4662 : 33 : g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
4663 : :
4664 : 33 : node = lookup_type_node_I (private_type);
4665 : 33 : if (G_UNLIKELY (!node || !node->is_instantiatable))
4666 : : {
4667 : 0 : g_critical ("instance of invalid non-instantiatable type '%s'",
4668 : : type_descriptive_name_I (instance->g_class->g_type));
4669 : 0 : return NULL;
4670 : : }
4671 : :
4672 : 33 : return ((gchar *) instance) - node->data->instance.private_size;
4673 : : }
4674 : :
4675 : : /**
4676 : : * g_type_class_get_instance_private_offset: (skip)
4677 : : * @g_class: (type GObject.TypeClass): a #GTypeClass
4678 : : *
4679 : : * Gets the offset of the private data for instances of @g_class.
4680 : : *
4681 : : * This is how many bytes you should add to the instance pointer of a
4682 : : * class in order to get the private data for the type represented by
4683 : : * @g_class.
4684 : : *
4685 : : * You can only call this function after you have registered a private
4686 : : * data area for @g_class using g_type_class_add_private().
4687 : : *
4688 : : * Returns: the offset, in bytes
4689 : : *
4690 : : * Since: 2.38
4691 : : **/
4692 : : gint
4693 : 1 : g_type_class_get_instance_private_offset (gpointer g_class)
4694 : : {
4695 : : GType instance_type;
4696 : : guint16 parent_size;
4697 : : TypeNode *node;
4698 : :
4699 : 1 : g_assert (g_class != NULL);
4700 : :
4701 : 1 : instance_type = ((GTypeClass *) g_class)->g_type;
4702 : 1 : node = lookup_type_node_I (instance_type);
4703 : :
4704 : 1 : g_assert (node != NULL);
4705 : 1 : g_assert (node->is_instantiatable);
4706 : :
4707 : 1 : if (NODE_PARENT_TYPE (node))
4708 : : {
4709 : 1 : TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
4710 : :
4711 : 1 : parent_size = pnode->data->instance.private_size;
4712 : : }
4713 : : else
4714 : 0 : parent_size = 0;
4715 : :
4716 : 1 : if (node->data->instance.private_size == parent_size)
4717 : 0 : g_error ("g_type_class_get_instance_private_offset() called on class %s but it has no private data",
4718 : : g_type_name (instance_type));
4719 : :
4720 : 1 : return -(gint) node->data->instance.private_size;
4721 : : }
4722 : :
4723 : : /**
4724 : : * g_type_add_class_private:
4725 : : * @class_type: GType of a classed type
4726 : : * @private_size: size of private structure
4727 : : *
4728 : : * Registers a private class structure for a classed type;
4729 : : * when the class is allocated, the private structures for
4730 : : * the class and all of its parent types are allocated
4731 : : * sequentially in the same memory block as the public
4732 : : * structures, and are zero-filled.
4733 : : *
4734 : : * This function should be called in the
4735 : : * type's get_type() function after the type is registered.
4736 : : * The private structure can be retrieved using the
4737 : : * G_TYPE_CLASS_GET_PRIVATE() macro.
4738 : : *
4739 : : * Since: 2.24
4740 : : */
4741 : : void
4742 : 1 : g_type_add_class_private (GType class_type,
4743 : : gsize private_size)
4744 : : {
4745 : 1 : TypeNode *node = lookup_type_node_I (class_type);
4746 : : gsize offset;
4747 : :
4748 : 1 : g_return_if_fail (private_size > 0);
4749 : :
4750 : 1 : if (!node || !node->is_classed || !node->data)
4751 : : {
4752 : 0 : g_critical ("cannot add class private field to invalid type '%s'",
4753 : : type_descriptive_name_I (class_type));
4754 : 0 : return;
4755 : : }
4756 : :
4757 : 1 : if (NODE_PARENT_TYPE (node))
4758 : : {
4759 : 1 : TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
4760 : 1 : if (node->data->class.class_private_size != pnode->data->class.class_private_size)
4761 : : {
4762 : 0 : g_critical ("g_type_add_class_private() called multiple times for the same type");
4763 : 0 : return;
4764 : : }
4765 : : }
4766 : :
4767 : 1 : G_WRITE_LOCK (&type_rw_lock);
4768 : :
4769 : 1 : offset = ALIGN_STRUCT (node->data->class.class_private_size);
4770 : 1 : node->data->class.class_private_size = offset + private_size;
4771 : :
4772 : 1 : G_WRITE_UNLOCK (&type_rw_lock);
4773 : : }
4774 : :
4775 : : gpointer
4776 : 1 : g_type_class_get_private (GTypeClass *klass,
4777 : : GType private_type)
4778 : : {
4779 : : TypeNode *class_node;
4780 : : TypeNode *private_node;
4781 : : TypeNode *parent_node;
4782 : : gsize offset;
4783 : :
4784 : 1 : g_return_val_if_fail (klass != NULL, NULL);
4785 : :
4786 : 1 : class_node = lookup_type_node_I (klass->g_type);
4787 : 1 : if (G_UNLIKELY (!class_node || !class_node->is_classed))
4788 : : {
4789 : 0 : g_critical ("class of invalid type '%s'",
4790 : : type_descriptive_name_I (klass->g_type));
4791 : 0 : return NULL;
4792 : : }
4793 : :
4794 : 1 : private_node = lookup_type_node_I (private_type);
4795 : 1 : if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, class_node)))
4796 : : {
4797 : 0 : g_critical ("attempt to retrieve private data for invalid type '%s'",
4798 : : type_descriptive_name_I (private_type));
4799 : 0 : return NULL;
4800 : : }
4801 : :
4802 : 1 : offset = ALIGN_STRUCT (class_node->data->class.class_size);
4803 : :
4804 : 1 : if (NODE_PARENT_TYPE (private_node))
4805 : : {
4806 : 1 : parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
4807 : 1 : g_assert (parent_node->data);
4808 : :
4809 : 1 : if (G_UNLIKELY (private_node->data->class.class_private_size == parent_node->data->class.class_private_size))
4810 : : {
4811 : 0 : g_critical ("g_type_instance_get_class_private() requires a prior call to g_type_add_class_private()");
4812 : 0 : return NULL;
4813 : : }
4814 : :
4815 : 1 : offset += ALIGN_STRUCT (parent_node->data->class.class_private_size);
4816 : : }
4817 : :
4818 : 1 : return G_STRUCT_MEMBER_P (klass, offset);
4819 : : }
4820 : :
4821 : : /**
4822 : : * g_type_ensure:
4823 : : * @type: a #GType
4824 : : *
4825 : : * Ensures that the indicated @type has been registered with the
4826 : : * type system, and its _class_init() method has been run.
4827 : : *
4828 : : * In theory, simply calling the type's _get_type() method (or using
4829 : : * the corresponding macro) is supposed take care of this. However,
4830 : : * _get_type() methods are often marked %G_GNUC_CONST for performance
4831 : : * reasons, even though this is technically incorrect (since
4832 : : * %G_GNUC_CONST requires that the function not have side effects,
4833 : : * which _get_type() methods do on the first call). As a result, if
4834 : : * you write a bare call to a _get_type() macro, it may get optimized
4835 : : * out by the compiler. Using g_type_ensure() guarantees that the
4836 : : * type's _get_type() method is called.
4837 : : *
4838 : : * Since: 2.34
4839 : : */
4840 : : void
4841 : 1247896 : g_type_ensure (GType type)
4842 : : {
4843 : : /* In theory, @type has already been resolved and so there's nothing
4844 : : * to do here. But this protects us in the case where the function
4845 : : * gets inlined (as it might in gobject_init_ctor() above).
4846 : : */
4847 : 1247896 : if (G_UNLIKELY (type == (GType)-1))
4848 : 0 : g_error ("can't happen");
4849 : 1247896 : }
4850 : :
4851 : : void
4852 : 0 : g_destroy_notify_assert_not_reached (gpointer object)
4853 : : {
4854 : : g_return_if_reached ();
4855 : : }
|