gtype.c 148 KB
Newer Older
1
/* GObject - GLib Type, Object, Parameter and Signal Library
2
 * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc.
3
 *
4
5
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
6
7
8
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
swilmet's avatar
swilmet committed
9
 * version 2.1 of the License, or (at your option) any later version.
10
11
12
13
14
15
16
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * 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
22
23
24
25

/*
 * MT safe
 */

#include "config.h"

26
#include "../glib/gvalgrind.h"
27
28
29
#include <string.h>

#include "gtype.h"
30
#include "gtype-private.h"
31
32
#include "gtypeplugin.h"
#include "gvaluecollector.h"
33
#include "gatomicarray.h"
34
#include "gobject_trace.h"
35

36
#include "glib-private.h"
37
#include "gconstructor.h"
38

39
40
41
42
#ifdef G_OS_WIN32
#include <windows.h>
#endif

43
44
45
#ifdef	G_ENABLE_DEBUG
#define	IF_DEBUG(debug_type)	if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
#endif
46

Stefan Kost's avatar
Stefan Kost committed
47
48
/**
 * SECTION:gtype
Matthias Clasen's avatar
Matthias Clasen committed
49
50
51
 * @short_description: The GLib Runtime type identification and
 *     management system
 * @title:Type Information
52
 *
53
 * The GType API is the foundation of the GObject system. It provides the
Stefan Kost's avatar
Stefan Kost committed
54
 * facilities for registering and managing all fundamental data types,
55
 * user-defined object and interface types.
56
 *
Stefan Kost's avatar
Stefan Kost committed
57
58
59
60
61
 * For type creation and registration purposes, all types fall into one of
 * two categories: static or dynamic.  Static types are never loaded or
 * unloaded at run-time as dynamic types may be.  Static types are created
 * with g_type_register_static() that gets type specific information passed
 * in via a #GTypeInfo structure.
62
 *
Stefan Kost's avatar
Stefan Kost committed
63
64
65
66
 * Dynamic types are created with g_type_register_dynamic() which takes a
 * #GTypePlugin structure instead. The remaining type information (the
 * #GTypeInfo structure) is retrieved during runtime through #GTypePlugin
 * and the g_type_plugin_*() API.
67
 *
68
69
 * These registration functions are usually called only once from a
 * function whose only purpose is to return the type identifier for a
Stefan Kost's avatar
Stefan Kost committed
70
71
72
 * specific class.  Once the type (or class or interface) is registered,
 * it may be instantiated, inherited, or implemented depending on exactly
 * what sort of type it is.
73
 *
Stefan Kost's avatar
Stefan Kost committed
74
75
76
77
 * There is also a third registration function for registering fundamental
 * types called g_type_register_fundamental() which requires both a #GTypeInfo
 * structure and a #GTypeFundamentalInfo structure but it is seldom used
 * since most fundamental types are predefined rather than user-defined.
78
 *
79
80
 * Type instance and class structs are limited to a total of 64 KiB,
 * including all parent types. Similarly, type instances' private data
81
 * (as created by G_ADD_PRIVATE()) are limited to a total of
82
83
84
85
 * 64 KiB. If a type instance needs a large static buffer, allocate it
 * separately (typically by using #GArray or #GPtrArray) and put a pointer
 * to the buffer in the structure.
 *
86
87
88
89
 * As mentioned in the [GType conventions][gtype-conventions], type names must
 * be at least three characters long. There is no upper length limit. The first
 * character must be a letter (a–z or A–Z) or an underscore (‘_’). Subsequent
 * characters can be letters, numbers or any of ‘-_+’.
Stefan Kost's avatar
Stefan Kost committed
90
 */
91
92
93
94
95
96


/* NOTE: some functions (some internal variants and exported ones)
 * invalidate data portions of the TypeNodes. if external functions/callbacks
 * are called, pointers to memory maintained by TypeNodes have to be looked up
 * again. this affects most of the struct TypeNode fields, e.g. ->children or
97
98
99
 * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but
 * not ->supers[]), as all those memory portions can get realloc()ed during
 * callback invocation.
100
 *
101
102
103
104
105
106
107
108
109
110
111
112
113
 * LOCKING:
 * lock handling issues when calling static functions are indicated by
 * uppercase letter postfixes, all static functions have to have
 * one of the below postfixes:
 * - _I:	[Indifferent about locking]
 *   function doesn't care about locks at all
 * - _U:	[Unlocked invocation]
 *   no read or write lock has to be held across function invocation
 *   (locks may be acquired and released during invocation though)
 * - _L:	[Locked invocation]
 *   a write lock or more than 0 read locks have to be held across
 *   function invocation
 * - _W:	[Write-locked invocation]
114
 *   a write lock has to be held across function invocation
115
116
117
 * - _Wm:	[Write-locked invocation, mutatable]
 *   like _W, but the write lock might be released and reacquired
 *   during invocation, watch your pointers
118
119
 * - _WmREC:    [Write-locked invocation, mutatable, recursive]
 *   like _Wm, but also acquires recursive mutex class_init_rec_mutex
120
121
 */

