gtypemodule.c revision 6347be5fb68fc3e5e9d5bfedc3cbd5349ef40074
1/* GObject - GLib Type, Object, Parameter and Signal Library 2 * Copyright (C) 2000 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 Public 15 * 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#include "config.h" 21 22#include <stdlib.h> 23 24#include "gtypeplugin.h" 25#include "gtypemodule.h" 26#include "gobjectalias.h" 27 28 29/** 30 * SECTION:gtypemodule 31 * 32 * @Short_description: Type loading modules 33 * 34 * @See_also:<variablelist> 35 * <varlistentry> 36 * <term>#GTypePlugin</term> 37 * <listitem><para>The abstract type loader interface.</para></listitem> 38 * </varlistentry> 39 * <varlistentry> 40 * <term>#GModule</term> 41 * <listitem><para>Portable mechanism for dynamically loaded modules.</para></listitem> 42 * </varlistentry> 43 * </variablelist> 44 * 45 * @Title: GTypeModule 46 * 47 * #GTypeModule provides a simple implementation of the #GTypePlugin 48 * interface. The model of #GTypeModule is a dynamically loaded module 49 * which implements some number of types and interface 50 * implementations. When the module is loaded, it registers its types 51 * and interfaces using g_type_module_register_type() and 52 * g_type_module_add_interface(). As long as any instances of these 53 * types and interface implementations are in use, the module is kept 54 * loaded. When the types and interfaces are gone, the module may be 55 * unloaded. If the types and interfaces become used again, the module 56 * will be reloaded. Note that the last unref can not happen in module 57 * code, since that would lead to the caller's code being unloaded before 58 * g_object_unref() returns to it. 59 * 60 * Keeping track of whether the module should be loaded or not is done by 61 * using a use count - it starts at zero, and whenever it is greater than 62 * zero, the module is loaded. The use count is maintained internally by 63 * the type system, but also can be explicitly controlled by 64 * g_type_module_use() and g_type_module_unuse(). Typically, when loading 65 * a module for the first type, g_type_module_use() will be used to load 66 * it so that it can initialize its types. At some later point, when the 67 * module no longer needs to be loaded except for the type 68 * implementations it contains, g_type_module_unuse() is called. 69 * 70 * #GTypeModule does not actually provide any implementation of module 71 * loading and unloading. To create a particular module type you must 72 * derive from #GTypeModule and implement the load and unload functions 73 * in #GTypeModuleClass. 74 */ 75 76 77typedef struct _ModuleTypeInfo ModuleTypeInfo; 78typedef struct _ModuleInterfaceInfo ModuleInterfaceInfo; 79 80struct _ModuleTypeInfo 81{ 82 gboolean loaded; 83 GType type; 84 GType parent_type; 85 GTypeInfo info; 86}; 87 88struct _ModuleInterfaceInfo 89{ 90 gboolean loaded; 91 GType instance_type; 92 GType interface_type; 93 GInterfaceInfo info; 94}; 95 96static void g_type_module_use_plugin (GTypePlugin *plugin); 97static void g_type_module_complete_type_info (GTypePlugin *plugin, 98 GType g_type, 99 GTypeInfo *info, 100 GTypeValueTable *value_table); 101static void g_type_module_complete_interface_info (GTypePlugin *plugin, 102 GType instance_type, 103 GType interface_type, 104 GInterfaceInfo *info); 105 106static gpointer parent_class = NULL; 107 108static void 109g_type_module_dispose (GObject *object) 110{ 111 GTypeModule *module = G_TYPE_MODULE (object); 112 113 if (module->type_infos || module->interface_infos) 114 { 115 g_warning (G_STRLOC ": unsolicitated invocation of g_object_dispose() on GTypeModule"); 116 117 g_object_ref (object); 118 } 119 120 G_OBJECT_CLASS (parent_class)->dispose (object); 121} 122 123static void 124g_type_module_finalize (GObject *object) 125{ 126 GTypeModule *module = G_TYPE_MODULE (object); 127 128 g_free (module->name); 129 130 G_OBJECT_CLASS (parent_class)->finalize (object); 131} 132 133static void 134g_type_module_class_init (GTypeModuleClass *class) 135{ 136 GObjectClass *gobject_class = G_OBJECT_CLASS (class); 137 138 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class)); 139 140 gobject_class->dispose = g_type_module_dispose; 141 gobject_class->finalize = g_type_module_finalize; 142} 143 144static void 145g_type_module_iface_init (GTypePluginClass *iface) 146{ 147 iface->use_plugin = g_type_module_use_plugin; 148 iface->unuse_plugin = (void (*) (GTypePlugin *))g_type_module_unuse; 149 iface->complete_type_info = g_type_module_complete_type_info; 150 iface->complete_interface_info = g_type_module_complete_interface_info; 151} 152 153GType 154g_type_module_get_type (void) 155{ 156 static GType type_module_type = 0; 157 158 if (!type_module_type) 159 { 160 static const GTypeInfo type_module_info = { 161 sizeof (GTypeModuleClass), 162 NULL, /* base_init */ 163 NULL, /* base_finalize */ 164 (GClassInitFunc) g_type_module_class_init, 165 NULL, /* class_finalize */ 166 NULL, /* class_data */ 167 sizeof (GTypeModule), 168 0, /* n_preallocs */ 169 NULL, /* instance_init */ 170 }; 171 static const GInterfaceInfo iface_info = { 172 (GInterfaceInitFunc) g_type_module_iface_init, 173 NULL, /* interface_finalize */ 174 NULL, /* interface_data */ 175 }; 176 177 type_module_type = g_type_register_static (G_TYPE_OBJECT, g_intern_static_string ("GTypeModule"), &type_module_info, G_TYPE_FLAG_ABSTRACT); 178 179 g_type_add_interface_static (type_module_type, G_TYPE_TYPE_PLUGIN, &iface_info); 180 } 181 182 return type_module_type; 183} 184 185/** 186 * g_type_module_set_name: 187 * @module: a #GTypeModule. 188 * @name: a human-readable name to use in error messages. 189 * 190 * Sets the name for a #GTypeModule 191 */ 192void 193g_type_module_set_name (GTypeModule *module, 194 const gchar *name) 195{ 196 g_return_if_fail (G_IS_TYPE_MODULE (module)); 197 198 g_free (module->name); 199 module->name = g_strdup (name); 200} 201 202static ModuleTypeInfo * 203g_type_module_find_type_info (GTypeModule *module, 204 GType type) 205{ 206 GSList *tmp_list = module->type_infos; 207 while (tmp_list) 208 { 209 ModuleTypeInfo *type_info = tmp_list->data; 210 if (type_info->type == type) 211 return type_info; 212 213 tmp_list = tmp_list->next; 214 } 215 216 return NULL; 217} 218 219static ModuleInterfaceInfo * 220g_type_module_find_interface_info (GTypeModule *module, 221 GType instance_type, 222 GType interface_type) 223{ 224 GSList *tmp_list = module->interface_infos; 225 while (tmp_list) 226 { 227 ModuleInterfaceInfo *interface_info = tmp_list->data; 228 if (interface_info->instance_type == instance_type && 229 interface_info->interface_type == interface_type) 230 return interface_info; 231 232 tmp_list = tmp_list->next; 233 } 234 235 return NULL; 236} 237 238/** 239 * g_type_module_use: 240 * @module: a #GTypeModule 241 * 242 * Increases the use count of a #GTypeModule by one. If the 243 * use count was zero before, the plugin will be loaded. 244 * 245 * Returns: %FALSE if the plugin needed to be loaded and 246 * loading the plugin failed. 247 */ 248gboolean 249g_type_module_use (GTypeModule *module) 250{ 251 g_return_val_if_fail (G_IS_TYPE_MODULE (module), FALSE); 252 253 module->use_count++; 254 if (module->use_count == 1) 255 { 256 GSList *tmp_list; 257 258 if (!G_TYPE_MODULE_GET_CLASS (module)->load (module)) 259 { 260 module->use_count--; 261 return FALSE; 262 } 263 264 tmp_list = module->type_infos; 265 while (tmp_list) 266 { 267 ModuleTypeInfo *type_info = tmp_list->data; 268 if (!type_info->loaded) 269 { 270 g_warning ("plugin '%s' failed to register type '%s'\n", 271 module->name ? module->name : "(unknown)", 272 g_type_name (type_info->type)); 273 return FALSE; 274 } 275 276 tmp_list = tmp_list->next; 277 } 278 } 279 280 return TRUE; 281} 282 283/** 284 * g_type_module_unuse: 285 * @module: a #GTypeModule 286 * 287 * Decreases the use count of a #GTypeModule by one. If the 288 * result is zero, the module will be unloaded. (However, the 289 * #GTypeModule will not be freed, and types associated with the 290 * #GTypeModule are not unregistered. Once a #GTypeModule is 291 * initialized, it must exist forever.) 292 */ 293void 294g_type_module_unuse (GTypeModule *module) 295{ 296 g_return_if_fail (G_IS_TYPE_MODULE (module)); 297 g_return_if_fail (module->use_count > 0); 298 299 module->use_count--; 300 301 if (module->use_count == 0) 302 { 303 GSList *tmp_list; 304 305 G_TYPE_MODULE_GET_CLASS (module)->unload (module); 306 307 tmp_list = module->type_infos; 308 while (tmp_list) 309 { 310 ModuleTypeInfo *type_info = tmp_list->data; 311 type_info->loaded = FALSE; 312 313 tmp_list = tmp_list->next; 314 } 315 } 316} 317 318static void 319g_type_module_use_plugin (GTypePlugin *plugin) 320{ 321 GTypeModule *module = G_TYPE_MODULE (plugin); 322 323 if (!g_type_module_use (module)) 324 { 325 g_warning ("Fatal error - Could not reload previously loaded plugin '%s'\n", 326 module->name ? module->name : "(unknown)"); 327 exit (1); 328 } 329} 330 331static void 332g_type_module_complete_type_info (GTypePlugin *plugin, 333 GType g_type, 334 GTypeInfo *info, 335 GTypeValueTable *value_table) 336{ 337 GTypeModule *module = G_TYPE_MODULE (plugin); 338 ModuleTypeInfo *module_type_info = g_type_module_find_type_info (module, g_type); 339 340 *info = module_type_info->info; 341 342 if (module_type_info->info.value_table) 343 *value_table = *module_type_info->info.value_table; 344} 345 346static void 347g_type_module_complete_interface_info (GTypePlugin *plugin, 348 GType instance_type, 349 GType interface_type, 350 GInterfaceInfo *info) 351{ 352 GTypeModule *module = G_TYPE_MODULE (plugin); 353 ModuleInterfaceInfo *module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type); 354 355 *info = module_interface_info->info; 356} 357 358/** 359 * g_type_module_register_type: 360 * @module: a #GTypeModule 361 * @parent_type: the type for the parent class 362 * @type_name: name for the type 363 * @type_info: type information structure 364 * @flags: flags field providing details about the type 365 * 366 * Looks up or registers a type that is implemented with a particular 367 * type plugin. If a type with name @type_name was previously registered, 368 * the #GType identifier for the type is returned, otherwise the type 369 * is newly registered, and the resulting #GType identifier returned. 370 * 371 * When reregistering a type (typically because a module is unloaded 372 * then reloaded, and reinitialized), @module and @parent_type must 373 * be the same as they were previously. 374 * 375 * As long as any instances of the type exist, the type plugin will 376 * not be unloaded. 377 * 378 * Returns: the new or existing type ID 379 */ 380GType 381g_type_module_register_type (GTypeModule *module, 382 GType parent_type, 383 const gchar *type_name, 384 const GTypeInfo *type_info, 385 GTypeFlags flags) 386{ 387 ModuleTypeInfo *module_type_info = NULL; 388 GType type; 389 390 g_return_val_if_fail (module != NULL, 0); 391 g_return_val_if_fail (type_name != NULL, 0); 392 g_return_val_if_fail (type_info != NULL, 0); 393 394 type = g_type_from_name (type_name); 395 if (type) 396 { 397 GTypePlugin *old_plugin = g_type_get_plugin (type); 398 399 if (old_plugin != G_TYPE_PLUGIN (module)) 400 { 401 g_warning ("Two different plugins tried to register '%s'.", type_name); 402 return 0; 403 } 404 } 405 406 if (type) 407 { 408 module_type_info = g_type_module_find_type_info (module, type); 409 410 if (module_type_info->parent_type != parent_type) 411 { 412 const gchar *parent_type_name = g_type_name (parent_type); 413 414 g_warning ("Type '%s' recreated with different parent type.\n" 415 "(was '%s', now '%s')", type_name, 416 g_type_name (module_type_info->parent_type), 417 parent_type_name ? parent_type_name : "(unknown)"); 418 return 0; 419 } 420 421 if (module_type_info->info.value_table) 422 g_free ((GTypeValueTable *) module_type_info->info.value_table); 423 } 424 else 425 { 426 module_type_info = g_new (ModuleTypeInfo, 1); 427 428 module_type_info->parent_type = parent_type; 429 module_type_info->type = g_type_register_dynamic (parent_type, type_name, G_TYPE_PLUGIN (module), flags); 430 431 module->type_infos = g_slist_prepend (module->type_infos, module_type_info); 432 } 433 434 module_type_info->loaded = TRUE; 435 module_type_info->info = *type_info; 436 if (type_info->value_table) 437 module_type_info->info.value_table = g_memdup (type_info->value_table, 438 sizeof (GTypeValueTable)); 439 440 return module_type_info->type; 441} 442 443/** 444 * g_type_module_add_interface: 445 * @module: a #GTypeModule 446 * @instance_type: type to which to add the interface. 447 * @interface_type: interface type to add 448 * @interface_info: type information structure 449 * 450 * Registers an additional interface for a type, whose interface lives 451 * in the given type plugin. If the interface was already registered 452 * for the type in this plugin, nothing will be done. 453 * 454 * As long as any instances of the type exist, the type plugin will 455 * not be unloaded. 456 */ 457void 458g_type_module_add_interface (GTypeModule *module, 459 GType instance_type, 460 GType interface_type, 461 const GInterfaceInfo *interface_info) 462{ 463 ModuleInterfaceInfo *module_interface_info = NULL; 464 465 g_return_if_fail (module != NULL); 466 g_return_if_fail (interface_info != NULL); 467 468 if (g_type_is_a (instance_type, interface_type)) 469 { 470 GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type, 471 interface_type); 472 473 if (!old_plugin) 474 { 475 g_warning ("Interface '%s' for '%s' was previously registered statically or for a parent type.", 476 g_type_name (interface_type), g_type_name (instance_type)); 477 return; 478 } 479 else if (old_plugin != G_TYPE_PLUGIN (module)) 480 { 481 g_warning ("Two different plugins tried to register interface '%s' for '%s'.", 482 g_type_name (interface_type), g_type_name (instance_type)); 483 return; 484 } 485 486 module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type); 487 488 g_assert (module_interface_info); 489 } 490 else 491 { 492 module_interface_info = g_new (ModuleInterfaceInfo, 1); 493 494 module_interface_info->instance_type = instance_type; 495 module_interface_info->interface_type = interface_type; 496 497 g_type_add_interface_dynamic (instance_type, interface_type, G_TYPE_PLUGIN (module)); 498 499 module->interface_infos = g_slist_prepend (module->interface_infos, module_interface_info); 500 } 501 502 module_interface_info->loaded = TRUE; 503 module_interface_info->info = *interface_info; 504} 505 506/** 507 * g_type_module_register_enum: 508 * @module: a #GTypeModule 509 * @name: name for the type 510 * @const_static_values: an array of #GEnumValue structs for the 511 * possible enumeration values. The array is 512 * terminated by a struct with all members being 513 * 0. 514 * 515 * Looks up or registers an enumeration that is implemented with a particular 516 * type plugin. If a type with name @type_name was previously registered, 517 * the #GType identifier for the type is returned, otherwise the type 518 * is newly registered, and the resulting #GType identifier returned. 519 * 520 * As long as any instances of the type exist, the type plugin will 521 * not be unloaded. 522 * 523 * Since: 2.6 524 * 525 * Returns: the new or existing type ID 526 */ 527GType 528g_type_module_register_enum (GTypeModule *module, 529 const gchar *name, 530 const GEnumValue *const_static_values) 531{ 532 GTypeInfo enum_type_info = { 0, }; 533 534 g_return_val_if_fail (G_IS_TYPE_MODULE (module), 0); 535 g_return_val_if_fail (name != NULL, 0); 536 g_return_val_if_fail (const_static_values != NULL, 0); 537 538 g_enum_complete_type_info (G_TYPE_ENUM, 539 &enum_type_info, const_static_values); 540 541 return g_type_module_register_type (G_TYPE_MODULE (module), 542 G_TYPE_ENUM, name, &enum_type_info, 0); 543} 544 545/** 546 * g_type_module_register_flags: 547 * @module: a #GTypeModule 548 * @name: name for the type 549 * @const_static_values: an array of #GFlagsValue structs for the 550 * possible flags values. The array is 551 * terminated by a struct with all members being 552 * 0. 553 * 554 * Looks up or registers a flags type that is implemented with a particular 555 * type plugin. If a type with name @type_name was previously registered, 556 * the #GType identifier for the type is returned, otherwise the type 557 * is newly registered, and the resulting #GType identifier returned. 558 * 559 * As long as any instances of the type exist, the type plugin will 560 * not be unloaded. 561 * 562 * Since: 2.6 563 * 564 * Returns: the new or existing type ID 565 */ 566GType 567g_type_module_register_flags (GTypeModule *module, 568 const gchar *name, 569 const GFlagsValue *const_static_values) 570{ 571 GTypeInfo flags_type_info = { 0, }; 572 573 g_return_val_if_fail (G_IS_TYPE_MODULE (module), 0); 574 g_return_val_if_fail (name != NULL, 0); 575 g_return_val_if_fail (const_static_values != NULL, 0); 576 577 g_flags_complete_type_info (G_TYPE_FLAGS, 578 &flags_type_info, const_static_values); 579 580 return g_type_module_register_type (G_TYPE_MODULE (module), 581 G_TYPE_FLAGS, name, &flags_type_info, 0); 582} 583 584 585#define __G_TYPE_MODULE_C__ 586#include "gobjectaliasdef.c" 587