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