122
#ifdef LOCK_DEBUG
123
124
125
126
#define G_READ_LOCK(rw_lock)    do { g_printerr (G_STRLOC ": readL++\n"); g_rw_lock_reader_lock (rw_lock); } while (0)
#define G_READ_UNLOCK(rw_lock)  do { g_printerr (G_STRLOC ": readL--\n"); g_rw_lock_reader_unlock (rw_lock); } while (0)
#define G_WRITE_LOCK(rw_lock)   do { g_printerr (G_STRLOC ": writeL++\n"); g_rw_lock_writer_lock (rw_lock); } while (0)
#define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_rw_lock_writer_unlock (rw_lock); } while (0)
127
#else
128
129
130
131
#define G_READ_LOCK(rw_lock)    g_rw_lock_reader_lock (rw_lock)
#define G_READ_UNLOCK(rw_lock)  g_rw_lock_reader_unlock (rw_lock)
#define G_WRITE_LOCK(rw_lock)   g_rw_lock_writer_lock (rw_lock)
#define G_WRITE_UNLOCK(rw_lock) g_rw_lock_writer_unlock (rw_lock)
132
#endif
133
#define	INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
134
    static const gchar _action[] = " invalidly modified type ";  \
Havoc Pennington's avatar
Havoc Pennington committed
135
    gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \
136
    if (_arg) \
137
      g_error ("%s(%p)%s'%s'", _fname, _arg, _action, _tname); \
138
    else \
139
      g_error ("%s()%s'%s'", _fname, _action, _tname); \
140
}G_STMT_END
141
142
#define g_assert_type_system_initialized() \
  g_assert (static_quark_type_flags)
143

144
145
146
147
#define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
				    G_TYPE_FLAG_INSTANTIATABLE | \
				    G_TYPE_FLAG_DERIVABLE | \
				    G_TYPE_FLAG_DEEP_DERIVABLE)
Emmanuele Bassi's avatar
Emmanuele Bassi committed
148
#define	TYPE_FLAG_MASK		   (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_FINAL)
149
150
151
#define	SIZEOF_FUNDAMENTAL_INFO	   ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \
						       sizeof (gpointer)), \
                                                  sizeof (glong)))
152

153
154
155
156
157
158
159
160
161
162
163
164
/* The 2*sizeof(size_t) alignment here is borrowed from
 * GNU libc, so it should be good most everywhere.
 * It is more conservative than is needed on some 64-bit
 * platforms, but ia64 does require a 16-byte alignment.
 * The SIMD extensions for x86 and ppc32 would want a
 * larger alignment than this, but we don't need to
 * do better than malloc.
 */
#define STRUCT_ALIGNMENT (2 * sizeof (gsize))
#define ALIGN_STRUCT(offset) \
      ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT)

165

166
/* --- typedefs --- */
167
168
typedef struct _TypeNode        TypeNode;
typedef struct _CommonData      CommonData;
169
typedef struct _BoxedData       BoxedData;
170
171
172
173
typedef struct _IFaceData       IFaceData;
typedef struct _ClassData       ClassData;
typedef struct _InstanceData    InstanceData;
typedef union  _TypeData        TypeData;
174
typedef struct _IFaceEntries    IFaceEntries;
175
176
177
178
179
typedef struct _IFaceEntry      IFaceEntry;
typedef struct _IFaceHolder	IFaceHolder;


/* --- prototypes --- */
180
static inline GTypeFundamentalInfo*	type_node_fundamental_info_I	(TypeNode		*node);
181
static	      void			type_add_flags_W		(TypeNode		*node,
182
									 GTypeFlags		 flags);
183
static	      void			type_data_make_W		(TypeNode		*node,
184
185
									 const GTypeInfo	*info,
									 const GTypeValueTable	*value_table);
186
static inline void			type_data_ref_Wm		(TypeNode		*node);
187
static inline void			type_data_unref_U               (TypeNode		*node,
188
									 gboolean		 uncached);
189
static void				type_data_last_unref_Wm		(TypeNode *              node,
190
									 gboolean		 uncached);
191
192
193
194
195
static inline gpointer			type_get_qdata_L		(TypeNode		*node,
									 GQuark			 quark);
static inline void			type_set_qdata_W		(TypeNode		*node,
									 GQuark			 quark,
									 gpointer		 data);
196
197
static IFaceHolder*			type_iface_peek_holder_L	(TypeNode		*iface,
									 GType			 instance_type);
