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 }