Tizen 2.1 base
[platform/upstream/glib2.0.git] / gobject / gtypemodule.c
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 cannot 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       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       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
409       if (module_type_info->parent_type != parent_type)
410         {
411           const gchar *parent_type_name = g_type_name (parent_type);
412           
413           g_warning ("Type '%s' recreated with different parent type.\n"
414                      "(was '%s', now '%s')", type_name,
415                      g_type_name (module_type_info->parent_type),
416                      parent_type_name ? parent_type_name : "(unknown)");
417           return 0;
418         }
419
420       if (module_type_info->info.value_table)
421         g_free ((GTypeValueTable *) module_type_info->info.value_table);
422     }
423   else
424     {
425       module_type_info = g_new (ModuleTypeInfo, 1);
426       
427       module_type_info->parent_type = parent_type;
428       module_type_info->type = g_type_register_dynamic (parent_type, type_name, G_TYPE_PLUGIN (module), flags);
429       
430       module->type_infos = g_slist_prepend (module->type_infos, module_type_info);
431     }
432
433   module_type_info->loaded = TRUE;
434   module_type_info->info = *type_info;
435   if (type_info->value_table)
436     module_type_info->info.value_table = g_memdup (type_info->value_table,
437                                                    sizeof (GTypeValueTable));
438
439   return module_type_info->type;
440 }
441
442 /**
443  * g_type_module_add_interface:
444  * @module: a #GTypeModule
445  * @instance_type: type to which to add the interface.
446  * @interface_type: interface type to add
447  * @interface_info: type information structure
448  *
449  * Registers an additional interface for a type, whose interface lives
450  * in the given type plugin. If the interface was already registered
451  * for the type in this plugin, nothing will be done.
452  *
453  * As long as any instances of the type exist, the type plugin will
454  * not be unloaded.
455  */
456 void
457 g_type_module_add_interface (GTypeModule          *module,
458                              GType                 instance_type,
459                              GType                 interface_type,
460                              const GInterfaceInfo *interface_info)
461 {
462   ModuleInterfaceInfo *module_interface_info = NULL;
463   
464   g_return_if_fail (module != NULL);
465   g_return_if_fail (interface_info != NULL);
466
467   if (g_type_is_a (instance_type, interface_type))
468     {
469       GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type,
470                                                              interface_type);
471
472       if (!old_plugin)
473         {
474           g_warning ("Interface '%s' for '%s' was previously registered statically or for a parent type.",
475                      g_type_name (interface_type), g_type_name (instance_type));
476           return;
477         }
478       else if (old_plugin != G_TYPE_PLUGIN (module))
479         {
480           g_warning ("Two different plugins tried to register interface '%s' for '%s'.",
481                      g_type_name (interface_type), g_type_name (instance_type));
482           return;
483         }
484       
485       module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
486
487       g_assert (module_interface_info);
488     }
489   else
490     {
491       module_interface_info = g_new (ModuleInterfaceInfo, 1);
492       
493       module_interface_info->instance_type = instance_type;
494       module_interface_info->interface_type = interface_type;
495       
496       g_type_add_interface_dynamic (instance_type, interface_type, G_TYPE_PLUGIN (module));
497       
498       module->interface_infos = g_slist_prepend (module->interface_infos, module_interface_info);
499     }
500   
501   module_interface_info->loaded = TRUE;
502   module_interface_info->info = *interface_info;
503 }
504
505 /**
506  * g_type_module_register_enum:
507  * @module: a #GTypeModule
508  * @name: name for the type
509  * @const_static_values: an array of #GEnumValue structs for the
510  *                       possible enumeration values. The array is
511  *                       terminated by a struct with all members being
512  *                       0.
513  *
514  * Looks up or registers an enumeration that is implemented with a particular
515  * type plugin. If a type with name @type_name was previously registered,
516  * the #GType identifier for the type is returned, otherwise the type
517  * is newly registered, and the resulting #GType identifier returned.
518  *
519  * As long as any instances of the type exist, the type plugin will
520  * not be unloaded.
521  *
522  * Since: 2.6
523  *
524  * Returns: the new or existing type ID
525  */
526 GType
527 g_type_module_register_enum (GTypeModule      *module,
528                              const gchar      *name,
529                              const GEnumValue *const_static_values)
530 {
531   GTypeInfo enum_type_info = { 0, };
532
533   g_return_val_if_fail (G_IS_TYPE_MODULE (module), 0);
534   g_return_val_if_fail (name != NULL, 0);
535   g_return_val_if_fail (const_static_values != NULL, 0);
536
537   g_enum_complete_type_info (G_TYPE_ENUM,
538                              &enum_type_info, const_static_values);
539
540   return g_type_module_register_type (G_TYPE_MODULE (module),
541                                       G_TYPE_ENUM, name, &enum_type_info, 0);
542 }
543
544 /**
545  * g_type_module_register_flags:
546  * @module: a #GTypeModule
547  * @name: name for the type
548  * @const_static_values: an array of #GFlagsValue structs for the
549  *                       possible flags values. The array is
550  *                       terminated by a struct with all members being
551  *                       0.
552  *
553  * Looks up or registers a flags type that is implemented with a particular
554  * type plugin. If a type with name @type_name was previously registered,
555  * the #GType identifier for the type is returned, otherwise the type
556  * is newly registered, and the resulting #GType identifier returned.
557  *
558  * As long as any instances of the type exist, the type plugin will
559  * not be unloaded.
560  *
561  * Since: 2.6
562  *
563  * Returns: the new or existing type ID
564  */
565 GType
566 g_type_module_register_flags (GTypeModule      *module,
567                              const gchar       *name,
568                              const GFlagsValue *const_static_values)
569 {
570   GTypeInfo flags_type_info = { 0, };
571
572   g_return_val_if_fail (G_IS_TYPE_MODULE (module), 0);
573   g_return_val_if_fail (name != NULL, 0);
574   g_return_val_if_fail (const_static_values != NULL, 0);
575
576   g_flags_complete_type_info (G_TYPE_FLAGS,
577                              &flags_type_info, const_static_values);
578
579   return g_type_module_register_type (G_TYPE_MODULE (module),
580                                       G_TYPE_FLAGS, name, &flags_type_info, 0);
581 }