198
199
200
201
static gboolean                         type_iface_vtable_base_init_Wm  (TypeNode               *iface,
                                                                         TypeNode               *node);
static void                             type_iface_vtable_iface_init_Wm (TypeNode               *iface,
                                                                         TypeNode               *node);
202
203
static gboolean				type_node_is_a_L		(TypeNode		*node,
									 TypeNode		*iface_node);
204
205


206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/* --- enumeration --- */

/* The InitState enumeration is used to track the progress of initializing
 * both classes and interface vtables. Keeping the state of initialization
 * is necessary to handle new interfaces being added while we are initializing
 * the class or other interfaces.
 */
typedef enum
{
  UNINITIALIZED,
  BASE_CLASS_INIT,
  BASE_IFACE_INIT,
  CLASS_INIT,
  IFACE_INIT,
  INITIALIZED
} InitState;

223
224
225
/* --- structures --- */
struct _TypeNode
{
226
  guint        ref_count;  /* (atomic) */
227
#ifdef G_ENABLE_DEBUG
228
  guint        instance_count;  /* (atomic) */
229
#endif
230
  GTypePlugin *plugin;
Benjamin Otte's avatar
Benjamin Otte committed
231
  guint        n_children; /* writable with lock */
232
  guint        n_supers : 8;
233
  guint        n_prerequisites : 9;
234
235
  guint        is_classed : 1;
  guint        is_instantiatable : 1;
236
  guint        mutatable_check_cache : 1;	/* combines some common path checks */
Benjamin Otte's avatar
Benjamin Otte committed
237
  GType       *children; /* writable with lock */
238
  TypeData    *data;
239
  GQuark       qname;
240
  GData       *global_gdata;
241
  union {
242
    GAtomicArray iface_entries;		/* for !iface types */
243
    GAtomicArray offsets;
244
  } _prot;
245
  GType       *prerequisites;
246
247
  GType        supers[1]; /* flexible array */
};
248

249
250
#define SIZEOF_BASE_TYPE_NODE()			(G_STRUCT_OFFSET (TypeNode, supers))
#define MAX_N_SUPERS				(255)
251
#define MAX_N_CHILDREN				(G_MAXUINT)
252
#define	MAX_N_INTERFACES			(255) /* Limited by offsets being 8 bits */
253
#define	MAX_N_PREREQUISITES			(511)
254
255
#define NODE_TYPE(node)				(node->supers[0])
#define NODE_PARENT_TYPE(node)			(node->supers[1])
256
#define NODE_FUNDAMENTAL_TYPE(node)		(node->supers[node->n_supers])
257
#define NODE_NAME(node)				(g_quark_to_string (node->qname))
258
#define NODE_REFCOUNT(node)                     ((guint) g_atomic_int_get ((int *) &(node)->ref_count))
259
#define	NODE_IS_BOXED(node)			(NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_BOXED)
260
#define	NODE_IS_IFACE(node)			(NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
261
262
#define	CLASSED_NODE_IFACES_ENTRIES(node)	(&(node)->_prot.iface_entries)
#define	CLASSED_NODE_IFACES_ENTRIES_LOCKED(node)(G_ATOMIC_ARRAY_GET_LOCKED(CLASSED_NODE_IFACES_ENTRIES((node)), IFaceEntries))
263
264
#define	IFACE_NODE_N_PREREQUISITES(node)	((node)->n_prerequisites)
#define	IFACE_NODE_PREREQUISITES(node)		((node)->prerequisites)
265
266
267
268
#define	iface_node_get_holders_L(node)		((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder))
#define	iface_node_set_holders_W(node, holders)	(type_set_qdata_W ((node), static_quark_iface_holder, (holders)))
#define	iface_node_get_dependants_array_L(n)	((GType*) type_get_qdata_L ((n), static_quark_dependants_array))
#define	iface_node_set_dependants_array_W(n,d)	(type_set_qdata_W ((n), static_quark_dependants_array, (d)))
269
270
#define	TYPE_ID_MASK				((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1))

271
272
273
274
#define NODE_IS_ANCESTOR(ancestor, node)                                                    \
        ((ancestor)->n_supers <= (node)->n_supers &&                                        \
	 (node)->supers[(node)->n_supers - (ancestor)->n_supers] == NODE_TYPE (ancestor))

275
276
277
278
279
280
281
struct _IFaceHolder
{
  GType           instance_type;
  GInterfaceInfo *info;
  GTypePlugin    *plugin;
  IFaceHolder    *next;
};
282

283
284
285
286
struct _IFaceEntry
{
  GType           iface_type;
  GTypeInterface *vtable;
287
  InitState       init_state;
288
};
289

290
struct _IFaceEntries {
291
  gsize offset_index;
292
293
294
295
296
297
  IFaceEntry entry[1];
};

