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