1/* GObject - GLib Type, Object, Parameter and Signal Library 2 * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General 15 * Public License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 * Boston, MA 02111-1307, USA. 18 */ 19 20/* 21 * MT safe 22 */ 23 24#include "config.h" 25 26#include <string.h> 27 28#include "gtype.h" 29#include "gtypeplugin.h" 30#include "gvaluecollector.h" 31#include "gbsearcharray.h" 32#include "gobjectalias.h" 33 34 35/** 36 * SECTION:gtype 37 * @short_description: The GLib Runtime type identification and 38 * management system 39 * @title:Type Information 40 * 41 * The GType API is the foundation of the GObject system. It provides the 42 * facilities for registering and managing all fundamental data types, 43 * user-defined object and interface types. Before using any GType 44 * or GObject functions, g_type_init() must be called to initialize the 45 * type system. 46 * 47 * For type creation and registration purposes, all types fall into one of 48 * two categories: static or dynamic. Static types are never loaded or 49 * unloaded at run-time as dynamic types may be. Static types are created 50 * with g_type_register_static() that gets type specific information passed 51 * in via a #GTypeInfo structure. 52 * Dynamic types are created with g_type_register_dynamic() which takes a 53 * #GTypePlugin structure instead. The remaining type information (the 54 * #GTypeInfo structure) is retrieved during runtime through #GTypePlugin 55 * and the g_type_plugin_*() API. 56 * These registration functions are usually called only once from a 57 * function whose only purpose is to return the type identifier for a 58 * specific class. Once the type (or class or interface) is registered, 59 * it may be instantiated, inherited, or implemented depending on exactly 60 * what sort of type it is. 61 * There is also a third registration function for registering fundamental 62 * types called g_type_register_fundamental() which requires both a #GTypeInfo 63 * structure and a #GTypeFundamentalInfo structure but it is seldom used 64 * since most fundamental types are predefined rather than user-defined. 65 * 66 * A final word about type names. 67 * Such an identifier needs to be at least three characters long. There is no 68 * upper length limit. The first character needs to be a letter (a-z or A-Z) 69 * or an underscore '_'. Subsequent characters can be letters, numbers or 70 * any of '-_+'. 71 */ 72 73 74/* NOTE: some functions (some internal variants and exported ones) 75 * invalidate data portions of the TypeNodes. if external functions/callbacks 76 * are called, pointers to memory maintained by TypeNodes have to be looked up 77 * again. this affects most of the struct TypeNode fields, e.g. ->children or 78 * CLASSED_NODE_IFACES_ENTRIES() respectively IFACE_NODE_PREREQUISITES() (but 79 * not ->supers[]), as all those memory portions can get realloc()ed during 80 * callback invocation. 81 * 82 * TODO: 83 * - g_type_from_name() should do an ordered array lookup after fetching the 84 * the quark, instead of a second hashtable lookup. 85 * 86 * LOCKING: 87 * lock handling issues when calling static functions are indicated by 88 * uppercase letter postfixes, all static functions have to have 89 * one of the below postfixes: 90 * - _I: [Indifferent about locking] 91 * function doesn't care about locks at all 92 * - _U: [Unlocked invocation] 93 * no read or write lock has to be held across function invocation 94 * (locks may be acquired and released during invocation though) 95 * - _L: [Locked invocation] 96 * a write lock or more than 0 read locks have to be held across 97 * function invocation 98 * - _W: [Write-locked invocation] 99 * a write lock has to be held across function invocation 100 * - _Wm: [Write-locked invocation, mutatable] 101 * like _W, but the write lock might be released and reacquired 102 * during invocation, watch your pointers 103 * - _WmREC: [Write-locked invocation, mutatable, recursive] 104 * like _Wm, but also acquires recursive mutex class_init_rec_mutex 105 */ 106 107#ifdef LOCK_DEBUG 108#define G_READ_LOCK(rw_lock) do { g_printerr (G_STRLOC ": readL++\n"); g_static_rw_lock_reader_lock (rw_lock); } while (0) 109#define G_READ_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": readL--\n"); g_static_rw_lock_reader_unlock (rw_lock); } while (0) 110#define G_WRITE_LOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL++\n"); g_static_rw_lock_writer_lock (rw_lock); } while (0) 111#define G_WRITE_UNLOCK(rw_lock) do { g_printerr (G_STRLOC ": writeL--\n"); g_static_rw_lock_writer_unlock (rw_lock); } while (0) 112#else 113#define G_READ_LOCK(rw_lock) g_static_rw_lock_reader_lock (rw_lock) 114#define G_READ_UNLOCK(rw_lock) g_static_rw_lock_reader_unlock (rw_lock) 115#define G_WRITE_LOCK(rw_lock) g_static_rw_lock_writer_lock (rw_lock) 116#define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock) 117#endif 118#define INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \ 119 static const gchar _action[] = " invalidly modified type "; \ 120 gpointer _arg = (gpointer) (arg); const gchar *_tname = (type_name), *_fname = (func); \ 121 if (_arg) \ 122 g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \ 123 else \ 124 g_error ("%s()%s`%s'", _fname, _action, _tname); \ 125}G_STMT_END 126#define g_return_val_if_uninitialized(condition, init_function, return_value) G_STMT_START{ \ 127 if (!(condition)) \ 128 { \ 129 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \ 130 "%s: initialization assertion failed, use %s() prior to this function", \ 131 G_STRLOC, G_STRINGIFY (init_function)); \ 132 return (return_value); \ 133 } \ 134}G_STMT_END 135 136#ifdef G_ENABLE_DEBUG 137#define DEBUG_CODE(debug_type, code_block) G_STMT_START { \ 138 if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \ 139 { code_block; } \ 140} G_STMT_END 141#else /* !G_ENABLE_DEBUG */ 142#define DEBUG_CODE(debug_type, code_block) /* code_block */ 143#endif /* G_ENABLE_DEBUG */ 144 145#define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \ 146 G_TYPE_FLAG_INSTANTIATABLE | \ 147 G_TYPE_FLAG_DERIVABLE | \ 148 G_TYPE_FLAG_DEEP_DERIVABLE) 149#define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT | G_TYPE_FLAG_VALUE_ABSTRACT) 150#define SIZEOF_FUNDAMENTAL_INFO ((gssize) MAX (MAX (sizeof (GTypeFundamentalInfo), \ 151 sizeof (gpointer)), \ 152 sizeof (glong))) 153 154/* The 2*sizeof(size_t) alignment here is borrowed from 155 * GNU libc, so it should be good most everywhere. 156 * It is more conservative than is needed on some 64-bit 157 * platforms, but ia64 does require a 16-byte alignment. 158 * The SIMD extensions for x86 and ppc32 would want a 159 * larger alignment than this, but we don't need to 160 * do better than malloc. 161 */ 162#define STRUCT_ALIGNMENT (2 * sizeof (gsize)) 163#define ALIGN_STRUCT(offset) \ 164 ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT) 165 166 167/* --- typedefs --- */ 168typedef struct _TypeNode TypeNode; 169typedef struct _CommonData CommonData; 170typedef struct _IFaceData IFaceData; 171typedef struct _ClassData ClassData; 172typedef struct _InstanceData InstanceData; 173typedef union _TypeData TypeData; 174typedef struct _IFaceEntry IFaceEntry; 175typedef struct _IFaceHolder IFaceHolder; 176 177 178/* --- prototypes --- */ 179static inline GTypeFundamentalInfo* type_node_fundamental_info_I (TypeNode *node); 180static void type_add_flags_W (TypeNode *node, 181 GTypeFlags flags); 182static void type_data_make_W (TypeNode *node, 183 const GTypeInfo *info, 184 const GTypeValueTable *value_table); 185static inline void type_data_ref_Wm (TypeNode *node); 186static inline void type_data_unref_WmREC (TypeNode *node, 187 gboolean uncached); 188static void type_data_last_unref_Wm (GType type, 189 gboolean uncached); 190static inline gpointer type_get_qdata_L (TypeNode *node, 191 GQuark quark); 192static inline void type_set_qdata_W (TypeNode *node, 193 GQuark quark, 194 gpointer data); 195static IFaceHolder* type_iface_peek_holder_L (TypeNode *iface, 196 GType instance_type); 197static gboolean type_iface_vtable_base_init_Wm (TypeNode *iface, 198 TypeNode *node); 199static void type_iface_vtable_iface_init_Wm (TypeNode *iface, 200 TypeNode *node); 201static gboolean type_node_is_a_L (TypeNode *node, 202 TypeNode *iface_node); 203 204 205/* --- enumeration --- */ 206 207/* The InitState enumeration is used to track the progress of initializing 208 * both classes and interface vtables. Keeping the state of initialization 209 * is necessary to handle new interfaces being added while we are initializing 210 * the class or other interfaces. 211 */ 212typedef enum 213{ 214 UNINITIALIZED, 215 BASE_CLASS_INIT, 216 BASE_IFACE_INIT, 217 CLASS_INIT, 218 IFACE_INIT, 219 INITIALIZED 220} InitState; 221 222/* --- structures --- */ 223struct _TypeNode 224{ 225 GTypePlugin *plugin; 226 guint n_children : 12; 227 guint n_supers : 8; 228 guint _prot_n_ifaces_prerequisites : 9; 229 guint is_classed : 1; 230 guint is_instantiatable : 1; 231 guint mutatable_check_cache : 1; /* combines some common path checks */ 232 GType *children; 233 TypeData * volatile data; 234 GQuark qname; 235 GData *global_gdata; 236 union { 237 IFaceEntry *iface_entries; /* for !iface types */ 238 GType *prerequisistes; 239 } _prot; 240 GType supers[1]; /* flexible array */ 241}; 242 243#define SIZEOF_BASE_TYPE_NODE() (G_STRUCT_OFFSET (TypeNode, supers)) 244#define MAX_N_SUPERS (255) 245#define MAX_N_CHILDREN (4095) 246#define MAX_N_IFACES (511) 247#define MAX_N_PREREQUISITES (MAX_N_IFACES) 248#define NODE_TYPE(node) (node->supers[0]) 249#define NODE_PARENT_TYPE(node) (node->supers[1]) 250#define NODE_FUNDAMENTAL_TYPE(node) (node->supers[node->n_supers]) 251#define NODE_NAME(node) (g_quark_to_string (node->qname)) 252#define NODE_IS_IFACE(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE) 253#define CLASSED_NODE_N_IFACES(node) ((node)->_prot_n_ifaces_prerequisites) 254#define CLASSED_NODE_IFACES_ENTRIES(node) ((node)->_prot.iface_entries) 255#define IFACE_NODE_N_PREREQUISITES(node) ((node)->_prot_n_ifaces_prerequisites) 256#define IFACE_NODE_PREREQUISITES(node) ((node)->_prot.prerequisistes) 257#define iface_node_get_holders_L(node) ((IFaceHolder*) type_get_qdata_L ((node), static_quark_iface_holder)) 258#define iface_node_set_holders_W(node, holders) (type_set_qdata_W ((node), static_quark_iface_holder, (holders))) 259#define iface_node_get_dependants_array_L(n) ((GType*) type_get_qdata_L ((n), static_quark_dependants_array)) 260#define iface_node_set_dependants_array_W(n,d) (type_set_qdata_W ((n), static_quark_dependants_array, (d))) 261#define TYPE_ID_MASK ((GType) ((1 << G_TYPE_FUNDAMENTAL_SHIFT) - 1)) 262 263#define NODE_IS_ANCESTOR(ancestor, node) \ 264 ((ancestor)->n_supers <= (node)->n_supers && \ 265 (node)->supers[(node)->n_supers - (ancestor)->n_supers] == NODE_TYPE (ancestor)) 266 267 268struct _IFaceHolder 269{ 270 GType instance_type; 271 GInterfaceInfo *info; 272 GTypePlugin *plugin; 273 IFaceHolder *next; 274}; 275 276struct _IFaceEntry 277{ 278 GType iface_type; 279 GTypeInterface *vtable; 280 InitState init_state; 281}; 282 283struct _CommonData 284{ 285 guint ref_count; 286 GTypeValueTable *value_table; 287}; 288 289struct _IFaceData 290{ 291 CommonData common; 292 guint16 vtable_size; 293 GBaseInitFunc vtable_init_base; 294 GBaseFinalizeFunc vtable_finalize_base; 295 GClassInitFunc dflt_init; 296 GClassFinalizeFunc dflt_finalize; 297 gconstpointer dflt_data; 298 gpointer dflt_vtable; 299}; 300 301struct _ClassData 302{ 303 CommonData common; 304 guint16 class_size; 305 guint init_state : 4; 306 GBaseInitFunc class_init_base; 307 GBaseFinalizeFunc class_finalize_base; 308 GClassInitFunc class_init; 309 GClassFinalizeFunc class_finalize; 310 gconstpointer class_data; 311 gpointer class; 312}; 313 314struct _InstanceData 315{ 316 CommonData common; 317 guint16 class_size; 318 guint init_state : 4; 319 GBaseInitFunc class_init_base; 320 GBaseFinalizeFunc class_finalize_base; 321 GClassInitFunc class_init; 322 GClassFinalizeFunc class_finalize; 323 gconstpointer class_data; 324 gpointer class; 325 guint16 instance_size; 326 guint16 private_size; 327 guint16 n_preallocs; 328 GInstanceInitFunc instance_init; 329}; 330 331union _TypeData 332{ 333 CommonData common; 334 IFaceData iface; 335 ClassData class; 336 InstanceData instance; 337}; 338 339typedef struct { 340 gpointer cache_data; 341 GTypeClassCacheFunc cache_func; 342} ClassCacheFunc; 343 344typedef struct { 345 gpointer check_data; 346 GTypeInterfaceCheckFunc check_func; 347} IFaceCheckFunc; 348 349 350/* --- variables --- */ 351static GStaticRWLock type_rw_lock = G_STATIC_RW_LOCK_INIT; 352static GStaticRecMutex class_init_rec_mutex = G_STATIC_REC_MUTEX_INIT; 353static guint static_n_class_cache_funcs = 0; 354static ClassCacheFunc *static_class_cache_funcs = NULL; 355static guint static_n_iface_check_funcs = 0; 356static IFaceCheckFunc *static_iface_check_funcs = NULL; 357static GQuark static_quark_type_flags = 0; 358static GQuark static_quark_iface_holder = 0; 359static GQuark static_quark_dependants_array = 0; 360GTypeDebugFlags _g_type_debug_flags = 0; 361 362 363/* --- type nodes --- */ 364static GHashTable *static_type_nodes_ht = NULL; 365static TypeNode *static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) + 1] = { NULL, }; 366static GType static_fundamental_next = G_TYPE_RESERVED_USER_FIRST; 367 368static inline TypeNode* 369lookup_type_node_I (register GType utype) 370{ 371 if (utype > G_TYPE_FUNDAMENTAL_MAX) 372 return (TypeNode*) (utype & ~TYPE_ID_MASK); 373 else 374 return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT]; 375} 376 377static TypeNode* 378type_node_any_new_W (TypeNode *pnode, 379 GType ftype, 380 const gchar *name, 381 GTypePlugin *plugin, 382 GTypeFundamentalFlags type_flags) 383{ 384 guint n_supers; 385 GType type; 386 TypeNode *node; 387 guint i, node_size = 0; 388 389 n_supers = pnode ? pnode->n_supers + 1 : 0; 390 391 if (!pnode) 392 node_size += SIZEOF_FUNDAMENTAL_INFO; /* fundamental type info */ 393 node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */ 394 node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */ 395 node = g_malloc0 (node_size); 396 if (!pnode) /* offset fundamental types */ 397 { 398 node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO); 399 static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node; 400 type = ftype; 401 } 402 else 403 type = (GType) node; 404 405 g_assert ((type & TYPE_ID_MASK) == 0); 406 407 node->n_supers = n_supers; 408 if (!pnode) 409 { 410 node->supers[0] = type; 411 node->supers[1] = 0; 412 413 node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0; 414 node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0; 415 416 if (NODE_IS_IFACE (node)) 417 { 418 IFACE_NODE_N_PREREQUISITES (node) = 0; 419 IFACE_NODE_PREREQUISITES (node) = NULL; 420 } 421 else 422 { 423 CLASSED_NODE_N_IFACES (node) = 0; 424 CLASSED_NODE_IFACES_ENTRIES (node) = NULL; 425 } 426 } 427 else 428 { 429 node->supers[0] = type; 430 memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1)); 431 432 node->is_classed = pnode->is_classed; 433 node->is_instantiatable = pnode->is_instantiatable; 434 435 if (NODE_IS_IFACE (node)) 436 { 437 IFACE_NODE_N_PREREQUISITES (node) = 0; 438 IFACE_NODE_PREREQUISITES (node) = NULL; 439 } 440 else 441 { 442 guint j; 443 444 CLASSED_NODE_N_IFACES (node) = CLASSED_NODE_N_IFACES (pnode); 445 CLASSED_NODE_IFACES_ENTRIES (node) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode), 446 sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode)[0]) * 447 CLASSED_NODE_N_IFACES (node)); 448 for (j = 0; j < CLASSED_NODE_N_IFACES (node); j++) 449 { 450 CLASSED_NODE_IFACES_ENTRIES (node)[j].vtable = NULL; 451 CLASSED_NODE_IFACES_ENTRIES (node)[j].init_state = UNINITIALIZED; 452 } 453 } 454 455 i = pnode->n_children++; 456 pnode->children = g_renew (GType, pnode->children, pnode->n_children); 457 pnode->children[i] = type; 458 } 459 460 node->plugin = plugin; 461 node->n_children = 0; 462 node->children = NULL; 463 node->data = NULL; 464 node->qname = g_quark_from_string (name); 465 node->global_gdata = NULL; 466 467 g_hash_table_insert (static_type_nodes_ht, 468 GUINT_TO_POINTER (node->qname), 469 (gpointer) type); 470 return node; 471} 472 473static inline GTypeFundamentalInfo* 474type_node_fundamental_info_I (TypeNode *node) 475{ 476 GType ftype = NODE_FUNDAMENTAL_TYPE (node); 477 478 if (ftype != NODE_TYPE (node)) 479 node = lookup_type_node_I (ftype); 480 481 return node ? G_STRUCT_MEMBER_P (node, -SIZEOF_FUNDAMENTAL_INFO) : NULL; 482} 483 484static TypeNode* 485type_node_fundamental_new_W (GType ftype, 486 const gchar *name, 487 GTypeFundamentalFlags type_flags) 488{ 489 GTypeFundamentalInfo *finfo; 490 TypeNode *node; 491 492 g_assert ((ftype & TYPE_ID_MASK) == 0); 493 g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX); 494 495 if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next) 496 static_fundamental_next++; 497 498 type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK; 499 500 node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags); 501 502 finfo = type_node_fundamental_info_I (node); 503 finfo->type_flags = type_flags; 504 505 return node; 506} 507 508static TypeNode* 509type_node_new_W (TypeNode *pnode, 510 const gchar *name, 511 GTypePlugin *plugin) 512 513{ 514 g_assert (pnode); 515 g_assert (pnode->n_supers < MAX_N_SUPERS); 516 g_assert (pnode->n_children < MAX_N_CHILDREN); 517 518 return type_node_any_new_W (pnode, NODE_FUNDAMENTAL_TYPE (pnode), name, plugin, 0); 519} 520 521static inline IFaceEntry* 522type_lookup_iface_entry_L (TypeNode *node, 523 TypeNode *iface_node) 524{ 525 if (NODE_IS_IFACE (iface_node) && CLASSED_NODE_N_IFACES (node)) 526 { 527 IFaceEntry *ifaces = CLASSED_NODE_IFACES_ENTRIES (node) - 1; 528 guint n_ifaces = CLASSED_NODE_N_IFACES (node); 529 GType iface_type = NODE_TYPE (iface_node); 530 531 do 532 { 533 guint i; 534 IFaceEntry *check; 535 536 i = (n_ifaces + 1) >> 1; 537 check = ifaces + i; 538 if (iface_type == check->iface_type) 539 return check; 540 else if (iface_type > check->iface_type) 541 { 542 n_ifaces -= i; 543 ifaces = check; 544 } 545 else /* if (iface_type < check->iface_type) */ 546 n_ifaces = i - 1; 547 } 548 while (n_ifaces); 549 } 550 551 return NULL; 552} 553 554static inline gboolean 555type_lookup_prerequisite_L (TypeNode *iface, 556 GType prerequisite_type) 557{ 558 if (NODE_IS_IFACE (iface) && IFACE_NODE_N_PREREQUISITES (iface)) 559 { 560 GType *prerequisites = IFACE_NODE_PREREQUISITES (iface) - 1; 561 guint n_prerequisites = IFACE_NODE_N_PREREQUISITES (iface); 562 563 do 564 { 565 guint i; 566 GType *check; 567 568 i = (n_prerequisites + 1) >> 1; 569 check = prerequisites + i; 570 if (prerequisite_type == *check) 571 return TRUE; 572 else if (prerequisite_type > *check) 573 { 574 n_prerequisites -= i; 575 prerequisites = check; 576 } 577 else /* if (prerequisite_type < *check) */ 578 n_prerequisites = i - 1; 579 } 580 while (n_prerequisites); 581 } 582 return FALSE; 583} 584 585static gchar* 586type_descriptive_name_I (GType type) 587{ 588 if (type) 589 { 590 TypeNode *node = lookup_type_node_I (type); 591 592 return node ? NODE_NAME (node) : "<unknown>"; 593 } 594 else 595 return "<invalid>"; 596} 597 598 599/* --- type consistency checks --- */ 600static gboolean 601check_plugin_U (GTypePlugin *plugin, 602 gboolean need_complete_type_info, 603 gboolean need_complete_interface_info, 604 const gchar *type_name) 605{ 606 /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U 607 */ 608 if (!plugin) 609 { 610 g_warning ("plugin handle for type `%s' is NULL", 611 type_name); 612 return FALSE; 613 } 614 if (!G_IS_TYPE_PLUGIN (plugin)) 615 { 616 g_warning ("plugin pointer (%p) for type `%s' is invalid", 617 plugin, type_name); 618 return FALSE; 619 } 620 if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info) 621 { 622 g_warning ("plugin for type `%s' has no complete_type_info() implementation", 623 type_name); 624 return FALSE; 625 } 626 if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info) 627 { 628 g_warning ("plugin for type `%s' has no complete_interface_info() implementation", 629 type_name); 630 return FALSE; 631 } 632 return TRUE; 633} 634 635static gboolean 636check_type_name_I (const gchar *type_name) 637{ 638 static const gchar extra_chars[] = "-_+"; 639 const gchar *p = type_name; 640 gboolean name_valid; 641 642 if (!type_name[0] || !type_name[1] || !type_name[2]) 643 { 644 g_warning ("type name `%s' is too short", type_name); 645 return FALSE; 646 } 647 /* check the first letter */ 648 name_valid = (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || p[0] == '_'; 649 for (p = type_name + 1; *p; p++) 650 name_valid &= ((p[0] >= 'A' && p[0] <= 'Z') || 651 (p[0] >= 'a' && p[0] <= 'z') || 652 (p[0] >= '0' && p[0] <= '9') || 653 strchr (extra_chars, p[0])); 654 if (!name_valid) 655 { 656 g_warning ("type name `%s' contains invalid characters", type_name); 657 return FALSE; 658 } 659 if (g_type_from_name (type_name)) 660 { 661 g_warning ("cannot register existing type `%s'", type_name); 662 return FALSE; 663 } 664 665 return TRUE; 666} 667 668static gboolean 669check_derivation_I (GType parent_type, 670 const gchar *type_name) 671{ 672 TypeNode *pnode; 673 GTypeFundamentalInfo* finfo; 674 675 pnode = lookup_type_node_I (parent_type); 676 if (!pnode) 677 { 678 g_warning ("cannot derive type `%s' from invalid parent type `%s'", 679 type_name, 680 type_descriptive_name_I (parent_type)); 681 return FALSE; 682 } 683 finfo = type_node_fundamental_info_I (pnode); 684 /* ensure flat derivability */ 685 if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE)) 686 { 687 g_warning ("cannot derive `%s' from non-derivable parent type `%s'", 688 type_name, 689 NODE_NAME (pnode)); 690 return FALSE; 691 } 692 /* ensure deep derivability */ 693 if (parent_type != NODE_FUNDAMENTAL_TYPE (pnode) && 694 !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE)) 695 { 696 g_warning ("cannot derive `%s' from non-fundamental parent type `%s'", 697 type_name, 698 NODE_NAME (pnode)); 699 return FALSE; 700 } 701 702 return TRUE; 703} 704 705static gboolean 706check_collect_format_I (const gchar *collect_format) 707{ 708 const gchar *p = collect_format; 709 gchar valid_format[] = { G_VALUE_COLLECT_INT, G_VALUE_COLLECT_LONG, 710 G_VALUE_COLLECT_INT64, G_VALUE_COLLECT_DOUBLE, 711 G_VALUE_COLLECT_POINTER, 0 }; 712 713 while (*p) 714 if (!strchr (valid_format, *p++)) 715 return FALSE; 716 return p - collect_format <= G_VALUE_COLLECT_FORMAT_MAX_LENGTH; 717} 718 719static gboolean 720check_value_table_I (const gchar *type_name, 721 const GTypeValueTable *value_table) 722{ 723 if (!value_table) 724 return FALSE; 725 else if (value_table->value_init == NULL) 726 { 727 if (value_table->value_free || value_table->value_copy || 728 value_table->value_peek_pointer || 729 value_table->collect_format || value_table->collect_value || 730 value_table->lcopy_format || value_table->lcopy_value) 731 g_warning ("cannot handle uninitializable values of type `%s'", 732 type_name); 733 return FALSE; 734 } 735 else /* value_table->value_init != NULL */ 736 { 737 if (!value_table->value_free) 738 { 739 /* +++ optional +++ 740 * g_warning ("missing `value_free()' for type `%s'", type_name); 741 * return FALSE; 742 */ 743 } 744 if (!value_table->value_copy) 745 { 746 g_warning ("missing `value_copy()' for type `%s'", type_name); 747 return FALSE; 748 } 749 if ((value_table->collect_format || value_table->collect_value) && 750 (!value_table->collect_format || !value_table->collect_value)) 751 { 752 g_warning ("one of `collect_format' and `collect_value()' is unspecified for type `%s'", 753 type_name); 754 return FALSE; 755 } 756 if (value_table->collect_format && !check_collect_format_I (value_table->collect_format)) 757 { 758 g_warning ("the `%s' specification for type `%s' is too long or invalid", 759 "collect_format", 760 type_name); 761 return FALSE; 762 } 763 if ((value_table->lcopy_format || value_table->lcopy_value) && 764 (!value_table->lcopy_format || !value_table->lcopy_value)) 765 { 766 g_warning ("one of `lcopy_format' and `lcopy_value()' is unspecified for type `%s'", 767 type_name); 768 return FALSE; 769 } 770 if (value_table->lcopy_format && !check_collect_format_I (value_table->lcopy_format)) 771 { 772 g_warning ("the `%s' specification for type `%s' is too long or invalid", 773 "lcopy_format", 774 type_name); 775 return FALSE; 776 } 777 } 778 return TRUE; 779} 780 781static gboolean 782check_type_info_I (TypeNode *pnode, 783 GType ftype, 784 const gchar *type_name, 785 const GTypeInfo *info) 786{ 787 GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (lookup_type_node_I (ftype)); 788 gboolean is_interface = ftype == G_TYPE_INTERFACE; 789 790 g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX && !(ftype & TYPE_ID_MASK)); 791 792 /* check instance members */ 793 if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) && 794 (info->instance_size || info->n_preallocs || info->instance_init)) 795 { 796 if (pnode) 797 g_warning ("cannot instantiate `%s', derived from non-instantiatable parent type `%s'", 798 type_name, 799 NODE_NAME (pnode)); 800 else 801 g_warning ("cannot instantiate `%s' as non-instantiatable fundamental", 802 type_name); 803 return FALSE; 804 } 805 /* check class & interface members */ 806 if (!((finfo->type_flags & G_TYPE_FLAG_CLASSED) || is_interface) && 807 (info->class_init || info->class_finalize || info->class_data || 808 info->class_size || info->base_init || info->base_finalize)) 809 { 810 if (pnode) 811 g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'", 812 type_name, 813 NODE_NAME (pnode)); 814 else 815 g_warning ("cannot create class for `%s' as non-classed fundamental", 816 type_name); 817 return FALSE; 818 } 819 /* check interface size */ 820 if (is_interface && info->class_size < sizeof (GTypeInterface)) 821 { 822 g_warning ("specified interface size for type `%s' is smaller than `GTypeInterface' size", 823 type_name); 824 return FALSE; 825 } 826 /* check class size */ 827 if (finfo->type_flags & G_TYPE_FLAG_CLASSED) 828 { 829 if (info->class_size < sizeof (GTypeClass)) 830 { 831 g_warning ("specified class size for type `%s' is smaller than `GTypeClass' size", 832 type_name); 833 return FALSE; 834 } 835 if (pnode && info->class_size < pnode->data->class.class_size) 836 { 837 g_warning ("specified class size for type `%s' is smaller " 838 "than the parent type's `%s' class size", 839 type_name, 840 NODE_NAME (pnode)); 841 return FALSE; 842 } 843 } 844 /* check instance size */ 845 if (finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) 846 { 847 if (info->instance_size < sizeof (GTypeInstance)) 848 { 849 g_warning ("specified instance size for type `%s' is smaller than `GTypeInstance' size", 850 type_name); 851 return FALSE; 852 } 853 if (pnode && info->instance_size < pnode->data->instance.instance_size) 854 { 855 g_warning ("specified instance size for type `%s' is smaller " 856 "than the parent type's `%s' instance size", 857 type_name, 858 NODE_NAME (pnode)); 859 return FALSE; 860 } 861 } 862 863 return TRUE; 864} 865 866static TypeNode* 867find_conforming_child_type_L (TypeNode *pnode, 868 TypeNode *iface) 869{ 870 TypeNode *node = NULL; 871 guint i; 872 873 if (type_lookup_iface_entry_L (pnode, iface)) 874 return pnode; 875 876 for (i = 0; i < pnode->n_children && !node; i++) 877 node = find_conforming_child_type_L (lookup_type_node_I (pnode->children[i]), iface); 878 879 return node; 880} 881 882static gboolean 883check_add_interface_L (GType instance_type, 884 GType iface_type) 885{ 886 TypeNode *node = lookup_type_node_I (instance_type); 887 TypeNode *iface = lookup_type_node_I (iface_type); 888 IFaceEntry *entry; 889 TypeNode *tnode; 890 GType *prerequisites; 891 guint i; 892 893 894 if (!node || !node->is_instantiatable) 895 { 896 g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'", 897 type_descriptive_name_I (instance_type)); 898 return FALSE; 899 } 900 if (!iface || !NODE_IS_IFACE (iface)) 901 { 902 g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'", 903 type_descriptive_name_I (iface_type), 904 NODE_NAME (node)); 905 return FALSE; 906 } 907 tnode = lookup_type_node_I (NODE_PARENT_TYPE (iface)); 908 if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode)) 909 { 910 /* 2001/7/31:timj: erk, i guess this warning is junk as interface derivation is flat */ 911 g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'", 912 NODE_NAME (iface), 913 NODE_NAME (node), 914 NODE_NAME (tnode)); 915 return FALSE; 916 } 917 /* allow overriding of interface type introduced for parent type */ 918 entry = type_lookup_iface_entry_L (node, iface); 919 if (entry && entry->vtable == NULL && !type_iface_peek_holder_L (iface, NODE_TYPE (node))) 920 { 921 /* ok, we do conform to this interface already, but the interface vtable was not 922 * yet intialized, and we just conform to the interface because it got added to 923 * one of our parents. so we allow overriding of holder info here. 924 */ 925 return TRUE; 926 } 927 /* check whether one of our children already conforms (or whether the interface 928 * got added to this node already) 929 */ 930 tnode = find_conforming_child_type_L (node, iface); /* tnode is_a node */ 931 if (tnode) 932 { 933 g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface", 934 NODE_NAME (iface), 935 NODE_NAME (node), 936 NODE_NAME (tnode)); 937 return FALSE; 938 } 939 prerequisites = IFACE_NODE_PREREQUISITES (iface); 940 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++) 941 { 942 tnode = lookup_type_node_I (prerequisites[i]); 943 if (!type_node_is_a_L (node, tnode)) 944 { 945 g_warning ("cannot add interface type `%s' to type `%s' which does not conform to prerequisite `%s'", 946 NODE_NAME (iface), 947 NODE_NAME (node), 948 NODE_NAME (tnode)); 949 return FALSE; 950 } 951 } 952 return TRUE; 953} 954 955static gboolean 956check_interface_info_I (TypeNode *iface, 957 GType instance_type, 958 const GInterfaceInfo *info) 959{ 960 if ((info->interface_finalize || info->interface_data) && !info->interface_init) 961 { 962 g_warning ("interface type `%s' for type `%s' comes without initializer", 963 NODE_NAME (iface), 964 type_descriptive_name_I (instance_type)); 965 return FALSE; 966 } 967 968 return TRUE; 969} 970 971/* --- type info (type node data) --- */ 972static void 973type_data_make_W (TypeNode *node, 974 const GTypeInfo *info, 975 const GTypeValueTable *value_table) 976{ 977 TypeData *data; 978 GTypeValueTable *vtable = NULL; 979 guint vtable_size = 0; 980 981 g_assert (node->data == NULL && info != NULL); 982 983 if (!value_table) 984 { 985 TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); 986 987 if (pnode) 988 vtable = pnode->data->common.value_table; 989 else 990 { 991 static const GTypeValueTable zero_vtable = { NULL, }; 992 993 value_table = &zero_vtable; 994 } 995 } 996 if (value_table) 997 { 998 /* need to setup vtable_size since we have to allocate it with data in one chunk */ 999 vtable_size = sizeof (GTypeValueTable); 1000 if (value_table->collect_format) 1001 vtable_size += strlen (value_table->collect_format); 1002 if (value_table->lcopy_format) 1003 vtable_size += strlen (value_table->lcopy_format); 1004 vtable_size += 2; 1005 } 1006 1007 if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */ 1008 { 1009 data = g_malloc0 (sizeof (InstanceData) + vtable_size); 1010 if (vtable_size) 1011 vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData)); 1012 data->instance.class_size = info->class_size; 1013 data->instance.class_init_base = info->base_init; 1014 data->instance.class_finalize_base = info->base_finalize; 1015 data->instance.class_init = info->class_init; 1016 data->instance.class_finalize = info->class_finalize; 1017 data->instance.class_data = info->class_data; 1018 data->instance.class = NULL; 1019 data->instance.init_state = UNINITIALIZED; 1020 data->instance.instance_size = info->instance_size; 1021 /* We'll set the final value for data->instance.private size 1022 * after the parent class has been initialized 1023 */ 1024 data->instance.private_size = 0; 1025#ifdef DISABLE_MEM_POOLS 1026 data->instance.n_preallocs = 0; 1027#else /* !DISABLE_MEM_POOLS */ 1028 data->instance.n_preallocs = MIN (info->n_preallocs, 1024); 1029#endif /* !DISABLE_MEM_POOLS */ 1030 data->instance.instance_init = info->instance_init; 1031 } 1032 else if (node->is_classed) /* only classed */ 1033 { 1034 data = g_malloc0 (sizeof (ClassData) + vtable_size); 1035 if (vtable_size) 1036 vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData)); 1037 data->class.class_size = info->class_size; 1038 data->class.class_init_base = info->base_init; 1039 data->class.class_finalize_base = info->base_finalize; 1040 data->class.class_init = info->class_init; 1041 data->class.class_finalize = info->class_finalize; 1042 data->class.class_data = info->class_data; 1043 data->class.class = NULL; 1044 data->class.init_state = UNINITIALIZED; 1045 } 1046 else if (NODE_IS_IFACE (node)) 1047 { 1048 data = g_malloc0 (sizeof (IFaceData) + vtable_size); 1049 if (vtable_size) 1050 vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData)); 1051 data->iface.vtable_size = info->class_size; 1052 data->iface.vtable_init_base = info->base_init; 1053 data->iface.vtable_finalize_base = info->base_finalize; 1054 data->iface.dflt_init = info->class_init; 1055 data->iface.dflt_finalize = info->class_finalize; 1056 data->iface.dflt_data = info->class_data; 1057 data->iface.dflt_vtable = NULL; 1058 } 1059 else 1060 { 1061 data = g_malloc0 (sizeof (CommonData) + vtable_size); 1062 if (vtable_size) 1063 vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData)); 1064 } 1065 1066 node->data = data; 1067 node->data->common.ref_count = 1; 1068 1069 if (vtable_size) 1070 { 1071 gchar *p; 1072 1073 /* we allocate the vtable and its strings together with the type data, so 1074 * children can take over their parent's vtable pointer, and we don't 1075 * need to worry freeing it or not when the child data is destroyed 1076 */ 1077 *vtable = *value_table; 1078 p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable)); 1079 p[0] = 0; 1080 vtable->collect_format = p; 1081 if (value_table->collect_format) 1082 { 1083 strcat (p, value_table->collect_format); 1084 p += strlen (value_table->collect_format); 1085 } 1086 p++; 1087 p[0] = 0; 1088 vtable->lcopy_format = p; 1089 if (value_table->lcopy_format) 1090 strcat (p, value_table->lcopy_format); 1091 } 1092 node->data->common.value_table = vtable; 1093 node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL && 1094 !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) & 1095 GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)))); 1096 1097 g_assert (node->data->common.value_table != NULL); /* paranoid */ 1098} 1099 1100static inline void 1101type_data_ref_Wm (TypeNode *node) 1102{ 1103 if (!node->data) 1104 { 1105 TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); 1106 GTypeInfo tmp_info; 1107 GTypeValueTable tmp_value_table; 1108 1109 g_assert (node->plugin != NULL); 1110 1111 if (pnode) 1112 { 1113 type_data_ref_Wm (pnode); 1114 if (node->data) 1115 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node)); 1116 } 1117 1118 memset (&tmp_info, 0, sizeof (tmp_info)); 1119 memset (&tmp_value_table, 0, sizeof (tmp_value_table)); 1120 1121 G_WRITE_UNLOCK (&type_rw_lock); 1122 g_type_plugin_use (node->plugin); 1123 g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table); 1124 G_WRITE_LOCK (&type_rw_lock); 1125 if (node->data) 1126 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node)); 1127 1128 check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (node), NODE_NAME (node), &tmp_info); 1129 type_data_make_W (node, &tmp_info, 1130 check_value_table_I (NODE_NAME (node), 1131 &tmp_value_table) ? &tmp_value_table : NULL); 1132 } 1133 else 1134 { 1135 g_assert (node->data->common.ref_count > 0); 1136 1137 node->data->common.ref_count += 1; 1138 } 1139} 1140 1141static inline void 1142type_data_unref_WmREC (TypeNode *node, 1143 gboolean uncached) 1144{ 1145 g_assert (node->data && node->data->common.ref_count); 1146 if (node->data->common.ref_count > 1) 1147 node->data->common.ref_count -= 1; 1148 else 1149 { 1150 GType node_type = NODE_TYPE (node); 1151 if (!node->plugin) 1152 { 1153 g_warning ("static type `%s' unreferenced too often", 1154 NODE_NAME (node)); 1155 return; 1156 } 1157 G_WRITE_UNLOCK (&type_rw_lock); 1158 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */ 1159 G_WRITE_LOCK (&type_rw_lock); 1160 type_data_last_unref_Wm (node_type, uncached); 1161 g_static_rec_mutex_unlock (&class_init_rec_mutex); 1162 } 1163} 1164 1165static void 1166type_node_add_iface_entry_W (TypeNode *node, 1167 GType iface_type, 1168 IFaceEntry *parent_entry) 1169{ 1170 IFaceEntry *entries; 1171 guint i; 1172 1173 g_assert (node->is_instantiatable && CLASSED_NODE_N_IFACES (node) < MAX_N_IFACES); 1174 1175 entries = CLASSED_NODE_IFACES_ENTRIES (node); 1176 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++) 1177 if (entries[i].iface_type == iface_type) 1178 { 1179 /* this can happen in two cases: 1180 * - our parent type already conformed to iface_type and node 1181 * got its own holder info. here, our children already have 1182 * entries and NULL vtables, since this will only work for 1183 * uninitialized classes. 1184 * - an interface type is added to an ancestor after it was 1185 * added to a child type. 1186 */ 1187 if (!parent_entry) 1188 g_assert (entries[i].vtable == NULL && entries[i].init_state == UNINITIALIZED); 1189 else 1190 { 1191 /* sick, interface is added to ancestor *after* child type; 1192 * nothing todo, the entry and our children were already setup correctly 1193 */ 1194 } 1195 return; 1196 } 1197 else if (entries[i].iface_type > iface_type) 1198 break; 1199 CLASSED_NODE_N_IFACES (node) += 1; 1200 CLASSED_NODE_IFACES_ENTRIES (node) = g_renew (IFaceEntry, 1201 CLASSED_NODE_IFACES_ENTRIES (node), 1202 CLASSED_NODE_N_IFACES (node)); 1203 entries = CLASSED_NODE_IFACES_ENTRIES (node); 1204 g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (CLASSED_NODE_N_IFACES (node) - i - 1)); 1205 entries[i].iface_type = iface_type; 1206 entries[i].vtable = NULL; 1207 entries[i].init_state = UNINITIALIZED; 1208 1209 if (parent_entry) 1210 { 1211 if (node->data && node->data->class.init_state >= BASE_IFACE_INIT) 1212 { 1213 entries[i].init_state = INITIALIZED; 1214 entries[i].vtable = parent_entry->vtable; 1215 } 1216 for (i = 0; i < node->n_children; i++) 1217 type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), iface_type, &entries[i]); 1218 } 1219} 1220 1221static void 1222type_add_interface_Wm (TypeNode *node, 1223 TypeNode *iface, 1224 const GInterfaceInfo *info, 1225 GTypePlugin *plugin) 1226{ 1227 IFaceHolder *iholder = g_new0 (IFaceHolder, 1); 1228 IFaceEntry *entry; 1229 guint i; 1230 1231 g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin))); 1232 1233 iholder->next = iface_node_get_holders_L (iface); 1234 iface_node_set_holders_W (iface, iholder); 1235 iholder->instance_type = NODE_TYPE (node); 1236 iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL; 1237 iholder->plugin = plugin; 1238 1239 /* create an iface entry for this type */ 1240 type_node_add_iface_entry_W (node, NODE_TYPE (iface), NULL); 1241 1242 /* if the class is already (partly) initialized, we may need to base 1243 * initalize and/or initialize the new interface. 1244 */ 1245 if (node->data) 1246 { 1247 InitState class_state = node->data->class.init_state; 1248 1249 if (class_state >= BASE_IFACE_INIT) 1250 type_iface_vtable_base_init_Wm (iface, node); 1251 1252 if (class_state >= IFACE_INIT) 1253 type_iface_vtable_iface_init_Wm (iface, node); 1254 } 1255 1256 /* create iface entries for children of this type */ 1257 entry = type_lookup_iface_entry_L (node, iface); 1258 for (i = 0; i < node->n_children; i++) 1259 type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), NODE_TYPE (iface), entry); 1260} 1261 1262static void 1263type_iface_add_prerequisite_W (TypeNode *iface, 1264 TypeNode *prerequisite_node) 1265{ 1266 GType prerequisite_type = NODE_TYPE (prerequisite_node); 1267 GType *prerequisites, *dependants; 1268 guint n_dependants, i; 1269 1270 g_assert (NODE_IS_IFACE (iface) && 1271 IFACE_NODE_N_PREREQUISITES (iface) < MAX_N_PREREQUISITES && 1272 (prerequisite_node->is_instantiatable || NODE_IS_IFACE (prerequisite_node))); 1273 1274 prerequisites = IFACE_NODE_PREREQUISITES (iface); 1275 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++) 1276 if (prerequisites[i] == prerequisite_type) 1277 return; /* we already have that prerequisiste */ 1278 else if (prerequisites[i] > prerequisite_type) 1279 break; 1280 IFACE_NODE_N_PREREQUISITES (iface) += 1; 1281 IFACE_NODE_PREREQUISITES (iface) = g_renew (GType, 1282 IFACE_NODE_PREREQUISITES (iface), 1283 IFACE_NODE_N_PREREQUISITES (iface)); 1284 prerequisites = IFACE_NODE_PREREQUISITES (iface); 1285 g_memmove (prerequisites + i + 1, prerequisites + i, 1286 sizeof (prerequisites[0]) * (IFACE_NODE_N_PREREQUISITES (iface) - i - 1)); 1287 prerequisites[i] = prerequisite_type; 1288 1289 /* we want to get notified when prerequisites get added to prerequisite_node */ 1290 if (NODE_IS_IFACE (prerequisite_node)) 1291 { 1292 dependants = iface_node_get_dependants_array_L (prerequisite_node); 1293 n_dependants = dependants ? dependants[0] : 0; 1294 n_dependants += 1; 1295 dependants = g_renew (GType, dependants, n_dependants + 1); 1296 dependants[n_dependants] = NODE_TYPE (iface); 1297 dependants[0] = n_dependants; 1298 iface_node_set_dependants_array_W (prerequisite_node, dependants); 1299 } 1300 1301 /* we need to notify all dependants */ 1302 dependants = iface_node_get_dependants_array_L (iface); 1303 n_dependants = dependants ? dependants[0] : 0; 1304 for (i = 1; i <= n_dependants; i++) 1305 type_iface_add_prerequisite_W (lookup_type_node_I (dependants[i]), prerequisite_node); 1306} 1307 1308/** 1309 * g_type_interface_add_prerequisite: 1310 * @interface_type: #GType value of an interface type. 1311 * @prerequisite_type: #GType value of an interface or instantiatable type. 1312 * 1313 * Adds @prerequisite_type to the list of prerequisites of @interface_type. 1314 * This means that any type implementing @interface_type must also implement 1315 * @prerequisite_type. Prerequisites can be thought of as an alternative to 1316 * interface derivation (which GType doesn't support). An interface can have 1317 * at most one instantiatable prerequisite type. 1318 */ 1319void 1320g_type_interface_add_prerequisite (GType interface_type, 1321 GType prerequisite_type) 1322{ 1323 TypeNode *iface, *prerequisite_node; 1324 IFaceHolder *holders; 1325 1326 g_return_if_fail (G_TYPE_IS_INTERFACE (interface_type)); /* G_TYPE_IS_INTERFACE() is an external call: _U */ 1327 g_return_if_fail (!g_type_is_a (interface_type, prerequisite_type)); 1328 g_return_if_fail (!g_type_is_a (prerequisite_type, interface_type)); 1329 1330 iface = lookup_type_node_I (interface_type); 1331 prerequisite_node = lookup_type_node_I (prerequisite_type); 1332 if (!iface || !prerequisite_node || !NODE_IS_IFACE (iface)) 1333 { 1334 g_warning ("interface type `%s' or prerequisite type `%s' invalid", 1335 type_descriptive_name_I (interface_type), 1336 type_descriptive_name_I (prerequisite_type)); 1337 return; 1338 } 1339 G_WRITE_LOCK (&type_rw_lock); 1340 holders = iface_node_get_holders_L (iface); 1341 if (holders) 1342 { 1343 G_WRITE_UNLOCK (&type_rw_lock); 1344 g_warning ("unable to add prerequisite `%s' to interface `%s' which is already in use for `%s'", 1345 type_descriptive_name_I (prerequisite_type), 1346 type_descriptive_name_I (interface_type), 1347 type_descriptive_name_I (holders->instance_type)); 1348 return; 1349 } 1350 if (prerequisite_node->is_instantiatable) 1351 { 1352 guint i; 1353 1354 /* can have at most one publically installable instantiatable prerequisite */ 1355 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++) 1356 { 1357 TypeNode *prnode = lookup_type_node_I (IFACE_NODE_PREREQUISITES (iface)[i]); 1358 1359 if (prnode->is_instantiatable) 1360 { 1361 G_WRITE_UNLOCK (&type_rw_lock); 1362 g_warning ("adding prerequisite `%s' to interface `%s' conflicts with existing prerequisite `%s'", 1363 type_descriptive_name_I (prerequisite_type), 1364 type_descriptive_name_I (interface_type), 1365 type_descriptive_name_I (NODE_TYPE (prnode))); 1366 return; 1367 } 1368 } 1369 1370 for (i = 0; i < prerequisite_node->n_supers + 1; i++) 1371 type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisite_node->supers[i])); 1372 G_WRITE_UNLOCK (&type_rw_lock); 1373 } 1374 else if (NODE_IS_IFACE (prerequisite_node)) 1375 { 1376 GType *prerequisites; 1377 guint i; 1378 1379 prerequisites = IFACE_NODE_PREREQUISITES (prerequisite_node); 1380 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (prerequisite_node); i++) 1381 type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisites[i])); 1382 type_iface_add_prerequisite_W (iface, prerequisite_node); 1383 G_WRITE_UNLOCK (&type_rw_lock); 1384 } 1385 else 1386 { 1387 G_WRITE_UNLOCK (&type_rw_lock); 1388 g_warning ("prerequisite `%s' for interface `%s' is neither instantiatable nor interface", 1389 type_descriptive_name_I (prerequisite_type), 1390 type_descriptive_name_I (interface_type)); 1391 } 1392} 1393 1394/** 1395 * g_type_interface_prerequisites: 1396 * @interface_type: an interface type 1397 * @n_prerequisites: location to return the number of prerequisites, or %NULL 1398 * 1399 * Returns the prerequisites of an interfaces type. 1400 * 1401 * Since: 2.2 1402 * 1403 * Returns: a newly-allocated zero-terminated array of #GType containing 1404 * the prerequisites of @interface_type 1405 */ 1406GType* 1407g_type_interface_prerequisites (GType interface_type, 1408 guint *n_prerequisites) 1409{ 1410 TypeNode *iface; 1411 1412 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL); 1413 1414 iface = lookup_type_node_I (interface_type); 1415 if (iface) 1416 { 1417 GType *types; 1418 TypeNode *inode = NULL; 1419 guint i, n = 0; 1420 1421 G_READ_LOCK (&type_rw_lock); 1422 types = g_new0 (GType, IFACE_NODE_N_PREREQUISITES (iface) + 1); 1423 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++) 1424 { 1425 GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i]; 1426 TypeNode *node = lookup_type_node_I (prerequisite); 1427 if (node->is_instantiatable && 1428 (!inode || type_node_is_a_L (node, inode))) 1429 inode = node; 1430 else 1431 types[n++] = NODE_TYPE (node); 1432 } 1433 if (inode) 1434 types[n++] = NODE_TYPE (inode); 1435 1436 if (n_prerequisites) 1437 *n_prerequisites = n; 1438 G_READ_UNLOCK (&type_rw_lock); 1439 1440 return types; 1441 } 1442 else 1443 { 1444 if (n_prerequisites) 1445 *n_prerequisites = 0; 1446 1447 return NULL; 1448 } 1449} 1450 1451 1452static IFaceHolder* 1453type_iface_peek_holder_L (TypeNode *iface, 1454 GType instance_type) 1455{ 1456 IFaceHolder *iholder; 1457 1458 g_assert (NODE_IS_IFACE (iface)); 1459 1460 iholder = iface_node_get_holders_L (iface); 1461 while (iholder && iholder->instance_type != instance_type) 1462 iholder = iholder->next; 1463 return iholder; 1464} 1465 1466static IFaceHolder* 1467type_iface_retrieve_holder_info_Wm (TypeNode *iface, 1468 GType instance_type, 1469 gboolean need_info) 1470{ 1471 IFaceHolder *iholder = type_iface_peek_holder_L (iface, instance_type); 1472 1473 if (iholder && !iholder->info && need_info) 1474 { 1475 GInterfaceInfo tmp_info; 1476 1477 g_assert (iholder->plugin != NULL); 1478 1479 type_data_ref_Wm (iface); 1480 if (iholder->info) 1481 INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface)); 1482 1483 memset (&tmp_info, 0, sizeof (tmp_info)); 1484 1485 G_WRITE_UNLOCK (&type_rw_lock); 1486 g_type_plugin_use (iholder->plugin); 1487 g_type_plugin_complete_interface_info (iholder->plugin, instance_type, NODE_TYPE (iface), &tmp_info); 1488 G_WRITE_LOCK (&type_rw_lock); 1489 if (iholder->info) 1490 INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface)); 1491 1492 check_interface_info_I (iface, instance_type, &tmp_info); 1493 iholder->info = g_memdup (&tmp_info, sizeof (tmp_info)); 1494 } 1495 1496 return iholder; /* we don't modify write lock upon returning NULL */ 1497} 1498 1499static void 1500type_iface_blow_holder_info_Wm (TypeNode *iface, 1501 GType instance_type) 1502{ 1503 IFaceHolder *iholder = iface_node_get_holders_L (iface); 1504 1505 g_assert (NODE_IS_IFACE (iface)); 1506 1507 while (iholder->instance_type != instance_type) 1508 iholder = iholder->next; 1509 1510 if (iholder->info && iholder->plugin) 1511 { 1512 g_free (iholder->info); 1513 iholder->info = NULL; 1514 1515 G_WRITE_UNLOCK (&type_rw_lock); 1516 g_type_plugin_unuse (iholder->plugin); 1517 G_WRITE_LOCK (&type_rw_lock); 1518 1519 type_data_unref_WmREC (iface, FALSE); 1520 } 1521} 1522 1523/* Assumes type's class already exists 1524 */ 1525static inline size_t 1526type_total_instance_size_I (TypeNode *node) 1527{ 1528 gsize total_instance_size; 1529 1530 total_instance_size = node->data->instance.instance_size; 1531 if (node->data->instance.private_size != 0) 1532 total_instance_size = ALIGN_STRUCT (total_instance_size) + node->data->instance.private_size; 1533 1534 return total_instance_size; 1535} 1536 1537/* --- type structure creation/destruction --- */ 1538typedef struct { 1539 gpointer instance; 1540 gpointer class; 1541} InstanceRealClass; 1542 1543static gint 1544instance_real_class_cmp (gconstpointer p1, 1545 gconstpointer p2) 1546{ 1547 const InstanceRealClass *irc1 = p1; 1548 const InstanceRealClass *irc2 = p2; 1549 guint8 *i1 = irc1->instance; 1550 guint8 *i2 = irc2->instance; 1551 return G_BSEARCH_ARRAY_CMP (i1, i2); 1552} 1553 1554G_LOCK_DEFINE_STATIC (instance_real_class); 1555static GBSearchArray *instance_real_class_bsa = NULL; 1556static GBSearchConfig instance_real_class_bconfig = { 1557 sizeof (InstanceRealClass), 1558 instance_real_class_cmp, 1559 0, 1560}; 1561 1562static inline void 1563instance_real_class_set (gpointer instance, 1564 GTypeClass *class) 1565{ 1566 InstanceRealClass key; 1567 key.instance = instance; 1568 key.class = class; 1569 G_LOCK (instance_real_class); 1570 if (!instance_real_class_bsa) 1571 instance_real_class_bsa = g_bsearch_array_create (&instance_real_class_bconfig); 1572 instance_real_class_bsa = g_bsearch_array_replace (instance_real_class_bsa, &instance_real_class_bconfig, &key); 1573 G_UNLOCK (instance_real_class); 1574} 1575 1576static inline void 1577instance_real_class_remove (gpointer instance) 1578{ 1579 InstanceRealClass key, *node; 1580 guint index; 1581 key.instance = instance; 1582 G_LOCK (instance_real_class); 1583 node = g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key); 1584 index = g_bsearch_array_get_index (instance_real_class_bsa, &instance_real_class_bconfig, node); 1585 instance_real_class_bsa = g_bsearch_array_remove (instance_real_class_bsa, &instance_real_class_bconfig, index); 1586 if (!g_bsearch_array_get_n_nodes (instance_real_class_bsa)) 1587 { 1588 g_bsearch_array_free (instance_real_class_bsa, &instance_real_class_bconfig); 1589 instance_real_class_bsa = NULL; 1590 } 1591 G_UNLOCK (instance_real_class); 1592} 1593 1594static inline GTypeClass* 1595instance_real_class_get (gpointer instance) 1596{ 1597 InstanceRealClass key, *node; 1598 GTypeClass *class; 1599 key.instance = instance; 1600 G_LOCK (instance_real_class); 1601 node = instance_real_class_bsa ? g_bsearch_array_lookup (instance_real_class_bsa, &instance_real_class_bconfig, &key) : NULL; 1602 class = node ? node->class : NULL; 1603 G_UNLOCK (instance_real_class); 1604 return class; 1605} 1606 1607/** 1608 * g_type_create_instance: 1609 * @type: An instantiatable type to create an instance for. 1610 * 1611 * Creates and initializes an instance of @type if @type is valid and 1612 * can be instantiated. The type system only performs basic allocation 1613 * and structure setups for instances: actual instance creation should 1614 * happen through functions supplied by the type's fundamental type 1615 * implementation. So use of g_type_create_instance() is reserved for 1616 * implementators of fundamental types only. E.g. instances of the 1617 * #GObject hierarchy should be created via g_object_new() and 1618 * <emphasis>never</emphasis> directly through 1619 * g_type_create_instance() which doesn't handle things like singleton 1620 * objects or object construction. Note: Do <emphasis>not</emphasis> 1621 * use this function, unless you're implementing a fundamental 1622 * type. Also language bindings should <emphasis>not</emphasis> use 1623 * this function but g_object_new() instead. 1624 * 1625 * Returns: An allocated and initialized instance, subject to further 1626 * treatment by the fundamental type implementation. 1627 */ 1628GTypeInstance* 1629g_type_create_instance (GType type) 1630{ 1631 TypeNode *node; 1632 GTypeInstance *instance; 1633 GTypeClass *class; 1634 guint i, total_size; 1635 1636 node = lookup_type_node_I (type); 1637 if (!node || !node->is_instantiatable) 1638 { 1639 g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'", 1640 type_descriptive_name_I (type)); 1641 return NULL; 1642 } 1643 /* G_TYPE_IS_ABSTRACT() is an external call: _U */ 1644 if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (type)) 1645 { 1646 g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'", 1647 type_descriptive_name_I (type)); 1648 return NULL; 1649 } 1650 1651 class = g_type_class_ref (type); 1652 total_size = type_total_instance_size_I (node); 1653 1654 instance = g_slice_alloc0 (total_size); 1655 1656 if (node->data->instance.private_size) 1657 instance_real_class_set (instance, class); 1658 for (i = node->n_supers; i > 0; i--) 1659 { 1660 TypeNode *pnode; 1661 1662 pnode = lookup_type_node_I (node->supers[i]); 1663 if (pnode->data->instance.instance_init) 1664 { 1665 instance->g_class = pnode->data->instance.class; 1666 pnode->data->instance.instance_init (instance, class); 1667 } 1668 } 1669 if (node->data->instance.private_size) 1670 instance_real_class_remove (instance); 1671 1672 instance->g_class = class; 1673 if (node->data->instance.instance_init) 1674 node->data->instance.instance_init (instance, class); 1675 1676 return instance; 1677} 1678 1679/** 1680 * g_type_free_instance: 1681 * @instance: an instance of a type. 1682 * 1683 * Frees an instance of a type, returning it to the instance pool for 1684 * the type, if there is one. 1685 * 1686 * Like g_type_create_instance(), this function is reserved for 1687 * implementors of fundamental types. 1688 */ 1689void 1690g_type_free_instance (GTypeInstance *instance) 1691{ 1692 TypeNode *node; 1693 GTypeClass *class; 1694 1695 g_return_if_fail (instance != NULL && instance->g_class != NULL); 1696 1697 class = instance->g_class; 1698 node = lookup_type_node_I (class->g_type); 1699 if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class) 1700 { 1701 g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'", 1702 type_descriptive_name_I (class->g_type)); 1703 return; 1704 } 1705 /* G_TYPE_IS_ABSTRACT() is an external call: _U */ 1706 if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (NODE_TYPE (node))) 1707 { 1708 g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'", 1709 NODE_NAME (node)); 1710 return; 1711 } 1712 1713 instance->g_class = NULL; 1714#ifdef G_ENABLE_DEBUG 1715 memset (instance, 0xaa, type_total_instance_size_I (node)); 1716#endif 1717 g_slice_free1 (type_total_instance_size_I (node), instance); 1718 1719 g_type_class_unref (class); 1720} 1721 1722static void 1723type_iface_ensure_dflt_vtable_Wm (TypeNode *iface) 1724{ 1725 g_assert (iface->data); 1726 1727 if (!iface->data->iface.dflt_vtable) 1728 { 1729 GTypeInterface *vtable = g_malloc0 (iface->data->iface.vtable_size); 1730 iface->data->iface.dflt_vtable = vtable; 1731 vtable->g_type = NODE_TYPE (iface); 1732 vtable->g_instance_type = 0; 1733 if (iface->data->iface.vtable_init_base || 1734 iface->data->iface.dflt_init) 1735 { 1736 G_WRITE_UNLOCK (&type_rw_lock); 1737 if (iface->data->iface.vtable_init_base) 1738 iface->data->iface.vtable_init_base (vtable); 1739 if (iface->data->iface.dflt_init) 1740 iface->data->iface.dflt_init (vtable, (gpointer) iface->data->iface.dflt_data); 1741 G_WRITE_LOCK (&type_rw_lock); 1742 } 1743 } 1744} 1745 1746 1747/* This is called to allocate and do the first part of initializing 1748 * the interface vtable; type_iface_vtable_iface_init_Wm() does the remainder. 1749 * 1750 * A FALSE return indicates that we didn't find an init function for 1751 * this type/iface pair, so the vtable from the parent type should 1752 * be used. Note that the write lock is not modified upon a FALSE 1753 * return. 1754 */ 1755static gboolean 1756type_iface_vtable_base_init_Wm (TypeNode *iface, 1757 TypeNode *node) 1758{ 1759 IFaceEntry *entry; 1760 IFaceHolder *iholder; 1761 GTypeInterface *vtable = NULL; 1762 TypeNode *pnode; 1763 1764 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */ 1765 iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), TRUE); 1766 if (!iholder) 1767 return FALSE; /* we don't modify write lock upon FALSE */ 1768 1769 type_iface_ensure_dflt_vtable_Wm (iface); 1770 1771 entry = type_lookup_iface_entry_L (node, iface); 1772 1773 g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info); 1774 1775 entry->init_state = IFACE_INIT; 1776 1777 pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); 1778 if (pnode) /* want to copy over parent iface contents */ 1779 { 1780 IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface); 1781 1782 if (pentry) 1783 vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size); 1784 } 1785 if (!vtable) 1786 vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); 1787 entry->vtable = vtable; 1788 vtable->g_type = NODE_TYPE (iface); 1789 vtable->g_instance_type = NODE_TYPE (node); 1790 1791 if (iface->data->iface.vtable_init_base) 1792 { 1793 G_WRITE_UNLOCK (&type_rw_lock); 1794 iface->data->iface.vtable_init_base (vtable); 1795 G_WRITE_LOCK (&type_rw_lock); 1796 } 1797 return TRUE; /* initialized the vtable */ 1798} 1799 1800/* Finishes what type_iface_vtable_base_init_Wm started by 1801 * calling the interface init function. 1802 * this function may only be called for types with their 1803 * own interface holder info, i.e. types for which 1804 * g_type_add_interface*() was called and not children thereof. 1805 */ 1806static void 1807type_iface_vtable_iface_init_Wm (TypeNode *iface, 1808 TypeNode *node) 1809{ 1810 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface); 1811 IFaceHolder *iholder = type_iface_peek_holder_L (iface, NODE_TYPE (node)); 1812 GTypeInterface *vtable = NULL; 1813 guint i; 1814 1815 /* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */ 1816 g_assert (iface->data && entry && iholder && iholder->info); 1817 g_assert (entry->init_state == IFACE_INIT); /* assert prior base_init() */ 1818 1819 entry->init_state = INITIALIZED; 1820 1821 vtable = entry->vtable; 1822 1823 if (iholder->info->interface_init) 1824 { 1825 G_WRITE_UNLOCK (&type_rw_lock); 1826 if (iholder->info->interface_init) 1827 iholder->info->interface_init (vtable, iholder->info->interface_data); 1828 G_WRITE_LOCK (&type_rw_lock); 1829 } 1830 1831 for (i = 0; i < static_n_iface_check_funcs; i++) 1832 { 1833 GTypeInterfaceCheckFunc check_func = static_iface_check_funcs[i].check_func; 1834 gpointer check_data = static_iface_check_funcs[i].check_data; 1835 1836 G_WRITE_UNLOCK (&type_rw_lock); 1837 check_func (check_data, (gpointer)vtable); 1838 G_WRITE_LOCK (&type_rw_lock); 1839 } 1840} 1841 1842static gboolean 1843type_iface_vtable_finalize_Wm (TypeNode *iface, 1844 TypeNode *node, 1845 GTypeInterface *vtable) 1846{ 1847 IFaceEntry *entry = type_lookup_iface_entry_L (node, iface); 1848 IFaceHolder *iholder; 1849 1850 /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */ 1851 iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), FALSE); 1852 if (!iholder) 1853 return FALSE; /* we don't modify write lock upon FALSE */ 1854 1855 g_assert (entry && entry->vtable == vtable && iholder->info); 1856 1857 entry->vtable = NULL; 1858 entry->init_state = UNINITIALIZED; 1859 if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base) 1860 { 1861 G_WRITE_UNLOCK (&type_rw_lock); 1862 if (iholder->info->interface_finalize) 1863 iholder->info->interface_finalize (vtable, iholder->info->interface_data); 1864 if (iface->data->iface.vtable_finalize_base) 1865 iface->data->iface.vtable_finalize_base (vtable); 1866 G_WRITE_LOCK (&type_rw_lock); 1867 } 1868 vtable->g_type = 0; 1869 vtable->g_instance_type = 0; 1870 g_free (vtable); 1871 1872 type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node)); 1873 1874 return TRUE; /* write lock modified */ 1875} 1876 1877static void 1878type_class_init_Wm (TypeNode *node, 1879 GTypeClass *pclass) 1880{ 1881 GSList *slist, *init_slist = NULL; 1882 GTypeClass *class; 1883 IFaceEntry *entry; 1884 TypeNode *bnode, *pnode; 1885 guint i; 1886 1887 g_assert (node->is_classed && node->data && 1888 node->data->class.class_size && 1889 !node->data->class.class && 1890 node->data->class.init_state == UNINITIALIZED); 1891 1892 class = g_malloc0 (node->data->class.class_size); 1893 node->data->class.class = class; 1894 node->data->class.init_state = BASE_CLASS_INIT; 1895 1896 if (pclass) 1897 { 1898 TypeNode *pnode = lookup_type_node_I (pclass->g_type); 1899 1900 memcpy (class, pclass, pnode->data->class.class_size); 1901 1902 if (node->is_instantiatable) 1903 { 1904 /* We need to initialize the private_size here rather than in 1905 * type_data_make_W() since the class init for the parent 1906 * class may have changed pnode->data->instance.private_size. 1907 */ 1908 node->data->instance.private_size = pnode->data->instance.private_size; 1909 } 1910 } 1911 class->g_type = NODE_TYPE (node); 1912 1913 G_WRITE_UNLOCK (&type_rw_lock); 1914 1915 /* stack all base class initialization functions, so we 1916 * call them in ascending order. 1917 */ 1918 for (bnode = node; bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode))) 1919 if (bnode->data->class.class_init_base) 1920 init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base); 1921 for (slist = init_slist; slist; slist = slist->next) 1922 { 1923 GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data; 1924 1925 class_init_base (class); 1926 } 1927 g_slist_free (init_slist); 1928 1929 G_WRITE_LOCK (&type_rw_lock); 1930 1931 node->data->class.init_state = BASE_IFACE_INIT; 1932 1933 /* Before we initialize the class, base initialize all interfaces, either 1934 * from parent, or through our holder info 1935 */ 1936 pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); 1937 1938 i = 0; 1939 while (i < CLASSED_NODE_N_IFACES (node)) 1940 { 1941 entry = &CLASSED_NODE_IFACES_ENTRIES (node)[i]; 1942 while (i < CLASSED_NODE_N_IFACES (node) && 1943 entry->init_state == IFACE_INIT) 1944 { 1945 entry++; 1946 i++; 1947 } 1948 1949 if (i == CLASSED_NODE_N_IFACES (node)) 1950 break; 1951 1952 if (!type_iface_vtable_base_init_Wm (lookup_type_node_I (entry->iface_type), node)) 1953 { 1954 guint j; 1955 1956 /* need to get this interface from parent, type_iface_vtable_base_init_Wm() 1957 * doesn't modify write lock upon FALSE, so entry is still valid; 1958 */ 1959 g_assert (pnode != NULL); 1960 1961 for (j = 0; j < CLASSED_NODE_N_IFACES (pnode); j++) 1962 { 1963 IFaceEntry *pentry = CLASSED_NODE_IFACES_ENTRIES (pnode) + j; 1964 1965 if (pentry->iface_type == entry->iface_type) 1966 { 1967 entry->vtable = pentry->vtable; 1968 entry->init_state = INITIALIZED; 1969 break; 1970 } 1971 } 1972 g_assert (entry->vtable != NULL); 1973 } 1974 1975 /* If the write lock was released, additional interface entries might 1976 * have been inserted into CLASSED_NODE_IFACES_ENTRIES (node); they'll 1977 * be base-initialized when inserted, so we don't have to worry that 1978 * we might miss them. Uninitialized entries can only be moved higher 1979 * when new ones are inserted. 1980 */ 1981 i++; 1982 } 1983 1984 node->data->class.init_state = CLASS_INIT; 1985 1986 G_WRITE_UNLOCK (&type_rw_lock); 1987 1988 if (node->data->class.class_init) 1989 node->data->class.class_init (class, (gpointer) node->data->class.class_data); 1990 1991 G_WRITE_LOCK (&type_rw_lock); 1992 1993 node->data->class.init_state = IFACE_INIT; 1994 1995 /* finish initializing the interfaces through our holder info. 1996 * inherited interfaces are already init_state == INITIALIZED, because 1997 * they either got setup in the above base_init loop, or during 1998 * class_init from within type_add_interface_Wm() for this or 1999 * an anchestor type. 2000 */ 2001 i = 0; 2002 while (TRUE) 2003 { 2004 entry = &CLASSED_NODE_IFACES_ENTRIES (node)[i]; 2005 while (i < CLASSED_NODE_N_IFACES (node) && 2006 entry->init_state == INITIALIZED) 2007 { 2008 entry++; 2009 i++; 2010 } 2011 2012 if (i == CLASSED_NODE_N_IFACES (node)) 2013 break; 2014 2015 type_iface_vtable_iface_init_Wm (lookup_type_node_I (entry->iface_type), node); 2016 2017 /* As in the loop above, additional initialized entries might be inserted 2018 * if the write lock is released, but that's harmless because the entries 2019 * we need to initialize only move higher in the list. 2020 */ 2021 i++; 2022 } 2023 2024 node->data->class.init_state = INITIALIZED; 2025} 2026 2027static void 2028type_data_finalize_class_ifaces_Wm (TypeNode *node) 2029{ 2030 guint i; 2031 2032 g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0); 2033 2034 reiterate: 2035 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++) 2036 { 2037 IFaceEntry *entry = CLASSED_NODE_IFACES_ENTRIES (node) + i; 2038 if (entry->vtable) 2039 { 2040 if (type_iface_vtable_finalize_Wm (lookup_type_node_I (entry->iface_type), node, entry->vtable)) 2041 { 2042 /* refetch entries, IFACES_ENTRIES might be modified */ 2043 goto reiterate; 2044 } 2045 else 2046 { 2047 /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE, 2048 * iface vtable came from parent 2049 */ 2050 entry->vtable = NULL; 2051 entry->init_state = UNINITIALIZED; 2052 } 2053 } 2054 } 2055} 2056 2057static void 2058type_data_finalize_class_U (TypeNode *node, 2059 ClassData *cdata) 2060{ 2061 GTypeClass *class = cdata->class; 2062 TypeNode *bnode; 2063 2064 g_assert (cdata->class && cdata->common.ref_count == 0); 2065 2066 if (cdata->class_finalize) 2067 cdata->class_finalize (class, (gpointer) cdata->class_data); 2068 2069 /* call all base class destruction functions in descending order 2070 */ 2071 if (cdata->class_finalize_base) 2072 cdata->class_finalize_base (class); 2073 for (bnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode))) 2074 if (bnode->data->class.class_finalize_base) 2075 bnode->data->class.class_finalize_base (class); 2076 2077 g_free (cdata->class); 2078} 2079 2080static void 2081type_data_last_unref_Wm (GType type, 2082 gboolean uncached) 2083{ 2084 TypeNode *node = lookup_type_node_I (type); 2085 2086 g_return_if_fail (node != NULL && node->plugin != NULL); 2087 2088 if (!node->data || node->data->common.ref_count == 0) 2089 { 2090 g_warning ("cannot drop last reference to unreferenced type `%s'", 2091 type_descriptive_name_I (type)); 2092 return; 2093 } 2094 2095 /* call class cache hooks */ 2096 if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs && !uncached) 2097 { 2098 guint i; 2099 2100 G_WRITE_UNLOCK (&type_rw_lock); 2101 G_READ_LOCK (&type_rw_lock); 2102 for (i = 0; i < static_n_class_cache_funcs; i++) 2103 { 2104 GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func; 2105 gpointer cache_data = static_class_cache_funcs[i].cache_data; 2106 gboolean need_break; 2107 2108 G_READ_UNLOCK (&type_rw_lock); 2109 need_break = cache_func (cache_data, node->data->class.class); 2110 G_READ_LOCK (&type_rw_lock); 2111 if (!node->data || node->data->common.ref_count == 0) 2112 INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node)); 2113 if (need_break) 2114 break; 2115 } 2116 G_READ_UNLOCK (&type_rw_lock); 2117 G_WRITE_LOCK (&type_rw_lock); 2118 } 2119 2120 if (node->data->common.ref_count > 1) /* may have been re-referenced meanwhile */ 2121 node->data->common.ref_count -= 1; 2122 else 2123 { 2124 GType ptype = NODE_PARENT_TYPE (node); 2125 TypeData *tdata; 2126 2127 node->data->common.ref_count = 0; 2128 2129 if (node->is_instantiatable) 2130 { 2131 /* destroy node->data->instance.mem_chunk */ 2132 } 2133 2134 tdata = node->data; 2135 if (node->is_classed && tdata->class.class) 2136 { 2137 if (CLASSED_NODE_N_IFACES (node)) 2138 type_data_finalize_class_ifaces_Wm (node); 2139 node->mutatable_check_cache = FALSE; 2140 node->data = NULL; 2141 G_WRITE_UNLOCK (&type_rw_lock); 2142 type_data_finalize_class_U (node, &tdata->class); 2143 G_WRITE_LOCK (&type_rw_lock); 2144 } 2145 else if (NODE_IS_IFACE (node) && tdata->iface.dflt_vtable) 2146 { 2147 node->mutatable_check_cache = FALSE; 2148 node->data = NULL; 2149 if (tdata->iface.dflt_finalize || tdata->iface.vtable_finalize_base) 2150 { 2151 G_WRITE_UNLOCK (&type_rw_lock); 2152 if (tdata->iface.dflt_finalize) 2153 tdata->iface.dflt_finalize (tdata->iface.dflt_vtable, (gpointer) tdata->iface.dflt_data); 2154 if (tdata->iface.vtable_finalize_base) 2155 tdata->iface.vtable_finalize_base (tdata->iface.dflt_vtable); 2156 G_WRITE_LOCK (&type_rw_lock); 2157 } 2158 g_free (tdata->iface.dflt_vtable); 2159 } 2160 else 2161 { 2162 node->mutatable_check_cache = FALSE; 2163 node->data = NULL; 2164 } 2165 2166 /* freeing tdata->common.value_table and its contents is taken care of 2167 * by allocating it in one chunk with tdata 2168 */ 2169 g_free (tdata); 2170 2171 G_WRITE_UNLOCK (&type_rw_lock); 2172 g_type_plugin_unuse (node->plugin); 2173 G_WRITE_LOCK (&type_rw_lock); 2174 if (ptype) 2175 type_data_unref_WmREC (lookup_type_node_I (ptype), FALSE); 2176 } 2177} 2178 2179/** 2180 * g_type_add_class_cache_func: 2181 * @cache_data: data to be passed to @cache_func 2182 * @cache_func: a #GTypeClassCacheFunc 2183 * 2184 * Adds a #GTypeClassCacheFunc to be called before the reference count of a 2185 * class goes from one to zero. This can be used to prevent premature class 2186 * destruction. All installed #GTypeClassCacheFunc functions will be chained 2187 * until one of them returns %TRUE. The functions have to check the class id 2188 * passed in to figure whether they actually want to cache the class of this 2189 * type, since all classes are routed through the same #GTypeClassCacheFunc 2190 * chain. 2191 */ 2192void 2193g_type_add_class_cache_func (gpointer cache_data, 2194 GTypeClassCacheFunc cache_func) 2195{ 2196 guint i; 2197 2198 g_return_if_fail (cache_func != NULL); 2199 2200 G_WRITE_LOCK (&type_rw_lock); 2201 i = static_n_class_cache_funcs++; 2202 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs); 2203 static_class_cache_funcs[i].cache_data = cache_data; 2204 static_class_cache_funcs[i].cache_func = cache_func; 2205 G_WRITE_UNLOCK (&type_rw_lock); 2206} 2207 2208/** 2209 * g_type_remove_class_cache_func: 2210 * @cache_data: data that was given when adding @cache_func 2211 * @cache_func: a #GTypeClassCacheFunc 2212 * 2213 * Removes a previously installed #GTypeClassCacheFunc. The cache 2214 * maintained by @cache_func has to be empty when calling 2215 * g_type_remove_class_cache_func() to avoid leaks. 2216 */ 2217void 2218g_type_remove_class_cache_func (gpointer cache_data, 2219 GTypeClassCacheFunc cache_func) 2220{ 2221 gboolean found_it = FALSE; 2222 guint i; 2223 2224 g_return_if_fail (cache_func != NULL); 2225 2226 G_WRITE_LOCK (&type_rw_lock); 2227 for (i = 0; i < static_n_class_cache_funcs; i++) 2228 if (static_class_cache_funcs[i].cache_data == cache_data && 2229 static_class_cache_funcs[i].cache_func == cache_func) 2230 { 2231 static_n_class_cache_funcs--; 2232 g_memmove (static_class_cache_funcs + i, 2233 static_class_cache_funcs + i + 1, 2234 sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i)); 2235 static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs); 2236 found_it = TRUE; 2237 break; 2238 } 2239 G_WRITE_UNLOCK (&type_rw_lock); 2240 2241 if (!found_it) 2242 g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p", 2243 cache_func, cache_data); 2244} 2245 2246 2247/** 2248 * g_type_add_interface_check: 2249 * @check_data: data to pass to @check_func 2250 * @check_func: function to be called after each interface 2251 * is initialized. 2252 * 2253 * Adds a function to be called after an interface vtable is 2254 * initialized for any class (i.e. after the @interface_init member of 2255 * #GInterfaceInfo has been called). 2256 * 2257 * This function is useful when you want to check an invariant that 2258 * depends on the interfaces of a class. For instance, the 2259 * implementation of #GObject uses this facility to check that an 2260 * object implements all of the properties that are defined on its 2261 * interfaces. 2262 * 2263 * Since: 2.4 2264 */ 2265void 2266g_type_add_interface_check (gpointer check_data, 2267 GTypeInterfaceCheckFunc check_func) 2268{ 2269 guint i; 2270 2271 g_return_if_fail (check_func != NULL); 2272 2273 G_WRITE_LOCK (&type_rw_lock); 2274 i = static_n_iface_check_funcs++; 2275 static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs); 2276 static_iface_check_funcs[i].check_data = check_data; 2277 static_iface_check_funcs[i].check_func = check_func; 2278 G_WRITE_UNLOCK (&type_rw_lock); 2279} 2280 2281/** 2282 * g_type_remove_interface_check: 2283 * @check_data: callback data passed to g_type_add_interface_check() 2284 * @check_func: callback function passed to g_type_add_interface_check() 2285 * 2286 * Removes an interface check function added with 2287 * g_type_add_interface_check(). 2288 * 2289 * Since: 2.4 2290 */ 2291void 2292g_type_remove_interface_check (gpointer check_data, 2293 GTypeInterfaceCheckFunc check_func) 2294{ 2295 gboolean found_it = FALSE; 2296 guint i; 2297 2298 g_return_if_fail (check_func != NULL); 2299 2300 G_WRITE_LOCK (&type_rw_lock); 2301 for (i = 0; i < static_n_iface_check_funcs; i++) 2302 if (static_iface_check_funcs[i].check_data == check_data && 2303 static_iface_check_funcs[i].check_func == check_func) 2304 { 2305 static_n_iface_check_funcs--; 2306 g_memmove (static_iface_check_funcs + i, 2307 static_iface_check_funcs + i + 1, 2308 sizeof (static_iface_check_funcs[0]) * (static_n_iface_check_funcs - i)); 2309 static_iface_check_funcs = g_renew (IFaceCheckFunc, static_iface_check_funcs, static_n_iface_check_funcs); 2310 found_it = TRUE; 2311 break; 2312 } 2313 G_WRITE_UNLOCK (&type_rw_lock); 2314 2315 if (!found_it) 2316 g_warning (G_STRLOC ": cannot remove unregistered class check func %p with data %p", 2317 check_func, check_data); 2318} 2319 2320/* --- type registration --- */ 2321/** 2322 * g_type_register_fundamental: 2323 * @type_id: A predefined type identifier. 2324 * @type_name: 0-terminated string used as the name of the new type. 2325 * @info: The #GTypeInfo structure for this type. 2326 * @finfo: The #GTypeFundamentalInfo structure for this type. 2327 * @flags: Bitwise combination of #GTypeFlags values. 2328 * 2329 * Registers @type_id as the predefined identifier and @type_name as the 2330 * name of a fundamental type. The type system uses the information 2331 * contained in the #GTypeInfo structure pointed to by @info and the 2332 * #GTypeFundamentalInfo structure pointed to by @finfo to manage the 2333 * type and its instances. The value of @flags determines additional 2334 * characteristics of the fundamental type. 2335 * 2336 * Returns: The predefined type identifier. 2337 */ 2338GType 2339g_type_register_fundamental (GType type_id, 2340 const gchar *type_name, 2341 const GTypeInfo *info, 2342 const GTypeFundamentalInfo *finfo, 2343 GTypeFlags flags) 2344{ 2345 TypeNode *node; 2346 2347 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0); 2348 g_return_val_if_fail (type_id > 0, 0); 2349 g_return_val_if_fail (type_name != NULL, 0); 2350 g_return_val_if_fail (info != NULL, 0); 2351 g_return_val_if_fail (finfo != NULL, 0); 2352 2353 if (!check_type_name_I (type_name)) 2354 return 0; 2355 if ((type_id & TYPE_ID_MASK) || 2356 type_id > G_TYPE_FUNDAMENTAL_MAX) 2357 { 2358 g_warning ("attempt to register fundamental type `%s' with invalid type id (%" G_GSIZE_FORMAT ")", 2359 type_name, 2360 type_id); 2361 return 0; 2362 } 2363 if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) && 2364 !(finfo->type_flags & G_TYPE_FLAG_CLASSED)) 2365 { 2366 g_warning ("cannot register instantiatable fundamental type `%s' as non-classed", 2367 type_name); 2368 return 0; 2369 } 2370 if (lookup_type_node_I (type_id)) 2371 { 2372 g_warning ("cannot register existing fundamental type `%s' (as `%s')", 2373 type_descriptive_name_I (type_id), 2374 type_name); 2375 return 0; 2376 } 2377 2378 G_WRITE_LOCK (&type_rw_lock); 2379 node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags); 2380 type_add_flags_W (node, flags); 2381 2382 if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info)) 2383 type_data_make_W (node, info, 2384 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL); 2385 G_WRITE_UNLOCK (&type_rw_lock); 2386 2387 return NODE_TYPE (node); 2388} 2389 2390/** 2391 * g_type_register_static_simple: 2392 * @parent_type: Type from which this type will be derived. 2393 * @type_name: 0-terminated string used as the name of the new type. 2394 * @class_size: Size of the class structure (see #GTypeInfo) 2395 * @class_init: Location of the class initialization function (see #GTypeInfo) 2396 * @instance_size: Size of the instance structure (see #GTypeInfo) 2397 * @instance_init: Location of the instance initialization function (see #GTypeInfo) 2398 * @flags: Bitwise combination of #GTypeFlags values. 2399 * 2400 * Registers @type_name as the name of a new static type derived from 2401 * @parent_type. The value of @flags determines the nature (e.g. 2402 * abstract or not) of the type. It works by filling a #GTypeInfo 2403 * struct and calling g_type_register_static(). 2404 * 2405 * Since: 2.12 2406 * 2407 * Returns: The new type identifier. 2408 */ 2409GType 2410g_type_register_static_simple (GType parent_type, 2411 const gchar *type_name, 2412 guint class_size, 2413 GClassInitFunc class_init, 2414 guint instance_size, 2415 GInstanceInitFunc instance_init, 2416 GTypeFlags flags) 2417{ 2418 GTypeInfo info; 2419 2420 info.class_size = class_size; 2421 info.base_init = NULL; 2422 info.base_finalize = NULL; 2423 info.class_init = class_init; 2424 info.class_finalize = NULL; 2425 info.class_data = NULL; 2426 info.instance_size = instance_size; 2427 info.n_preallocs = 0; 2428 info.instance_init = instance_init; 2429 info.value_table = NULL; 2430 2431 return g_type_register_static (parent_type, type_name, &info, flags); 2432} 2433 2434/** 2435 * g_type_register_static: 2436 * @parent_type: Type from which this type will be derived. 2437 * @type_name: 0-terminated string used as the name of the new type. 2438 * @info: The #GTypeInfo structure for this type. 2439 * @flags: Bitwise combination of #GTypeFlags values. 2440 * 2441 * Registers @type_name as the name of a new static type derived from 2442 * @parent_type. The type system uses the information contained in the 2443 * #GTypeInfo structure pointed to by @info to manage the type and its 2444 * instances (if not abstract). The value of @flags determines the nature 2445 * (e.g. abstract or not) of the type. 2446 * 2447 * Returns: The new type identifier. 2448 */ 2449GType 2450g_type_register_static (GType parent_type, 2451 const gchar *type_name, 2452 const GTypeInfo *info, 2453 GTypeFlags flags) 2454{ 2455 TypeNode *pnode, *node; 2456 GType type = 0; 2457 2458 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0); 2459 g_return_val_if_fail (parent_type > 0, 0); 2460 g_return_val_if_fail (type_name != NULL, 0); 2461 g_return_val_if_fail (info != NULL, 0); 2462 2463 if (!check_type_name_I (type_name) || 2464 !check_derivation_I (parent_type, type_name)) 2465 return 0; 2466 if (info->class_finalize) 2467 { 2468 g_warning ("class finalizer specified for static type `%s'", 2469 type_name); 2470 return 0; 2471 } 2472 2473 pnode = lookup_type_node_I (parent_type); 2474 G_WRITE_LOCK (&type_rw_lock); 2475 type_data_ref_Wm (pnode); 2476 if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info)) 2477 { 2478 node = type_node_new_W (pnode, type_name, NULL); 2479 type_add_flags_W (node, flags); 2480 type = NODE_TYPE (node); 2481 type_data_make_W (node, info, 2482 check_value_table_I (type_name, info->value_table) ? info->value_table : NULL); 2483 } 2484 G_WRITE_UNLOCK (&type_rw_lock); 2485 2486 return type; 2487} 2488 2489/** 2490 * g_type_register_dynamic: 2491 * @parent_type: Type from which this type will be derived. 2492 * @type_name: 0-terminated string used as the name of the new type. 2493 * @plugin: The #GTypePlugin structure to retrieve the #GTypeInfo from. 2494 * @flags: Bitwise combination of #GTypeFlags values. 2495 * 2496 * Registers @type_name as the name of a new dynamic type derived from 2497 * @parent_type. The type system uses the information contained in the 2498 * #GTypePlugin structure pointed to by @plugin to manage the type and its 2499 * instances (if not abstract). The value of @flags determines the nature 2500 * (e.g. abstract or not) of the type. 2501 * 2502 * Returns: The new type identifier or #G_TYPE_INVALID if registration failed. 2503 */ 2504GType 2505g_type_register_dynamic (GType parent_type, 2506 const gchar *type_name, 2507 GTypePlugin *plugin, 2508 GTypeFlags flags) 2509{ 2510 TypeNode *pnode, *node; 2511 GType type; 2512 2513 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, 0); 2514 g_return_val_if_fail (parent_type > 0, 0); 2515 g_return_val_if_fail (type_name != NULL, 0); 2516 g_return_val_if_fail (plugin != NULL, 0); 2517 2518 if (!check_type_name_I (type_name) || 2519 !check_derivation_I (parent_type, type_name) || 2520 !check_plugin_U (plugin, TRUE, FALSE, type_name)) 2521 return 0; 2522 2523 G_WRITE_LOCK (&type_rw_lock); 2524 pnode = lookup_type_node_I (parent_type); 2525 node = type_node_new_W (pnode, type_name, plugin); 2526 type_add_flags_W (node, flags); 2527 type = NODE_TYPE (node); 2528 G_WRITE_UNLOCK (&type_rw_lock); 2529 2530 return type; 2531} 2532 2533/** 2534 * g_type_add_interface_static: 2535 * @instance_type: #GType value of an instantiable type. 2536 * @interface_type: #GType value of an interface type. 2537 * @info: The #GInterfaceInfo structure for this 2538 * (@instance_type, @interface_type) combination. 2539 * 2540 * Adds the static @interface_type to @instantiable_type. The information 2541 * contained in the #GTypeInterfaceInfo structure pointed to by @info 2542 * is used to manage the relationship. 2543 */ 2544void 2545g_type_add_interface_static (GType instance_type, 2546 GType interface_type, 2547 const GInterfaceInfo *info) 2548{ 2549 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */ 2550 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type)); 2551 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE); 2552 2553 /* we only need to lock class_init_rec_mutex if instance_type already has its 2554 * class initialized, however this function is rarely enough called to take 2555 * the simple route and always acquire class_init_rec_mutex. 2556 */ 2557 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */ 2558 G_WRITE_LOCK (&type_rw_lock); 2559 if (check_add_interface_L (instance_type, interface_type)) 2560 { 2561 TypeNode *node = lookup_type_node_I (instance_type); 2562 TypeNode *iface = lookup_type_node_I (interface_type); 2563 if (check_interface_info_I (iface, NODE_TYPE (node), info)) 2564 type_add_interface_Wm (node, iface, info, NULL); 2565 } 2566 G_WRITE_UNLOCK (&type_rw_lock); 2567 g_static_rec_mutex_unlock (&class_init_rec_mutex); 2568} 2569 2570/** 2571 * g_type_add_interface_dynamic: 2572 * @instance_type: the #GType value of an instantiable type. 2573 * @interface_type: the #GType value of an interface type. 2574 * @plugin: the #GTypePlugin structure to retrieve the #GInterfaceInfo from. 2575 * 2576 * Adds the dynamic @interface_type to @instantiable_type. The information 2577 * contained in the #GTypePlugin structure pointed to by @plugin 2578 * is used to manage the relationship. 2579 */ 2580void 2581g_type_add_interface_dynamic (GType instance_type, 2582 GType interface_type, 2583 GTypePlugin *plugin) 2584{ 2585 TypeNode *node; 2586 /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */ 2587 g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type)); 2588 g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE); 2589 2590 node = lookup_type_node_I (instance_type); 2591 if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node))) 2592 return; 2593 2594 /* see comment in g_type_add_interface_static() about class_init_rec_mutex */ 2595 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */ 2596 G_WRITE_LOCK (&type_rw_lock); 2597 if (check_add_interface_L (instance_type, interface_type)) 2598 { 2599 TypeNode *iface = lookup_type_node_I (interface_type); 2600 type_add_interface_Wm (node, iface, NULL, plugin); 2601 } 2602 G_WRITE_UNLOCK (&type_rw_lock); 2603 g_static_rec_mutex_unlock (&class_init_rec_mutex); 2604} 2605 2606 2607/* --- public API functions --- */ 2608/** 2609 * g_type_class_ref: 2610 * @type: Type ID of a classed type. 2611 * 2612 * Increments the reference count of the class structure belonging to 2613 * @type. This function will demand-create the class if it doesn't 2614 * exist already. 2615 * 2616 * Returns: The #GTypeClass structure for the given type ID. 2617 */ 2618gpointer 2619g_type_class_ref (GType type) 2620{ 2621 TypeNode *node; 2622 GType ptype; 2623 2624 /* optimize for common code path */ 2625 G_WRITE_LOCK (&type_rw_lock); 2626 node = lookup_type_node_I (type); 2627 if (node && node->is_classed && node->data && 2628 node->data->class.class && 2629 node->data->class.init_state == INITIALIZED) 2630 { 2631 type_data_ref_Wm (node); 2632 G_WRITE_UNLOCK (&type_rw_lock); 2633 return node->data->class.class; 2634 } 2635 if (!node || !node->is_classed || 2636 (node->data && node->data->common.ref_count < 1)) 2637 { 2638 G_WRITE_UNLOCK (&type_rw_lock); 2639 g_warning ("cannot retrieve class for invalid (unclassed) type `%s'", 2640 type_descriptive_name_I (type)); 2641 return NULL; 2642 } 2643 type_data_ref_Wm (node); 2644 ptype = NODE_PARENT_TYPE (node); 2645 G_WRITE_UNLOCK (&type_rw_lock); 2646 2647 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */ 2648 /* here, we either have node->data->class.class == NULL, or a recursive 2649 * call to g_type_class_ref() with a partly initialized class, or 2650 * node->data->class.init_state == INITIALIZED, because any 2651 * concurrently running initialization was guarded by class_init_rec_mutex. 2652 */ 2653 if (!node->data->class.class) /* class uninitialized */ 2654 { 2655 /* acquire reference on parent class */ 2656 GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL; 2657 G_WRITE_LOCK (&type_rw_lock); 2658 if (node->data->class.class) /* class was initialized during parent class initialization? */ 2659 INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node)); 2660 type_class_init_Wm (node, pclass); 2661 G_WRITE_UNLOCK (&type_rw_lock); 2662 } 2663 g_static_rec_mutex_unlock (&class_init_rec_mutex); 2664 2665 return node->data->class.class; 2666} 2667 2668/** 2669 * g_type_class_unref: 2670 * @g_class: The #GTypeClass structure to unreference. 2671 * 2672 * Decrements the reference count of the class structure being passed in. 2673 * Once the last reference count of a class has been released, classes 2674 * may be finalized by the type system, so further dereferencing of a 2675 * class pointer after g_type_class_unref() are invalid. 2676 */ 2677void 2678g_type_class_unref (gpointer g_class) 2679{ 2680 TypeNode *node; 2681 GTypeClass *class = g_class; 2682 2683 g_return_if_fail (g_class != NULL); 2684 2685 node = lookup_type_node_I (class->g_type); 2686 G_WRITE_LOCK (&type_rw_lock); 2687 if (node && node->is_classed && node->data && 2688 node->data->class.class == class && node->data->common.ref_count > 0) 2689 type_data_unref_WmREC (node, FALSE); 2690 else 2691 g_warning ("cannot unreference class of invalid (unclassed) type `%s'", 2692 type_descriptive_name_I (class->g_type)); 2693 G_WRITE_UNLOCK (&type_rw_lock); 2694} 2695 2696/** 2697 * g_type_class_unref_uncached: 2698 * @g_class: The #GTypeClass structure to unreference. 2699 * 2700 * A variant of g_type_class_unref() for use in #GTypeClassCacheFunc 2701 * implementations. It unreferences a class without consulting the chain 2702 * of #GTypeClassCacheFunc<!-- -->s, avoiding the recursion which would occur 2703 * otherwise. 2704 */ 2705void 2706g_type_class_unref_uncached (gpointer g_class) 2707{ 2708 TypeNode *node; 2709 GTypeClass *class = g_class; 2710 2711 g_return_if_fail (g_class != NULL); 2712 2713 G_WRITE_LOCK (&type_rw_lock); 2714 node = lookup_type_node_I (class->g_type); 2715 if (node && node->is_classed && node->data && 2716 node->data->class.class == class && node->data->common.ref_count > 0) 2717 type_data_unref_WmREC (node, TRUE); 2718 else 2719 g_warning ("cannot unreference class of invalid (unclassed) type `%s'", 2720 type_descriptive_name_I (class->g_type)); 2721 G_WRITE_UNLOCK (&type_rw_lock); 2722} 2723 2724/** 2725 * g_type_class_peek: 2726 * @type: Type ID of a classed type. 2727 * 2728 * This function is essentially the same as g_type_class_ref(), except that 2729 * the classes reference count isn't incremented. As a consequence, this function 2730 * may return %NULL if the class of the type passed in does not currently 2731 * exist (hasn't been referenced before). 2732 * 2733 * Returns: The #GTypeClass structure for the given type ID or %NULL 2734 * if the class does not currently exist. 2735 */ 2736gpointer 2737g_type_class_peek (GType type) 2738{ 2739 TypeNode *node; 2740 gpointer class; 2741 2742 node = lookup_type_node_I (type); 2743 G_READ_LOCK (&type_rw_lock); 2744 if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */ 2745 class = node->data->class.class; 2746 else 2747 class = NULL; 2748 G_READ_UNLOCK (&type_rw_lock); 2749 2750 return class; 2751} 2752 2753/** 2754 * g_type_class_peek_static: 2755 * @type: Type ID of a classed type. 2756 * 2757 * A more efficient version of g_type_class_peek() which works only for 2758 * static types. 2759 * 2760 * Since: 2.4 2761 * Returns: The #GTypeClass structure for the given type ID or %NULL 2762 * if the class does not currently exist or is dynamically loaded. 2763 */ 2764gpointer 2765g_type_class_peek_static (GType type) 2766{ 2767 TypeNode *node; 2768 gpointer class; 2769 2770 node = lookup_type_node_I (type); 2771 G_READ_LOCK (&type_rw_lock); 2772 if (node && node->is_classed && node->data && 2773 /* peek only static types: */ node->plugin == NULL && 2774 node->data->class.class) /* common.ref_count _may_ be 0 */ 2775 class = node->data->class.class; 2776 else 2777 class = NULL; 2778 G_READ_UNLOCK (&type_rw_lock); 2779 2780 return class; 2781} 2782 2783/** 2784 * g_type_class_peek_parent: 2785 * @g_class: The #GTypeClass structure to retrieve the parent class for. 2786 * 2787 * This is a convenience function often needed in class initializers. 2788 * It returns the class structure of the immediate parent type of the 2789 * class passed in. Since derived classes hold a reference count on 2790 * their parent classes as long as they are instantiated, the returned 2791 * class will always exist. This function is essentially equivalent 2792 * to: 2793 * 2794 * <programlisting> 2795 * g_type_class_peek (g_type_parent (G_TYPE_FROM_CLASS (g_class))); 2796 * </programlisting> 2797 * 2798 * Returns: The parent class of @g_class. 2799 */ 2800gpointer 2801g_type_class_peek_parent (gpointer g_class) 2802{ 2803 TypeNode *node; 2804 gpointer class = NULL; 2805 2806 g_return_val_if_fail (g_class != NULL, NULL); 2807 2808 node = lookup_type_node_I (G_TYPE_FROM_CLASS (g_class)); 2809 /* We used to acquire a read lock here. That is not necessary, since 2810 * parent->data->class.class is constant as long as the derived class 2811 * exists. 2812 */ 2813 if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node)) 2814 { 2815 node = lookup_type_node_I (NODE_PARENT_TYPE (node)); 2816 class = node->data->class.class; 2817 } 2818 else if (NODE_PARENT_TYPE (node)) 2819 g_warning (G_STRLOC ": invalid class pointer `%p'", g_class); 2820 2821 return class; 2822} 2823 2824/** 2825 * g_type_interface_peek: 2826 * @instance_class: A #GTypeClass structure. 2827 * @iface_type: An interface ID which this class conforms to. 2828 * 2829 * Returns the #GTypeInterface structure of an interface to which the 2830 * passed in class conforms. 2831 * 2832 * Returns: The GTypeInterface structure of iface_type if implemented 2833 * by @instance_class, %NULL otherwise 2834 */ 2835gpointer 2836g_type_interface_peek (gpointer instance_class, 2837 GType iface_type) 2838{ 2839 TypeNode *node; 2840 TypeNode *iface; 2841 gpointer vtable = NULL; 2842 GTypeClass *class = instance_class; 2843 2844 g_return_val_if_fail (instance_class != NULL, NULL); 2845 2846 node = lookup_type_node_I (class->g_type); 2847 iface = lookup_type_node_I (iface_type); 2848 if (node && node->is_instantiatable && iface) 2849 { 2850 IFaceEntry *entry; 2851 2852 G_READ_LOCK (&type_rw_lock); 2853 2854 entry = type_lookup_iface_entry_L (node, iface); 2855 if (entry && entry->vtable) /* entry is relocatable */ 2856 vtable = entry->vtable; 2857 2858 G_READ_UNLOCK (&type_rw_lock); 2859 } 2860 else 2861 g_warning (G_STRLOC ": invalid class pointer `%p'", class); 2862 2863 return vtable; 2864} 2865 2866/** 2867 * g_type_interface_peek_parent: 2868 * @g_iface: A #GTypeInterface structure. 2869 * 2870 * Returns the corresponding #GTypeInterface structure of the parent type 2871 * of the instance type to which @g_iface belongs. This is useful when 2872 * deriving the implementation of an interface from the parent type and 2873 * then possibly overriding some methods. 2874 * 2875 * Returns: The corresponding #GTypeInterface structure of the parent 2876 * type of the instance type to which @g_iface belongs, or 2877 * %NULL if the parent type doesn't conform to the interface. 2878 */ 2879gpointer 2880g_type_interface_peek_parent (gpointer g_iface) 2881{ 2882 TypeNode *node; 2883 TypeNode *iface; 2884 gpointer vtable = NULL; 2885 GTypeInterface *iface_class = g_iface; 2886 2887 g_return_val_if_fail (g_iface != NULL, NULL); 2888 2889 iface = lookup_type_node_I (iface_class->g_type); 2890 node = lookup_type_node_I (iface_class->g_instance_type); 2891 if (node) 2892 node = lookup_type_node_I (NODE_PARENT_TYPE (node)); 2893 if (node && node->is_instantiatable && iface) 2894 { 2895 IFaceEntry *entry; 2896 2897 G_READ_LOCK (&type_rw_lock); 2898 2899 entry = type_lookup_iface_entry_L (node, iface); 2900 if (entry && entry->vtable) /* entry is relocatable */ 2901 vtable = entry->vtable; 2902 2903 G_READ_UNLOCK (&type_rw_lock); 2904 } 2905 else if (node) 2906 g_warning (G_STRLOC ": invalid interface pointer `%p'", g_iface); 2907 2908 return vtable; 2909} 2910 2911/** 2912 * g_type_default_interface_ref: 2913 * @g_type: an interface type 2914 * 2915 * Increments the reference count for the interface type @g_type, 2916 * and returns the default interface vtable for the type. 2917 * 2918 * If the type is not currently in use, then the default vtable 2919 * for the type will be created and initalized by calling 2920 * the base interface init and default vtable init functions for 2921 * the type (the @<structfield>base_init</structfield> 2922 * and <structfield>class_init</structfield> members of #GTypeInfo). 2923 * Calling g_type_default_interface_ref() is useful when you 2924 * want to make sure that signals and properties for an interface 2925 * have been installed. 2926 * 2927 * Since: 2.4 2928 * 2929 * Returns: the default vtable for the interface; call 2930 * g_type_default_interface_unref() when you are done using 2931 * the interface. 2932 */ 2933gpointer 2934g_type_default_interface_ref (GType g_type) 2935{ 2936 TypeNode *node; 2937 gpointer dflt_vtable; 2938 2939 G_WRITE_LOCK (&type_rw_lock); 2940 2941 node = lookup_type_node_I (g_type); 2942 if (!node || !NODE_IS_IFACE (node) || 2943 (node->data && node->data->common.ref_count < 1)) 2944 { 2945 G_WRITE_UNLOCK (&type_rw_lock); 2946 g_warning ("cannot retrieve default vtable for invalid or non-interface type '%s'", 2947 type_descriptive_name_I (g_type)); 2948 return NULL; 2949 } 2950 2951 if (!node->data || !node->data->iface.dflt_vtable) 2952 { 2953 G_WRITE_UNLOCK (&type_rw_lock); 2954 g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */ 2955 G_WRITE_LOCK (&type_rw_lock); 2956 node = lookup_type_node_I (g_type); 2957 type_data_ref_Wm (node); 2958 type_iface_ensure_dflt_vtable_Wm (node); 2959 g_static_rec_mutex_unlock (&class_init_rec_mutex); 2960 } 2961 else 2962 type_data_ref_Wm (node); /* ref_count >= 1 already */ 2963 2964 dflt_vtable = node->data->iface.dflt_vtable; 2965 G_WRITE_UNLOCK (&type_rw_lock); 2966 2967 return dflt_vtable; 2968} 2969 2970/** 2971 * g_type_default_interface_peek: 2972 * @g_type: an interface type 2973 * 2974 * If the interface type @g_type is currently in use, returns its 2975 * default interface vtable. 2976 * 2977 * Since: 2.4 2978 * 2979 * Returns: the default vtable for the interface, or %NULL 2980 * if the type is not currently in use. 2981 */ 2982gpointer 2983g_type_default_interface_peek (GType g_type) 2984{ 2985 TypeNode *node; 2986 gpointer vtable; 2987 2988 node = lookup_type_node_I (g_type); 2989 G_READ_LOCK (&type_rw_lock); 2990 if (node && NODE_IS_IFACE (node) && node->data && node->data->iface.dflt_vtable) 2991 vtable = node->data->iface.dflt_vtable; 2992 else 2993 vtable = NULL; 2994 G_READ_UNLOCK (&type_rw_lock); 2995 2996 return vtable; 2997} 2998 2999/** 3000 * g_type_default_interface_unref: 3001 * @g_iface: the default vtable structure for a interface, as 3002 * returned by g_type_default_interface_ref() 3003 * 3004 * Decrements the reference count for the type corresponding to the 3005 * interface default vtable @g_iface. If the type is dynamic, then 3006 * when no one is using the interface and all references have 3007 * been released, the finalize function for the interface's default 3008 * vtable (the <structfield>class_finalize</structfield> member of 3009 * #GTypeInfo) will be called. 3010 * 3011 * Since: 2.4 3012 */ 3013void 3014g_type_default_interface_unref (gpointer g_iface) 3015{ 3016 TypeNode *node; 3017 GTypeInterface *vtable = g_iface; 3018 3019 g_return_if_fail (g_iface != NULL); 3020 3021 node = lookup_type_node_I (vtable->g_type); 3022 G_WRITE_LOCK (&type_rw_lock); 3023 if (node && NODE_IS_IFACE (node) && 3024 node->data->iface.dflt_vtable == g_iface && 3025 node->data->common.ref_count > 0) 3026 type_data_unref_WmREC (node, FALSE); 3027 else 3028 g_warning ("cannot unreference invalid interface default vtable for '%s'", 3029 type_descriptive_name_I (vtable->g_type)); 3030 G_WRITE_UNLOCK (&type_rw_lock); 3031} 3032 3033/** 3034 * g_type_name: 3035 * @type: Type to return name for. 3036 * 3037 * Get the unique name that is assigned to a type ID. Note that this 3038 * function (like all other GType API) cannot cope with invalid type 3039 * IDs. %G_TYPE_INVALID may be passed to this function, as may be any 3040 * other validly registered type ID, but randomized type IDs should 3041 * not be passed in and will most likely lead to a crash. 3042 * 3043 * Returns: Static type name or %NULL. 3044 */ 3045G_CONST_RETURN gchar* 3046g_type_name (GType type) 3047{ 3048 TypeNode *node; 3049 3050 g_return_val_if_uninitialized (static_quark_type_flags, g_type_init, NULL); 3051 3052 node = lookup_type_node_I (type); 3053 3054 return node ? NODE_NAME (node) : NULL; 3055} 3056 3057/** 3058 * g_type_qname: 3059 * @type: Type to return quark of type name for. 3060 * 3061 * Get the corresponding quark of the type IDs name. 3062 * 3063 * Returns: The type names quark or 0. 3064 */ 3065GQuark 3066g_type_qname (GType type) 3067{ 3068 TypeNode *node; 3069 3070 node = lookup_type_node_I (type); 3071 3072 return node ? node->qname : 0; 3073} 3074 3075/** 3076 * g_type_from_name: 3077 * @name: Type name to lookup. 3078 * 3079 * Lookup the type ID from a given type name, returning 0 if no type 3080 * has been registered under this name (this is the preferred method 3081 * to find out by name whether a specific type has been registered 3082 * yet). 3083 * 3084 * Returns: Corresponding type ID or 0. 3085 */ 3086GType 3087g_type_from_name (const gchar *name) 3088{ 3089 GType type = 0; 3090 GQuark quark; 3091 3092 g_return_val_if_fail (name != NULL, 0); 3093 3094 quark = g_quark_try_string (name); 3095 if (quark) 3096 { 3097 G_READ_LOCK (&type_rw_lock); 3098 type = (GType) g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark)); 3099 G_READ_UNLOCK (&type_rw_lock); 3100 } 3101 3102 return type; 3103} 3104 3105/** 3106 * g_type_parent: 3107 * @type: The derived type. 3108 * 3109 * Return the direct parent type of the passed in type. If the passed 3110 * in type has no parent, i.e. is a fundamental type, 0 is returned. 3111 * 3112 * Returns: The parent type. 3113 */ 3114GType 3115g_type_parent (GType type) 3116{ 3117 TypeNode *node; 3118 3119 node = lookup_type_node_I (type); 3120 3121 return node ? NODE_PARENT_TYPE (node) : 0; 3122} 3123 3124/** 3125 * g_type_depth: 3126 * @type: A #GType value. 3127 * 3128 * Returns the length of the ancestry of the passed in type. This 3129 * includes the type itself, so that e.g. a fundamental type has depth 1. 3130 * 3131 * Returns: The depth of @type. 3132 */ 3133guint 3134g_type_depth (GType type) 3135{ 3136 TypeNode *node; 3137 3138 node = lookup_type_node_I (type); 3139 3140 return node ? node->n_supers + 1 : 0; 3141} 3142 3143/** 3144 * g_type_next_base: 3145 * @leaf_type: Descendant of @root_type and the type to be returned. 3146 * @root_type: Immediate parent of the returned type. 3147 * 3148 * Given a @leaf_type and a @root_type which is contained in its 3149 * anchestry, return the type that @root_type is the immediate parent 3150 * of. In other words, this function determines the type that is 3151 * derived directly from @root_type which is also a base class of 3152 * @leaf_type. Given a root type and a leaf type, this function can 3153 * be used to determine the types and order in which the leaf type is 3154 * descended from the root type. 3155 * 3156 * Returns: Immediate child of @root_type and anchestor of @leaf_type. 3157 */ 3158GType 3159g_type_next_base (GType type, 3160 GType base_type) 3161{ 3162 GType atype = 0; 3163 TypeNode *node; 3164 3165 node = lookup_type_node_I (type); 3166 if (node) 3167 { 3168 TypeNode *base_node = lookup_type_node_I (base_type); 3169 3170 if (base_node && base_node->n_supers < node->n_supers) 3171 { 3172 guint n = node->n_supers - base_node->n_supers; 3173 3174 if (node->supers[n] == base_type) 3175 atype = node->supers[n - 1]; 3176 } 3177 } 3178 3179 return atype; 3180} 3181 3182static inline gboolean 3183type_node_check_conformities_UorL (TypeNode *node, 3184 TypeNode *iface_node, 3185 /* support_inheritance */ 3186 gboolean support_interfaces, 3187 gboolean support_prerequisites, 3188 gboolean have_lock) 3189{ 3190 gboolean match; 3191 3192 if (/* support_inheritance && */ 3193 NODE_IS_ANCESTOR (iface_node, node)) 3194 return TRUE; 3195 3196 support_interfaces = support_interfaces && node->is_instantiatable && NODE_IS_IFACE (iface_node); 3197 support_prerequisites = support_prerequisites && NODE_IS_IFACE (node); 3198 match = FALSE; 3199 if (support_interfaces || support_prerequisites) 3200 { 3201 if (!have_lock) 3202 G_READ_LOCK (&type_rw_lock); 3203 if (support_interfaces && type_lookup_iface_entry_L (node, iface_node)) 3204 match = TRUE; 3205 else if (support_prerequisites && type_lookup_prerequisite_L (node, NODE_TYPE (iface_node))) 3206 match = TRUE; 3207 if (!have_lock) 3208 G_READ_UNLOCK (&type_rw_lock); 3209 } 3210 return match; 3211} 3212 3213static gboolean 3214type_node_is_a_L (TypeNode *node, 3215 TypeNode *iface_node) 3216{ 3217 return type_node_check_conformities_UorL (node, iface_node, TRUE, TRUE, TRUE); 3218} 3219 3220static inline gboolean 3221type_node_conforms_to_U (TypeNode *node, 3222 TypeNode *iface_node, 3223 gboolean support_interfaces, 3224 gboolean support_prerequisites) 3225{ 3226 return type_node_check_conformities_UorL (node, iface_node, support_interfaces, support_prerequisites, FALSE); 3227} 3228 3229/** 3230 * g_type_is_a: 3231 * @type: Type to check anchestry for. 3232 * @is_a_type: Possible anchestor of @type or interface @type could conform to. 3233 * 3234 * If @is_a_type is a derivable type, check whether @type is a 3235 * descendant of @is_a_type. If @is_a_type is an interface, check 3236 * whether @type conforms to it. 3237 * 3238 * Returns: %TRUE if @type is_a @is_a_type holds true. 3239 */ 3240gboolean 3241g_type_is_a (GType type, 3242 GType iface_type) 3243{ 3244 TypeNode *node, *iface_node; 3245 gboolean is_a; 3246 3247 node = lookup_type_node_I (type); 3248 iface_node = lookup_type_node_I (iface_type); 3249 is_a = node && iface_node && type_node_conforms_to_U (node, iface_node, TRUE, TRUE); 3250 3251 return is_a; 3252} 3253 3254/** 3255 * g_type_children: 3256 * @type: The parent type. 3257 * @n_children: Optional #guint pointer to contain the number of child types. 3258 * 3259 * Return a newly allocated and 0-terminated array of type IDs, listing the 3260 * child types of @type. The return value has to be g_free()ed after use. 3261 * 3262 * Returns: Newly allocated and 0-terminated array of child types. 3263 */ 3264GType* 3265g_type_children (GType type, 3266 guint *n_children) 3267{ 3268 TypeNode *node; 3269 3270 node = lookup_type_node_I (type); 3271 if (node) 3272 { 3273 GType *children; 3274 3275 G_READ_LOCK (&type_rw_lock); /* ->children is relocatable */ 3276 children = g_new (GType, node->n_children + 1); 3277 memcpy (children, node->children, sizeof (GType) * node->n_children); 3278 children[node->n_children] = 0; 3279 3280 if (n_children) 3281 *n_children = node->n_children; 3282 G_READ_UNLOCK (&type_rw_lock); 3283 3284 return children; 3285 } 3286 else 3287 { 3288 if (n_children) 3289 *n_children = 0; 3290 3291 return NULL; 3292 } 3293} 3294 3295/** 3296 * g_type_interfaces: 3297 * @type: The type to list interface types for. 3298 * @n_interfaces: Optional #guint pointer to contain the number of 3299 * interface types. 3300 * 3301 * Return a newly allocated and 0-terminated array of type IDs, listing the 3302 * interface types that @type conforms to. The return value has to be 3303 * g_free()ed after use. 3304 * 3305 * Returns: Newly allocated and 0-terminated array of interface types. 3306 */ 3307GType* 3308g_type_interfaces (GType type, 3309 guint *n_interfaces) 3310{ 3311 TypeNode *node; 3312 3313 node = lookup_type_node_I (type); 3314 if (node && node->is_instantiatable) 3315 { 3316 GType *ifaces; 3317 guint i; 3318 3319 G_READ_LOCK (&type_rw_lock); 3320 ifaces = g_new (GType, CLASSED_NODE_N_IFACES (node) + 1); 3321 for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++) 3322 ifaces[i] = CLASSED_NODE_IFACES_ENTRIES (node)[i].iface_type; 3323 ifaces[i] = 0; 3324 3325 if (n_interfaces) 3326 *n_interfaces = CLASSED_NODE_N_IFACES (node); 3327 G_READ_UNLOCK (&type_rw_lock); 3328 3329 return ifaces; 3330 } 3331 else 3332 { 3333 if (n_interfaces) 3334 *n_interfaces = 0; 3335 3336 return NULL; 3337 } 3338} 3339 3340typedef struct _QData QData; 3341struct _GData 3342{ 3343 guint n_qdatas; 3344 QData *qdatas; 3345}; 3346struct _QData 3347{ 3348 GQuark quark; 3349 gpointer data; 3350}; 3351 3352static inline gpointer 3353type_get_qdata_L (TypeNode *node, 3354 GQuark quark) 3355{ 3356 GData *gdata = node->global_gdata; 3357 3358 if (quark && gdata && gdata->n_qdatas) 3359 { 3360 QData *qdatas = gdata->qdatas - 1; 3361 guint n_qdatas = gdata->n_qdatas; 3362 3363 do 3364 { 3365 guint i; 3366 QData *check; 3367 3368 i = (n_qdatas + 1) / 2; 3369 check = qdatas + i; 3370 if (quark == check->quark) 3371 return check->data; 3372 else if (quark > check->quark) 3373 { 3374 n_qdatas -= i; 3375 qdatas = check; 3376 } 3377 else /* if (quark < check->quark) */ 3378 n_qdatas = i - 1; 3379 } 3380 while (n_qdatas); 3381 } 3382 return NULL; 3383} 3384 3385/** 3386 * g_type_get_qdata: 3387 * @type: a #GType 3388 * @quark: a #GQuark id to identify the data 3389 * 3390 * Obtains data which has previously been attached to @type 3391 * with g_type_set_qdata(). 3392 * 3393 * Returns: the data, or %NULL if no data was found 3394 */ 3395gpointer 3396g_type_get_qdata (GType type, 3397 GQuark quark) 3398{ 3399 TypeNode *node; 3400 gpointer data; 3401 3402 node = lookup_type_node_I (type); 3403 if (node) 3404 { 3405 G_READ_LOCK (&type_rw_lock); 3406 data = type_get_qdata_L (node, quark); 3407 G_READ_UNLOCK (&type_rw_lock); 3408 } 3409 else 3410 { 3411 g_return_val_if_fail (node != NULL, NULL); 3412 data = NULL; 3413 } 3414 return data; 3415} 3416 3417static inline void 3418type_set_qdata_W (TypeNode *node, 3419 GQuark quark, 3420 gpointer data) 3421{ 3422 GData *gdata; 3423 QData *qdata; 3424 guint i; 3425 3426 /* setup qdata list if necessary */ 3427 if (!node->global_gdata) 3428 node->global_gdata = g_new0 (GData, 1); 3429 gdata = node->global_gdata; 3430 3431 /* try resetting old data */ 3432 qdata = gdata->qdatas; 3433 for (i = 0; i < gdata->n_qdatas; i++) 3434 if (qdata[i].quark == quark) 3435 { 3436 qdata[i].data = data; 3437 return; 3438 } 3439 3440 /* add new entry */ 3441 gdata->n_qdatas++; 3442 gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas); 3443 qdata = gdata->qdatas; 3444 for (i = 0; i < gdata->n_qdatas - 1; i++) 3445 if (qdata[i].quark > quark) 3446 break; 3447 g_memmove (qdata + i + 1, qdata + i, sizeof (qdata[0]) * (gdata->n_qdatas - i - 1)); 3448 qdata[i].quark = quark; 3449 qdata[i].data = data; 3450} 3451 3452/** 3453 * g_type_set_qdata: 3454 * @type: a #GType 3455 * @quark: a #GQuark id to identify the data 3456 * @data: the data 3457 * 3458 * Attaches arbitrary data to a type. 3459 */ 3460void 3461g_type_set_qdata (GType type, 3462 GQuark quark, 3463 gpointer data) 3464{ 3465 TypeNode *node; 3466 3467 g_return_if_fail (quark != 0); 3468 3469 node = lookup_type_node_I (type); 3470 if (node) 3471 { 3472 G_WRITE_LOCK (&type_rw_lock); 3473 type_set_qdata_W (node, quark, data); 3474 G_WRITE_UNLOCK (&type_rw_lock); 3475 } 3476 else 3477 g_return_if_fail (node != NULL); 3478} 3479 3480static void 3481type_add_flags_W (TypeNode *node, 3482 GTypeFlags flags) 3483{ 3484 guint dflags; 3485 3486 g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0); 3487 g_return_if_fail (node != NULL); 3488 3489 if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data->class.class) 3490 g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node)); 3491 dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)); 3492 dflags |= flags; 3493 type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags)); 3494} 3495 3496/** 3497 * g_type_query: 3498 * @type: the #GType value of a static, classed type. 3499 * @query: A user provided structure that is filled in with constant values 3500 * upon success. 3501 * 3502 * Queries the type system for information about a specific type. 3503 * This function will fill in a user-provided structure to hold 3504 * type-specific information. If an invalid #GType is passed in, the 3505 * @type member of the #GTypeQuery is 0. All members filled into the 3506 * #GTypeQuery structure should be considered constant and have to be 3507 * left untouched. 3508 */ 3509void 3510g_type_query (GType type, 3511 GTypeQuery *query) 3512{ 3513 TypeNode *node; 3514 3515 g_return_if_fail (query != NULL); 3516 3517 /* if node is not static and classed, we won't allow query */ 3518 query->type = 0; 3519 node = lookup_type_node_I (type); 3520 if (node && node->is_classed && !node->plugin) 3521 { 3522 /* type is classed and probably even instantiatable */ 3523 G_READ_LOCK (&type_rw_lock); 3524 if (node->data) /* type is static or referenced */ 3525 { 3526 query->type = NODE_TYPE (node); 3527 query->type_name = NODE_NAME (node); 3528 query->class_size = node->data->class.class_size; 3529 query->instance_size = node->is_instantiatable ? node->data->instance.instance_size : 0; 3530 } 3531 G_READ_UNLOCK (&type_rw_lock); 3532 } 3533} 3534 3535 3536/* --- implementation details --- */ 3537gboolean 3538g_type_test_flags (GType type, 3539 guint flags) 3540{ 3541 TypeNode *node; 3542 gboolean result = FALSE; 3543 3544 node = lookup_type_node_I (type); 3545 if (node) 3546 { 3547 guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK; 3548 guint tflags = flags & TYPE_FLAG_MASK; 3549 3550 if (fflags) 3551 { 3552 GTypeFundamentalInfo *finfo = type_node_fundamental_info_I (node); 3553 3554 fflags = (finfo->type_flags & fflags) == fflags; 3555 } 3556 else 3557 fflags = TRUE; 3558 3559 if (tflags) 3560 { 3561 G_READ_LOCK (&type_rw_lock); 3562 tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags; 3563 G_READ_UNLOCK (&type_rw_lock); 3564 } 3565 else 3566 tflags = TRUE; 3567 3568 result = tflags && fflags; 3569 } 3570 3571 return result; 3572} 3573 3574/** 3575 * g_type_get_plugin: 3576 * @type: The #GType to retrieve the plugin for. 3577 * 3578 * Returns the #GTypePlugin structure for @type or 3579 * %NULL if @type does not have a #GTypePlugin structure. 3580 * 3581 * Returns: The corresponding plugin if @type is a dynamic type, 3582 * %NULL otherwise. 3583 */ 3584GTypePlugin* 3585g_type_get_plugin (GType type) 3586{ 3587 TypeNode *node; 3588 3589 node = lookup_type_node_I (type); 3590 3591 return node ? node->plugin : NULL; 3592} 3593 3594/** 3595 * g_type_interface_get_plugin: 3596 * @instance_type: the #GType value of an instantiatable type. 3597 * @interface_type: the #GType value of an interface type. 3598 * 3599 * Returns the #GTypePlugin structure for the dynamic interface 3600 * @interface_type which has been added to @instance_type, or %NULL if 3601 * @interface_type has not been added to @instance_type or does not 3602 * have a #GTypePlugin structure. See g_type_add_interface_dynamic(). 3603 * 3604 * Returns: the #GTypePlugin for the dynamic interface @interface_type 3605 * of @instance_type. 3606 */ 3607GTypePlugin* 3608g_type_interface_get_plugin (GType instance_type, 3609 GType interface_type) 3610{ 3611 TypeNode *node; 3612 TypeNode *iface; 3613 3614 g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL); /* G_TYPE_IS_INTERFACE() is an external call: _U */ 3615 3616 node = lookup_type_node_I (instance_type); 3617 iface = lookup_type_node_I (interface_type); 3618 if (node && iface) 3619 { 3620 IFaceHolder *iholder; 3621 GTypePlugin *plugin; 3622 3623 G_READ_LOCK (&type_rw_lock); 3624 3625 iholder = iface_node_get_holders_L (iface); 3626 while (iholder && iholder->instance_type != instance_type) 3627 iholder = iholder->next; 3628 plugin = iholder ? iholder->plugin : NULL; 3629 3630 G_READ_UNLOCK (&type_rw_lock); 3631 3632 return plugin; 3633 } 3634 3635 g_return_val_if_fail (node == NULL, NULL); 3636 g_return_val_if_fail (iface == NULL, NULL); 3637 3638 g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair."); 3639 3640 return NULL; 3641} 3642 3643/** 3644 * g_type_fundamental_next: 3645 * 3646 * Returns the next free fundamental type id which can be used to 3647 * register a new fundamental type with g_type_register_fundamental(). 3648 * The returned type ID represents the highest currently registered 3649 * fundamental type identifier. 3650 * 3651 * Returns: The nextmost fundamental type ID to be registered, 3652 * or 0 if the type system ran out of fundamental type IDs. 3653 */ 3654GType 3655g_type_fundamental_next (void) 3656{ 3657 GType type; 3658 3659 G_READ_LOCK (&type_rw_lock); 3660 type = static_fundamental_next; 3661 G_READ_UNLOCK (&type_rw_lock); 3662 type = G_TYPE_MAKE_FUNDAMENTAL (type); 3663 return type <= G_TYPE_FUNDAMENTAL_MAX ? type : 0; 3664} 3665 3666/** 3667 * g_type_fundamental: 3668 * @type_id: valid type ID 3669 * 3670 * Internal function, used to extract the fundamental type ID portion. 3671 * use G_TYPE_FUNDAMENTAL() instead. 3672 * 3673 * Returns: fundamental type ID 3674 */ 3675GType 3676g_type_fundamental (GType type_id) 3677{ 3678 TypeNode *node = lookup_type_node_I (type_id); 3679 3680 return node ? NODE_FUNDAMENTAL_TYPE (node) : 0; 3681} 3682 3683gboolean 3684g_type_check_instance_is_a (GTypeInstance *type_instance, 3685 GType iface_type) 3686{ 3687 TypeNode *node, *iface; 3688 gboolean check; 3689 3690 if (!type_instance || !type_instance->g_class) 3691 return FALSE; 3692 3693 node = lookup_type_node_I (type_instance->g_class->g_type); 3694 iface = lookup_type_node_I (iface_type); 3695 check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE); 3696 3697 return check; 3698} 3699 3700gboolean 3701g_type_check_class_is_a (GTypeClass *type_class, 3702 GType is_a_type) 3703{ 3704 TypeNode *node, *iface; 3705 gboolean check; 3706 3707 if (!type_class) 3708 return FALSE; 3709 3710 node = lookup_type_node_I (type_class->g_type); 3711 iface = lookup_type_node_I (is_a_type); 3712 check = node && node->is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE); 3713 3714 return check; 3715} 3716 3717GTypeInstance* 3718g_type_check_instance_cast (GTypeInstance *type_instance, 3719 GType iface_type) 3720{ 3721 if (type_instance) 3722 { 3723 if (type_instance->g_class) 3724 { 3725 TypeNode *node, *iface; 3726 gboolean is_instantiatable, check; 3727 3728 node = lookup_type_node_I (type_instance->g_class->g_type); 3729 is_instantiatable = node && node->is_instantiatable; 3730 iface = lookup_type_node_I (iface_type); 3731 check = is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE); 3732 if (check) 3733 return type_instance; 3734 3735 if (is_instantiatable) 3736 g_warning ("invalid cast from `%s' to `%s'", 3737 type_descriptive_name_I (type_instance->g_class->g_type), 3738 type_descriptive_name_I (iface_type)); 3739 else 3740 g_warning ("invalid uninstantiatable type `%s' in cast to `%s'", 3741 type_descriptive_name_I (type_instance->g_class->g_type), 3742 type_descriptive_name_I (iface_type)); 3743 } 3744 else 3745 g_warning ("invalid unclassed pointer in cast to `%s'", 3746 type_descriptive_name_I (iface_type)); 3747 } 3748 3749 return type_instance; 3750} 3751 3752GTypeClass* 3753g_type_check_class_cast (GTypeClass *type_class, 3754 GType is_a_type) 3755{ 3756 if (type_class) 3757 { 3758 TypeNode *node, *iface; 3759 gboolean is_classed, check; 3760 3761 node = lookup_type_node_I (type_class->g_type); 3762 is_classed = node && node->is_classed; 3763 iface = lookup_type_node_I (is_a_type); 3764 check = is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE); 3765 if (check) 3766 return type_class; 3767 3768 if (is_classed) 3769 g_warning ("invalid class cast from `%s' to `%s'", 3770 type_descriptive_name_I (type_class->g_type), 3771 type_descriptive_name_I (is_a_type)); 3772 else 3773 g_warning ("invalid unclassed type `%s' in class cast to `%s'", 3774 type_descriptive_name_I (type_class->g_type), 3775 type_descriptive_name_I (is_a_type)); 3776 } 3777 else 3778 g_warning ("invalid class cast from (NULL) pointer to `%s'", 3779 type_descriptive_name_I (is_a_type)); 3780 return type_class; 3781} 3782 3783/** 3784 * g_type_check_instance: 3785 * @instance: A valid #GTypeInstance structure. 3786 * 3787 * Private helper function to aid implementation of the G_TYPE_CHECK_INSTANCE() 3788 * macro. 3789 * 3790 * @Returns: #TRUE if @instance is valid, #FALSE otherwise. 3791 */ 3792gboolean 3793g_type_check_instance (GTypeInstance *type_instance) 3794{ 3795 /* this function is just here to make the signal system 3796 * conveniently elaborated on instance checks 3797 */ 3798 if (type_instance) 3799 { 3800 if (type_instance->g_class) 3801 { 3802 TypeNode *node = lookup_type_node_I (type_instance->g_class->g_type); 3803 3804 if (node && node->is_instantiatable) 3805 return TRUE; 3806 3807 g_warning ("instance of invalid non-instantiatable type `%s'", 3808 type_descriptive_name_I (type_instance->g_class->g_type)); 3809 } 3810 else 3811 g_warning ("instance with invalid (NULL) class pointer"); 3812 } 3813 else 3814 g_warning ("invalid (NULL) pointer instance"); 3815 3816 return FALSE; 3817} 3818 3819static inline gboolean 3820type_check_is_value_type_U (GType type) 3821{ 3822 GTypeFlags tflags = G_TYPE_FLAG_VALUE_ABSTRACT; 3823 TypeNode *node; 3824 3825 /* common path speed up */ 3826 node = lookup_type_node_I (type); 3827 if (node && node->mutatable_check_cache) 3828 return TRUE; 3829 3830 G_READ_LOCK (&type_rw_lock); 3831 restart_check: 3832 if (node) 3833 { 3834 if (node->data && node->data->common.ref_count > 0 && 3835 node->data->common.value_table->value_init) 3836 tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)); 3837 else if (NODE_IS_IFACE (node)) 3838 { 3839 guint i; 3840 3841 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++) 3842 { 3843 GType prtype = IFACE_NODE_PREREQUISITES (node)[i]; 3844 TypeNode *prnode = lookup_type_node_I (prtype); 3845 3846 if (prnode->is_instantiatable) 3847 { 3848 type = prtype; 3849 node = lookup_type_node_I (type); 3850 goto restart_check; 3851 } 3852 } 3853 } 3854 } 3855 G_READ_UNLOCK (&type_rw_lock); 3856 3857 return !(tflags & G_TYPE_FLAG_VALUE_ABSTRACT); 3858} 3859 3860gboolean 3861g_type_check_is_value_type (GType type) 3862{ 3863 return type_check_is_value_type_U (type); 3864} 3865 3866gboolean 3867g_type_check_value (GValue *value) 3868{ 3869 return value && type_check_is_value_type_U (value->g_type); 3870} 3871 3872gboolean 3873g_type_check_value_holds (GValue *value, 3874 GType type) 3875{ 3876 return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type); 3877} 3878 3879/** 3880 * g_type_value_table_peek: 3881 * @type: A #GType value. 3882 * 3883 * Returns the location of the #GTypeValueTable associated with @type. 3884 * <emphasis>Note that this function should only be used from source code 3885 * that implements or has internal knowledge of the implementation of 3886 * @type.</emphasis> 3887 * 3888 * Returns: Location of the #GTypeValueTable associated with @type or 3889 * %NULL if there is no #GTypeValueTable associated with @type. 3890 */ 3891GTypeValueTable* 3892g_type_value_table_peek (GType type) 3893{ 3894 GTypeValueTable *vtable = NULL; 3895 TypeNode *node = lookup_type_node_I (type); 3896 gboolean has_refed_data, has_table; 3897 TypeData *data; 3898 3899 /* speed up common code path, we're not 100% safe here, 3900 * but we should only get called with referenced types anyway 3901 */ 3902 data = node ? node->data : NULL; 3903 if (node && node->mutatable_check_cache) 3904 return data->common.value_table; 3905 3906 G_READ_LOCK (&type_rw_lock); 3907 3908 restart_table_peek: 3909 has_refed_data = node && node->data && node->data->common.ref_count; 3910 has_table = has_refed_data && node->data->common.value_table->value_init; 3911 if (has_refed_data) 3912 { 3913 if (has_table) 3914 vtable = node->data->common.value_table; 3915 else if (NODE_IS_IFACE (node)) 3916 { 3917 guint i; 3918 3919 for (i = 0; i < IFACE_NODE_N_PREREQUISITES (node); i++) 3920 { 3921 GType prtype = IFACE_NODE_PREREQUISITES (node)[i]; 3922 TypeNode *prnode = lookup_type_node_I (prtype); 3923 3924 if (prnode->is_instantiatable) 3925 { 3926 type = prtype; 3927 node = lookup_type_node_I (type); 3928 goto restart_table_peek; 3929 } 3930 } 3931 } 3932 } 3933 3934 G_READ_UNLOCK (&type_rw_lock); 3935 3936 if (vtable) 3937 return vtable; 3938 3939 if (!node) 3940 g_warning (G_STRLOC ": type id `%" G_GSIZE_FORMAT "' is invalid", type); 3941 if (!has_refed_data) 3942 g_warning ("can't peek value table for type `%s' which is not currently referenced", 3943 type_descriptive_name_I (type)); 3944 3945 return NULL; 3946} 3947 3948G_CONST_RETURN gchar* 3949g_type_name_from_instance (GTypeInstance *instance) 3950{ 3951 if (!instance) 3952 return "<NULL-instance>"; 3953 else 3954 return g_type_name_from_class (instance->g_class); 3955} 3956 3957G_CONST_RETURN gchar* 3958g_type_name_from_class (GTypeClass *g_class) 3959{ 3960 if (!g_class) 3961 return "<NULL-class>"; 3962 else 3963 return g_type_name (g_class->g_type); 3964} 3965 3966 3967/* --- initialization --- */ 3968/** 3969 * g_type_init_with_debug_flags: 3970 * @debug_flags: Bitwise combination of #GTypeDebugFlags values for 3971 * debugging purposes. 3972 * 3973 * Similar to g_type_init(), but additionally sets debug flags. 3974 */ 3975void 3976g_type_init_with_debug_flags (GTypeDebugFlags debug_flags) 3977{ 3978 G_LOCK_DEFINE_STATIC (type_init_lock); 3979 const gchar *env_string; 3980 GTypeInfo info; 3981 TypeNode *node; 3982 volatile GType votype; 3983 3984 G_LOCK (type_init_lock); 3985 3986 G_WRITE_LOCK (&type_rw_lock); 3987 3988 if (static_quark_type_flags) 3989 { 3990 G_WRITE_UNLOCK (&type_rw_lock); 3991 G_UNLOCK (type_init_lock); 3992 return; 3993 } 3994 3995 /* setup GObject library wide debugging flags */ 3996 _g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK; 3997 env_string = g_getenv ("GOBJECT_DEBUG"); 3998 if (env_string != NULL) 3999 { 4000 static GDebugKey debug_keys[] = { 4001 { "objects", G_TYPE_DEBUG_OBJECTS }, 4002 { "signals", G_TYPE_DEBUG_SIGNALS }, 4003 }; 4004 4005 _g_type_debug_flags |= g_parse_debug_string (env_string, 4006 debug_keys, 4007 sizeof (debug_keys) / sizeof (debug_keys[0])); 4008 env_string = NULL; 4009 } 4010 4011 /* quarks */ 4012 static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags"); 4013 static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder"); 4014 static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array"); 4015 4016 /* type qname hash table */ 4017 static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal); 4018 4019 /* invalid type G_TYPE_INVALID (0) 4020 */ 4021 static_fundamental_type_nodes[0] = NULL; 4022 4023 /* void type G_TYPE_NONE 4024 */ 4025 node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0); 4026 votype = NODE_TYPE (node); 4027 g_assert (votype == G_TYPE_NONE); 4028 4029 /* interface fundamental type G_TYPE_INTERFACE (!classed) 4030 */ 4031 memset (&info, 0, sizeof (info)); 4032 node = type_node_fundamental_new_W (G_TYPE_INTERFACE, g_intern_static_string ("GInterface"), G_TYPE_FLAG_DERIVABLE); 4033 votype = NODE_TYPE (node); 4034 type_data_make_W (node, &info, NULL); 4035 g_assert (votype == G_TYPE_INTERFACE); 4036 4037 G_WRITE_UNLOCK (&type_rw_lock); 4038 4039 g_value_c_init (); 4040 4041 /* G_TYPE_TYPE_PLUGIN 4042 */ 4043 votype = g_type_plugin_get_type (); 4044 4045 /* G_TYPE_* value types 4046 */ 4047 g_value_types_init (); 4048 4049 /* G_TYPE_ENUM & G_TYPE_FLAGS 4050 */ 4051 g_enum_types_init (); 4052 4053 /* G_TYPE_BOXED 4054 */ 4055 g_boxed_type_init (); 4056 4057 /* G_TYPE_PARAM 4058 */ 4059 g_param_type_init (); 4060 4061 /* G_TYPE_OBJECT 4062 */ 4063 g_object_type_init (); 4064 4065 /* G_TYPE_PARAM_* pspec types 4066 */ 4067 g_param_spec_types_init (); 4068 4069 /* Value Transformations 4070 */ 4071 g_value_transforms_init (); 4072 4073 /* Signal system 4074 */ 4075 g_signal_init (); 4076 4077 G_UNLOCK (type_init_lock); 4078} 4079 4080/** 4081 * g_type_init: 4082 * 4083 * Prior to any use of the type system, g_type_init() has to be called 4084 * to initialize the type system and assorted other code portions 4085 * (such as the various fundamental type implementations or the signal 4086 * system). 4087 */ 4088void 4089g_type_init (void) 4090{ 4091 g_type_init_with_debug_flags (0); 4092} 4093 4094/** 4095 * g_type_class_add_private: 4096 * @g_class: class structure for an instantiatable type 4097 * @private_size: size of private structure. 4098 * 4099 * Registers a private structure for an instantiatable type; 4100 * when an object is allocated, the private structures for 4101 * the type and all of its parent types are allocated 4102 * sequentially in the same memory block as the public 4103 * structures. This function should be called in the 4104 * type's class_init() function. The private structure can 4105 * be retrieved using the G_TYPE_INSTANCE_GET_PRIVATE() macro. 4106 * The following example shows attaching a private structure 4107 * <structname>MyObjectPrivate</structname> to an object 4108 * <structname>MyObject</structname> defined in the standard GObject 4109 * fashion. 4110 * 4111 * |[ 4112 * typedef struct _MyObjectPrivate MyObjectPrivate; 4113 * 4114 * struct _MyObjectPrivate { 4115 * int some_field; 4116 * }; 4117 * 4118 * #define MY_OBJECT_GET_PRIVATE(o) \ 4119 * (G_TYPE_INSTANCE_GET_PRIVATE ((o), MY_TYPE_OBJECT, MyObjectPrivate)) 4120 * 4121 * static void 4122 * my_object_class_init (MyObjectClass *klass) 4123 * { 4124 * g_type_class_add_private (klass, sizeof (MyObjectPrivate)); 4125 * } 4126 * 4127 * static int 4128 * my_object_get_some_field (MyObject *my_object) 4129 * { 4130 * MyObjectPrivate *priv = MY_OBJECT_GET_PRIVATE (my_object); 4131 * 4132 * return priv->some_field; 4133 * } 4134 * ]| 4135 * 4136 * Since: 2.4 4137 */ 4138void 4139g_type_class_add_private (gpointer g_class, 4140 gsize private_size) 4141{ 4142 GType instance_type = ((GTypeClass *)g_class)->g_type; 4143 TypeNode *node = lookup_type_node_I (instance_type); 4144 gsize offset; 4145 4146 g_return_if_fail (private_size > 0); 4147 4148 if (!node || !node->is_instantiatable || !node->data || node->data->class.class != g_class) 4149 { 4150 g_warning ("cannot add private field to invalid (non-instantiatable) type '%s'", 4151 type_descriptive_name_I (instance_type)); 4152 return; 4153 } 4154 4155 if (NODE_PARENT_TYPE (node)) 4156 { 4157 TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); 4158 if (node->data->instance.private_size != pnode->data->instance.private_size) 4159 { 4160 g_warning ("g_type_add_private() called multiple times for the same type"); 4161 return; 4162 } 4163 } 4164 4165 G_WRITE_LOCK (&type_rw_lock); 4166 4167 offset = ALIGN_STRUCT (node->data->instance.private_size); 4168 node->data->instance.private_size = offset + private_size; 4169 4170 G_WRITE_UNLOCK (&type_rw_lock); 4171} 4172 4173gpointer 4174g_type_instance_get_private (GTypeInstance *instance, 4175 GType private_type) 4176{ 4177 TypeNode *instance_node; 4178 TypeNode *private_node; 4179 TypeNode *parent_node; 4180 GTypeClass *class; 4181 gsize offset; 4182 4183 g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL); 4184 4185 /* while instances are initialized, their class pointers change, 4186 * so figure the instances real class first 4187 */ 4188 class = instance_real_class_get (instance); 4189 if (!class) 4190 class = instance->g_class; 4191 4192 instance_node = lookup_type_node_I (class->g_type); 4193 if (G_UNLIKELY (!instance_node || !instance_node->is_instantiatable)) 4194 { 4195 g_warning ("instance of invalid non-instantiatable type `%s'", 4196 type_descriptive_name_I (instance->g_class->g_type)); 4197 return NULL; 4198 } 4199 4200 private_node = lookup_type_node_I (private_type); 4201 if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, instance_node))) 4202 { 4203 g_warning ("attempt to retrieve private data for invalid type '%s'", 4204 type_descriptive_name_I (private_type)); 4205 return NULL; 4206 } 4207 4208 /* Note that we don't need a read lock, since instance existing 4209 * means that the instance class and all parent classes 4210 * exist, so the node->data, node->data->instance.instance_size, 4211 * and node->data->instance.private_size are not going to be changed. 4212 * for any of the relevant types. 4213 */ 4214 4215 offset = ALIGN_STRUCT (instance_node->data->instance.instance_size); 4216 4217 if (NODE_PARENT_TYPE (private_node)) 4218 { 4219 parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node)); 4220 g_assert (parent_node->data && parent_node->data->common.ref_count); 4221 4222 if (G_UNLIKELY (private_node->data->instance.private_size == parent_node->data->instance.private_size)) 4223 { 4224 g_warning ("g_type_instance_get_private() requires a prior call to g_type_class_add_private()"); 4225 return NULL; 4226 } 4227 4228 offset += ALIGN_STRUCT (parent_node->data->instance.private_size); 4229 } 4230 4231 return G_STRUCT_MEMBER_P (instance, offset); 4232} 4233 4234#define __G_TYPE_C__ 4235#include "gobjectaliasdef.c" 4236