#define IFACE_ENTRIES_HEADER_SIZE (sizeof(IFaceEntries) - sizeof(IFaceEntry))
#define IFACE_ENTRIES_N_ENTRIES(_entries) ( (G_ATOMIC_ARRAY_DATA_SIZE((_entries)) - IFACE_ENTRIES_HEADER_SIZE) / sizeof(IFaceEntry) )

298
299
struct _CommonData
{
300
  GTypeValueTable  *value_table;
301
};
302

303
304
305
306
307
308
309
struct _BoxedData
{
  CommonData         data;
  GBoxedCopyFunc     copy_func;
  GBoxedFreeFunc     free_func;
};

310
311
312
struct _IFaceData
{
  CommonData         common;
313
  guint16            vtable_size;
314
315
  GBaseInitFunc      vtable_init_base;
  GBaseFinalizeFunc  vtable_finalize_base;
316
317
318
319
  GClassInitFunc     dflt_init;
  GClassFinalizeFunc dflt_finalize;
  gconstpointer      dflt_data;
  gpointer           dflt_vtable;
320
};
321

322
323
324
struct _ClassData
{
  CommonData         common;
325
  guint16            class_size;
326
  guint16            class_private_size;
327
  int                init_state;  /* (atomic) - g_type_class_ref reads it unlocked */
328
329
330
331
332
333
334
  GBaseInitFunc      class_init_base;
  GBaseFinalizeFunc  class_finalize_base;
  GClassInitFunc     class_init;
  GClassFinalizeFunc class_finalize;
  gconstpointer      class_data;
  gpointer           class;
};
335

336
337
338
struct _InstanceData
{
  CommonData         common;
339
  guint16            class_size;
340
  guint16            class_private_size;
341
  int                init_state;  /* (atomic) - g_type_class_ref reads it unlocked */
342
343
344
345
346
347
348
  GBaseInitFunc      class_init_base;
  GBaseFinalizeFunc  class_finalize_base;
  GClassInitFunc     class_init;
  GClassFinalizeFunc class_finalize;
  gconstpointer      class_data;
  gpointer           class;
  guint16            instance_size;
349
  guint16            private_size;
350
351
352
  guint16            n_preallocs;
  GInstanceInitFunc  instance_init;
};
353

354
355
356
union _TypeData
{
  CommonData         common;
357
  BoxedData          boxed;
358
359
360
361
  IFaceData          iface;
  ClassData          class;
  InstanceData       instance;
};
362

363
364
365
366
typedef struct {
  gpointer            cache_data;
  GTypeClassCacheFunc cache_func;
} ClassCacheFunc;
367

368
369
370
371
typedef struct {
  gpointer                check_data;
  GTypeInterfaceCheckFunc check_func;
} IFaceCheckFunc;
372
373
374


/* --- variables --- */
Allison Karlitskaya's avatar
Allison Karlitskaya committed
375
376
static GRWLock         type_rw_lock;
static GRecMutex       class_init_rec_mutex;
377
378
static guint           static_n_class_cache_funcs = 0;
static ClassCacheFunc *static_class_cache_funcs = NULL;
379
380
static guint           static_n_iface_check_funcs = 0;
static IFaceCheckFunc *static_iface_check_funcs = NULL;
381
static GQuark          static_quark_type_flags = 0;
382
383
static GQuark          static_quark_iface_holder = 0;
static GQuark          static_quark_dependants_array = 0;
384
static guint           type_registration_serial = 0;
385
386

G_GNUC_BEGIN_IGNORE_DEPRECATIONS
387
GTypeDebugFlags	       _g_type_debug_flags = 0;
388
G_GNUC_END_IGNORE_DEPRECATIONS
389
390

/* --- type nodes --- */
391
static GHashTable       *static_type_nodes_ht = NULL;
392
static TypeNode		*static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) + 1] = { NULL, };
393
static GType		 static_fundamental_next = G_TYPE_RESERVED_USER_FIRST;
394
395

static inline TypeNode*
396
lookup_type_node_I (GType utype)
397
{
398
399
  if (utype > G_TYPE_FUNDAMENTAL_MAX)
    return (TypeNode*) (utype & ~TYPE_ID_MASK);
400
  else
401
    return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT];
402
403
}

404
405
406
/**
 * g_type_get_type_registration_serial:
 *
407
408
 * Returns an opaque serial number that represents the state of the set
 * of registered types. Any time a type is registered this serial changes,
Matthias Clasen's avatar
Matthias Clasen committed
409
410
411
 * which means you can cache information based on type lookups (such as
 * g_type_from_name()) and know if the cache is still valid at a later
 * time by comparing the current serial with the one at the type lookup.
412
413
414
 *
 * Since: 2.36
 *
415
 * Returns: An unsigned int, representing the state of type registrations
416
417
418
419
420
421
422
 */
