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