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 * @short_description: Type loading modules 32 * @see_also:<variablelist> 33 * <varlistentry> 34 * <term>#GTypePlugin</term> 35 * <listitem><para>The abstract type loader interface.</para></listitem> 36 * </varlistentry> 37 * <varlistentry> 38 * <term>#GModule</term> 39 * <listitem><para>Portable mechanism for dynamically loaded modules.</para></listitem> 40 * </varlistentry> 41 * </variablelist> 42 * @title: GTypeModule 43 * 44 * #GTypeModule provides a simple implementation of the #GTypePlugin 45 * interface. The model of #GTypeModule is a dynamically loaded module 46 * which implements some number of types and interface 47 * implementations. When the module is loaded, it registers its types 48 * and interfaces using g_type_module_register_type() and 49 * g_type_module_add_interface(). As long as any instances of these 50 * types and interface implementations are in use, the module is kept 51 * loaded. When the types and interfaces are gone, the module may be 52 * unloaded. If the types and interfaces become used again, the module 53 * will be reloaded. Note that the last unref can not happen in module 54 * code, since that would lead to the caller's code being unloaded before 55 * g_object_unref() returns to it. 56 * 57 * Keeping track of whether the module should be loaded or not is done by 58 * using a use count - it starts at zero, and whenever it is greater than 59 * zero, the module is loaded. The use count is maintained internally by 60 * the type system, but also can be explicitly controlled by 61 * g_type_module_use() and g_type_module_unuse(). Typically, when loading 62 * a module for the first type, g_type_module_use() will be used to load 63 * it so that it can initialize its types. At some later point, when the 64 * module no longer needs to be loaded except for the type 65 * implementations it contains, g_type_module_unuse() is called. 66 * 67 * #GTypeModule does not actually provide any implementation of module 68 * loading and unloading. To create a particular module type you must 69 * derive from #GTypeModule and implement the load and unload functions 70 * in #GTypeModuleClass. 71 */ 72 73 74 typedef struct _ModuleTypeInfo ModuleTypeInfo; 75 typedef struct _ModuleInterfaceInfo ModuleInterfaceInfo; 76 77 struct _ModuleTypeInfo 78 { 79 gboolean loaded; 80 GType type; 81 GType parent_type; 82 GTypeInfo info; 83 }; 84 85 struct _ModuleInterfaceInfo 86 { 87 gboolean loaded; 88 GType instance_type; 89 GType interface_type; 90 GInterfaceInfo info; 91 }; 92 93 static void g_type_module_use_plugin (GTypePlugin *plugin); 94 static void g_type_module_complete_type_info (GTypePlugin *plugin, 95 GType g_type, 96 GTypeInfo *info, 97 GTypeValueTable *value_table); 98 static void g_type_module_complete_interface_info (GTypePlugin *plugin, 99 GType instance_type, 100 GType interface_type, 101 GInterfaceInfo *info); 102 103 static gpointer parent_class = NULL; 104 105 static void 106 g_type_module_dispose (GObject *object) 107 { 108 GTypeModule *module = G_TYPE_MODULE (object); 109 110 if (module->type_infos || module->interface_infos) 111 { 112 g_warning (G_STRLOC ": unsolicitated invocation of g_object_dispose() on GTypeModule"); 113 114 g_object_ref (object); 115 } 116 117 G_OBJECT_CLASS (parent_class)->dispose (object); 118 } 119 120 static void 121 g_type_module_finalize (GObject *object) 122 { 123 GTypeModule *module = G_TYPE_MODULE (object); 124 125 g_free (module->name); 126 127 G_OBJECT_CLASS (parent_class)->finalize (object); 128 } 129 130 static void 131 g_type_module_class_init (GTypeModuleClass *class) 132 { 133 GObjectClass *gobject_class = G_OBJECT_CLASS (class); 134 135 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class)); 136 137 gobject_class->dispose = g_type_module_dispose; 138 gobject_class->finalize = g_type_module_finalize; 139 } 140 141 static void 142 g_type_module_iface_init (GTypePluginClass *iface) 143 { 144 iface->use_plugin = g_type_module_use_plugin; 145 iface->unuse_plugin = (void (*) (GTypePlugin *))g_type_module_unuse; 146 iface->complete_type_info = g_type_module_complete_type_info; 147 iface->complete_interface_info = g_type_module_complete_interface_info; 148 } 149 150 GType 151 g_type_module_get_type (void) 152 { 153 static GType type_module_type = 0; 154 155 if (!type_module_type) 156 { 157 static const GTypeInfo type_module_info = { 158 sizeof (GTypeModuleClass), 159 NULL, /* base_init */ 160 NULL, /* base_finalize */ 161 (GClassInitFunc) g_type_module_class_init, 162 NULL, /* class_finalize */ 163 NULL, /* class_data */ 164 sizeof (GTypeModule), 165 0, /* n_preallocs */ 166 NULL, /* instance_init */ 167 }; 168 static const GInterfaceInfo iface_info = { 169 (GInterfaceInitFunc) g_type_module_iface_init, 170 NULL, /* interface_finalize */ 171 NULL, /* interface_data */ 172 }; 173 174 type_module_type = g_type_register_static (G_TYPE_OBJECT, g_intern_static_string ("GTypeModule"), &type_module_info, G_TYPE_FLAG_ABSTRACT); 175 176 g_type_add_interface_static (type_module_type, G_TYPE_TYPE_PLUGIN, &iface_info); 177 } 178 179 return type_module_type; 180 } 181 182 /** 183 * g_type_module_set_name: 184 * @module: a #GTypeModule. 185 * @name: a human-readable name to use in error messages. 186 * 187 * Sets the name for a #GTypeModule 188 */ 189 void 190 g_type_module_set_name (GTypeModule *module, 191 const gchar *name) 192 { 193 g_return_if_fail (G_IS_TYPE_MODULE (module)); 194 195 g_free (module->name); 196 module->name = g_strdup (name); 197 } 198 199 static ModuleTypeInfo * 200 g_type_module_find_type_info (GTypeModule *module, 201 GType type) 202 { 203 GSList *tmp_list = module->type_infos; 204 while (tmp_list) 205 { 206 ModuleTypeInfo *type_info = tmp_list->data; 207 if (type_info->type == type) 208 return type_info; 209 210 tmp_list = tmp_list->next; 211 } 212 213 return NULL; 214 } 215 216 static ModuleInterfaceInfo * 217 g_type_module_find_interface_info (GTypeModule *module, 218 GType instance_type, 219 GType interface_type) 220 { 221 GSList *tmp_list = module->interface_infos; 222 while (tmp_list) 223 { 224 ModuleInterfaceInfo *interface_info = tmp_list->data; 225 if (interface_info->instance_type == instance_type && 226 interface_info->interface_type == interface_type) 227 return interface_info; 228 229 tmp_list = tmp_list->next; 230 } 231 232 return NULL; 233 } 234 235 /** 236 * g_type_module_use: 237 * @module: a #GTypeModule 238 * 239 * Increases the use count of a #GTypeModule by one. If the 240 * use count was zero before, the plugin will be loaded. 241 * If loading the plugin fails, the use count is reset to 242 * its prior value. 243 * 244 * Returns: %FALSE if the plugin needed to be loaded and 245 * loading the plugin failed. 246 */ 247 gboolean 248 g_type_module_use (GTypeModule *module) 249 { 250 g_return_val_if_fail (G_IS_TYPE_MODULE (module), FALSE); 251 252 module->use_count++; 253 if (module->use_count == 1) 254 { 255 GSList *tmp_list; 256 257 if (!G_TYPE_MODULE_GET_CLASS (module)->load (module)) 258 { 259 module->use_count--; 260 return FALSE; 261 } 262 263 tmp_list = module->type_infos; 264 while (tmp_list) 265 { 266 ModuleTypeInfo *type_info = tmp_list->data; 267 if (!type_info->loaded) 268 { 269 g_warning ("plugin '%s' failed to register type '%s'\n", 270 module->name ? module->name : "(unknown)", 271 g_type_name (type_info->type)); 272 module->use_count--; 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 */ 293 void 294 g_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 318 static void 319 g_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 331 static void 332 g_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 346 static void 347 g_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 */ 380 GType 381 g_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 */ 457 void 458 g_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 */ 527 GType 528 g_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 */ 566 GType 567 g_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