guint
g_type_get_type_registration_serial (void)
{
  return (guint)g_atomic_int_get ((gint *)&type_registration_serial);
}

423
static TypeNode*
424
425
426
427
428
type_node_any_new_W (TypeNode             *pnode,
		     GType                 ftype,
		     const gchar          *name,
		     GTypePlugin          *plugin,
		     GTypeFundamentalFlags type_flags)
429
{
430
  guint n_supers;
431
432
433
  GType type;
  TypeNode *node;
  guint i, node_size = 0;
434

435
436
  n_supers = pnode ? pnode->n_supers + 1 : 0;
  
437
  if (!pnode)
438
    node_size += SIZEOF_FUNDAMENTAL_INFO;	      /* fundamental type info */
439
  node_size += SIZEOF_BASE_TYPE_NODE ();	      /* TypeNode structure */
440
  node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */
441
  node = g_malloc0 (node_size);
442
  if (!pnode)					      /* offset fundamental types */
443
444
    {
      node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
445
      static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;
446
      type = ftype;
447
448
449
450

#if ENABLE_VALGRIND
      VALGRIND_MALLOCLIKE_BLOCK (node, node_size - SIZEOF_FUNDAMENTAL_INFO, FALSE, TRUE);
#endif
451
452
453
    }
  else
    type = (GType) node;
454
  
455
456
  g_assert ((type & TYPE_ID_MASK) == 0);
  
457
458
459
460
461
  node->n_supers = n_supers;
  if (!pnode)
    {
      node->supers[0] = type;
      node->supers[1] = 0;
462
      
463
464
      node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
      node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
465
      
466
467
468
469
470
      if (NODE_IS_IFACE (node))
	{
          IFACE_NODE_N_PREREQUISITES (node) = 0;
	  IFACE_NODE_PREREQUISITES (node) = NULL;
	}
471
      else
472
	_g_atomic_array_init (CLASSED_NODE_IFACES_ENTRIES (node));
473
474
475
476
    }
  else
    {
      node->supers[0] = type;
477
      memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
478
      
479
480
      node->is_classed = pnode->is_classed;
      node->is_instantiatable = pnode->is_instantiatable;
481
      
482
      if (NODE_IS_IFACE (node))
483
	{
484
485
	  IFACE_NODE_N_PREREQUISITES (node) = 0;
	  IFACE_NODE_PREREQUISITES (node) = NULL;
486
487
488
	}
      else
	{
489
	  guint j;
490
491
492
493
494
495
	  IFaceEntries *entries;

	  entries = _g_atomic_array_copy (CLASSED_NODE_IFACES_ENTRIES (pnode),
					  IFACE_ENTRIES_HEADER_SIZE,
					  0);
	  if (entries)
496
	    {
497
498
499
500
501
502
503
	      for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (entries); j++)
		{
		  entries->entry[j].vtable = NULL;
		  entries->entry[j].init_state = UNINITIALIZED;
		}
	      _g_atomic_array_update (CLASSED_NODE_IFACES_ENTRIES (node),
				      entries);
504
	    }
505
	}
506

507
508
509
510
      i = pnode->n_children++;
      pnode->children = g_renew (GType, pnode->children, pnode->n_children);
      pnode->children[i] = type;
    }
511
512
513

  TRACE(GOBJECT_TYPE_NEW(name, node->supers[1], type));

514
515
516
517
518
  node->plugin = plugin;
  node->n_children = 0;
  node->children = NULL;
  node->data = NULL;
  node->qname = g_quark_from_string (name);
519
520
  node->global_gdata = NULL;
  g_hash_table_insert (static_type_nodes_ht,
521
		       (gpointer) g_quark_to_string (node->qname),
522
		       (gpointer) type);
523
524
525

  g_atomic_int_inc ((gint *)&type_registration_serial);

526
527
528
529
  return node;
}

static inline GTypeFundamentalInfo*
530
type_node_fundamental_info_I (TypeNode *node)
531
{
532
  GType ftype = NODE_FUNDAMENTAL_TYPE (node);
533
534
  
  if (ftype != NODE_TYPE (node))
535
    node = lookup_type_node_I (ftype);
536
  
537
  return node ? G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO) : NULL;
538
539
540
}

static TypeNode*
541
542
543
type_node_fundamental_new_W (GType                 ftype,
			     const gchar          *name,
			     GTypeFundamentalFlags type_flags)
544
545
546
{
  GTypeFundamentalInfo *finfo;
  TypeNode *node;
547
548
  
  g_assert ((ftype & TYPE_ID_MASK) == 0);
549
  g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX);
550
  
551
552
  if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next)
    static_fundamental_next++;
553
  
554
  type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
555
556
557
  
  node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
  
558
  finfo = type_node_fundamental_info_I (node);
