Home | History | Annotate | Download | only in gobject
      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