559
  finfo->type_flags = type_flags;
560
  
561
562
563
564
  return node;
}

static TypeNode*
565
566
567
568
type_node_new_W (TypeNode    *pnode,
		 const gchar *name,
		 GTypePlugin *plugin)
     
569
570
571
572
{
  g_assert (pnode);
  g_assert (pnode->n_supers < MAX_N_SUPERS);
  g_assert (pnode->n_children < MAX_N_CHILDREN);
573
  
574
  return type_node_any_new_W (pnode, NODE_FUNDAMENTAL_TYPE (pnode), name, plugin, 0);
575
576
577
}

static inline IFaceEntry*
578
579
lookup_iface_entry_I (IFaceEntries *entries,
                      TypeNode     *iface_node)
580
{
581
  guint8 *offsets;
582
  gsize offset_index;
583
  IFaceEntry *check;
584
  gsize index;
585
  IFaceEntry *entry;
586

587
588
589
590
  if (entries == NULL)
    return NULL;

  G_ATOMIC_ARRAY_DO_TRANSACTION
591
    (&iface_node->_prot.offsets, guint8,
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615

     entry = NULL;
     offsets = transaction_data;
     offset_index = entries->offset_index;
     if (offsets != NULL &&
	 offset_index < G_ATOMIC_ARRAY_DATA_SIZE(offsets))
       {
	 index = offsets[offset_index];
	 if (index > 0)
	   {
	     /* zero means unset, subtract one to get real index */
	     index -= 1;

	     if (index < IFACE_ENTRIES_N_ENTRIES (entries))
	       {
		 check = (IFaceEntry *)&entries->entry[index];
		 if (check->iface_type == NODE_TYPE (iface_node))
		   entry = check;
	       }
	   }
       }
     );

 return entry;
616
617
}

618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
static inline IFaceEntry*
type_lookup_iface_entry_L (TypeNode *node,
			   TypeNode *iface_node)
{
  if (!NODE_IS_IFACE (iface_node))
    return NULL;

  return lookup_iface_entry_I (CLASSED_NODE_IFACES_ENTRIES_LOCKED (node),
			       iface_node);
}


static inline gboolean
type_lookup_iface_vtable_I (TypeNode *node,
			    TypeNode *iface_node,
			    gpointer *vtable_ptr)
{
  IFaceEntry *entry;
  gboolean res;

  if (!NODE_IS_IFACE (iface_node))
    {
      if (vtable_ptr)
	*vtable_ptr = NULL;
      return FALSE;
    }

  G_ATOMIC_ARRAY_DO_TRANSACTION
    (CLASSED_NODE_IFACES_ENTRIES (node), IFaceEntries,

     entry = lookup_iface_entry_I (transaction_data, iface_node);
     res = entry != NULL;
     if (vtable_ptr)
       {
	 if (entry)
	   *vtable_ptr = entry->vtable;
	 else
	   *vtable_ptr = NULL;
       }
     );

  return res;
}

662
static inline gboolean
663
664
type_lookup_prerequisite_L (TypeNode *iface,
			    GType     prerequisite_type)
665
666
667
668
669
{
  if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface))
    {
      GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1;
      guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface);
670
      
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
      do
	{
	  guint i;
	  GType *check;
	  
	  i = (n_prerequisites + 1) >> 1;
	  check = prerequisites + i;
	  if (prerequisite_type == *check)
	    return TRUE;
	  else if (prerequisite_type > *check)
	    {
	      n_prerequisites -= i;
	      prerequisites = check;
	    }
	  else /* if (prerequisite_type < *check) */
	    n_prerequisites = i - 1;
	}
      while (n_prerequisites);
    }
  return FALSE;
}

693
static const gchar*
694
type_descriptive_name_I (GType type)
695
696
697
{
  if (type)
    {
698
      TypeNode *node = lookup_type_node_I (type);
699
700
      
      return node ? NODE_NAME (node) : "<unknown>";
701
702
703
704
705
706
707
708
    }
  else
    return "<invalid>";
}


/* --- type consistency checks --- */
static gboolean
709
710
711
712
check_plugin_U (GTypePlugin *plugin,
		gboolean     need_complete_type_info,
		gboolean     need_complete_interface_info,
		const gchar *type_name)
713
{
714
715
  /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U 
   */
716
717
  if (!plugin)
    {
718
      g_warning ("plugin handle for type '%s' is NULL",
719
720
721
		 type_name);
      return FALSE;
    }
722
  if (!G_IS_TYPE_PLUGIN (plugin))
723
    {
724
      g_warning ("plugin pointer (%p) for type '%s' is invalid",
725
		 plugin, type_name);
726
727
      return FALSE;
    }
728
  if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
729
    {
730
      g_warning ("plugin for type '%s' has no complete_type_info() implementation",
731
732
733
		 type_name);
      return FALSE;
    }
734
  if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
735
    {
736
      g_warning ("plugin for type '%s' has no complete_interface_info() implementation",
737
738
739
740
741
742
743
		 type_name);
      return FALSE;
    }
  return TRUE;
}

static gboolean
744
check_type_name_I (const gchar *type_name)
745
{
746
  static const gchar extra_chars[] = "-_+";
747
748
  const gchar *p = type_name;
  gboolean name_valid;
749
  
750
751
  if (!type_name[0] || !type_name[1] || !type_name[2])
    {
752
      g_warning ("type name '%s' is too short", type_name);
753
754
755
756
757
758
759
760
761
762
763
      return FALSE;
    }
  /* check the first letter */
  name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_';
  for (p = type_name + 1; *p; p++)
    name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') ||
		   (p[0] >= 'a' && p[0] <= 'z') ||
		   (p[0] >= '0' && p[0] <= '9') ||
		   strchr (extra_chars, p[0]));
  if (!name_valid)
    {
764
      g_warning ("type name '%s' contains invalid characters", type_name);
765
766
767
768
      return FALSE;
    }
  if (g_type_from_name (type_name))
    {
769
      g_warning ("cannot register existing type '%s'", type_name);
770
771
      return FALSE;
    }
772
  
773
774
775
776
  return TRUE;
}

static gboolean
777
check_derivation_I (GType        parent_type,
778
		    const gchar *type_name)
779
{
780
781
  TypeNode *pnode;
  GTypeFundamentalInfo* finfo;
782
  
783
  pnode = lookup_type_node_I (parent_type);
784
785
  if (!pnode)
    {
786
      g_warning ("cannot derive type '%s' from invalid parent type '%s'",
787
		 type_name,
788
		 type_descriptive_name_I (parent_type));
789
790
      return FALSE;
    }
791
  finfo = type_node_fundamental_info_I (pnode);
792
793
794
  /* ensure flat derivability */
  if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
    {
795
      g_warning ("cannot derive '%s' from non-derivable parent type '%s'",
796
797
798
799
800
		 type_name,
		 NODE_NAME (pnode));
      return FALSE;
    }
  /* ensure deep derivability */
801
  if (parent_type != NODE_FUNDAMENTAL_TYPE (pnode) &&
802
803
      !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
    {
804
      g_warning ("cannot derive '%s' from non-fundamental parent type '%s'",
805
806
807
808
		 type_name,
		 NODE_NAME (pnode));
      return FALSE;
    }
Emmanuele Bassi's avatar
Emmanuele Bassi committed
809
810
811
812
813
814
815
  if ((G_TYPE_FLAG_FINAL & GPOINTER_TO_UINT (type_get_qdata_L (pnode, static_quark_type_flags))) == G_TYPE_FLAG_FINAL)
    {
      g_warning ("cannot derive '%s' from final parent type '%s'",
                 type_name,
                 NODE_NAME (pnode));
      return FALSE;
    }
816
817
818
819
  
  return TRUE;
}

820
821
822
823
824
static gboolean
check_collect_format_I (const gchar *collect_format)
{
  const gchar *p = collect_format;
  gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG,
825
826
			   G_VALUE_COLLECT_INT64, G_VALUE_COLLECT_DOUBLE,
			   G_VALUE_COLLECT_POINTER, 0 };
827
  
828
829
830
831
832
833
  while (*p)
    if (!strchr (valid_format, *p++))
      return FALSE;
  return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH;
}

834
static gboolean
835
836
check_value_table_I (const gchar           *type_name,
		     const GTypeValueTable *value_table)
837
838
839
840
841
842
{
  if (!value_table)
    return FALSE;
  else if (value_table->value_init == NULL)
    {
      if (value_table->value_free || value_table->value_copy ||
843
	  value_table->value_peek_pointer ||
844
845
	  value_table->collect_format || value_table->collect_value ||
	  value_table->lcopy_format || value_table->lcopy_value)
846
	g_warning ("cannot handle uninitializable values of type '%s'",
847
848
849
850
851
852
853
854
		   type_name);
      return FALSE;
    }
  else /* value_table->value_init != NULL */
    {
      if (!value_table->value_free)
	{
	  /* +++ optional +++
855
	   * g_warning ("missing 'value_free()' for type '%s'", type_name);
856
857
858
859
860
	   * return FALSE;
	   */
	}
      if (!value_table->value_copy)
	{
861
	  g_warning ("missing 'value_copy()' for type '%s'", type_name);
862
863
	  return FALSE;
	}
864
865
866
      if ((value_table->collect_format || value_table->collect_value) &&
	  (!value_table->collect_format || !value_table->collect_value))
	{
867
	  g_warning ("one of 'collect_format' and 'collect_value()' is unspecified for type '%s'",
868
869
870
871
872
		     type_name);
	  return FALSE;
	}
      if (value_table->collect_format && !check_collect_format_I (value_table->collect_format))
	{
873
	  g_warning ("the '%s' specification for type '%s' is too long or invalid",
874
875
876
877
878
879
		     "collect_format",
		     type_name);
	  return FALSE;
	}
      if ((value_table->lcopy_format || value_table->lcopy_value) &&
	  (!value_table->lcopy_format || !value_table->lcopy_value))
880
	{
881
	  g_warning ("one of 'lcopy_format' and 'lcopy_value()' is unspecified for type '%s'",
882
883
884
		     type_name);
	  return FALSE;
	}
885
      if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format))
886
	{
887
	  g_warning ("the '%s' specification for type '%s' is too long or invalid",
888
		     "lcopy_format",
889
890
891
892
893
894
895
896
		     type_name);
	  return FALSE;
	}
    }
  return TRUE;
}

static gboolean
897
check_type_info_I (TypeNode        *pnode,
898
899
900
		   GType            ftype,
		   const gchar     *type_name,
		   const GTypeInfo *info)
901
{
902
  GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (lookup_type_node_I (ftype));
903
  gboolean is_interface = ftype == G_TYPE_INTERFACE;
904
905
  
  g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX && !(ftype & TYPE_ID_MASK));
906
  
907
908
909
910
911
  /* check instance members */
  if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
      (info->instance_size || info->n_preallocs || info->instance_init))
    {
      if (pnode)
912
	g_warning ("cannot instantiate '%s', derived from non-instantiatable parent type '%s'",
913
914
915
		   type_name,
		   NODE_NAME (pnode));
      else
916
	g_warning ("cannot instantiate '%s' as non-instantiatable fundamental",
917
918
919
920
		   type_name);
      return FALSE;
    }
  /* check class & interface members */
921
  if (!((finfo->type_flags & G_TYPE_FLAG_CLASSED) || is_interface) &&
922
      (info->class_init || info->class_finalize || info->class_data ||
923
       info->class_size || info->base_init || info->base_finalize))
924
925
    {
      if (pnode)
926
	g_warning ("cannot create class for '%s', derived from non-classed parent type '%s'",
927
928
929
		   type_name,
                   NODE_NAME (pnode));
      else
930
	g_warning ("cannot create class for '%s' as non-classed fundamental",
931
932
933
934
935
936
		   type_name);
      return FALSE;
    }
  /* check interface size */
  if (is_interface && info->class_size < sizeof (GTypeInterface))
    {
937
      g_warning ("specified interface size for type '%s' is smaller than 'GTypeInterface' size",
938
939
940
941
942
943
944
945
		 type_name);
      return FALSE;
    }
  /* check class size */
  if (finfo->type_flags & G_TYPE_FLAG_CLASSED)
    {
      if (info->class_size < sizeof (GTypeClass))
	{
946
	  g_warning ("specified class size for type '%s' is smaller than 'GTypeClass' size",
947
948
949
950
951
		     type_name);
	  return FALSE;
	}
      if (pnode && info->class_size < pnode->data->class.class_size)
	{
952
953
	  g_warning ("specified class size for type '%s' is smaller "
		     "than the parent type's '%s' class size",
954
955
956
957
958
959
960
961
962
963
		     type_name,
		     NODE_NAME (pnode));
	  return FALSE;
	}
    }
  /* check instance size */
  if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE)
    {
      if (info->instance_size < sizeof (GTypeInstance))
	{
964
	  g_warning ("specified instance size for type '%s' is smaller than 'GTypeInstance' size",
965
966
967
968
969
		     type_name);
	  return FALSE;
	}
      if (pnode && info->instance_size < pnode->data->instance.instance_size)
	{
970
971
	  g_warning ("specified instance size for type '%s' is smaller "
		     "than the parent type's '%s' instance size",
972
973
974
975
976
		     type_name,
		     NODE_NAME (pnode));
	  return FALSE;
	}
    }
977
  
978
979
980
981
  return TRUE;
}

static TypeNode*
982
983
find_conforming_child_type_L (TypeNode *pnode,
			      TypeNode *iface)
984
985
986
{
  TypeNode *node = NULL;
  guint i;
987
988
  
  if (type_lookup_iface_entry_L (pnode, iface))
989
    return pnode;
990
  
991
  for (i = 0; i < pnode->n_children && !node; i++)
992
    node = find_conforming_child_type_L (lookup_type_node_I (pnode->children[i]), iface);
993
  
994
995
996
997
  return node;
}

static gboolean
998
999
check_add_interface_L (GType instance_type,
		       GType iface_type)
1000
{
For faster browsing, not all history is shown. View entire blame