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.1 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
61typedef struct _ModuleTypeInfo ModuleTypeInfo;
62typedef struct _ModuleInterfaceInfo ModuleInterfaceInfo;
63
64struct _ModuleTypeInfo
65{
66 gboolean loaded;
67 GType type;
68 GType parent_type;
69 GTypeInfo info;
70};
71
72struct _ModuleInterfaceInfo
73{
74 gboolean loaded;
75 GType instance_type;
76 GType interface_type;
77 GInterfaceInfo info;
78};
79
80static void g_type_module_use_plugin (GTypePlugin *plugin);
81static void g_type_module_complete_type_info (GTypePlugin *plugin,
82 GType g_type,
83 GTypeInfo *info,
84 GTypeValueTable *value_table);
85static void g_type_module_complete_interface_info (GTypePlugin *plugin,
86 GType instance_type,
87 GType interface_type,
88 GInterfaceInfo *info);
89
90static gpointer parent_class = NULL;
91
92static void
93g_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
107static void
108g_type_module_finalize (GObject *object)
109{
110 GTypeModule *module = G_TYPE_MODULE (object);
111
112 g_free (mem: module->name);
113
114 G_OBJECT_CLASS (parent_class)->finalize (object);
115}
116
117static void
118g_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
128static void
129g_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
137GType
138g_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 NULL, /* value_table */
155 };
156 const GInterfaceInfo iface_info = {
157 (GInterfaceInitFunc) g_type_module_iface_init,
158 NULL, /* interface_finalize */
159 NULL, /* interface_data */
160 };
161
162 type_module_type = g_type_register_static (G_TYPE_OBJECT, type_name: g_intern_static_string (string: "GTypeModule"), info: &type_module_info, flags: G_TYPE_FLAG_ABSTRACT);
163
164 g_type_add_interface_static (instance_type: type_module_type, G_TYPE_TYPE_PLUGIN, info: &iface_info);
165 }
166
167 return type_module_type;
168}
169
170/**
171 * g_type_module_set_name:
172 * @module: a #GTypeModule.
173 * @name: a human-readable name to use in error messages.
174 *
175 * Sets the name for a #GTypeModule
176 */
177void
178g_type_module_set_name (GTypeModule *module,
179 const gchar *name)
180{
181 g_return_if_fail (G_IS_TYPE_MODULE (module));
182
183 g_free (mem: module->name);
184 module->name = g_strdup (str: name);
185}
186
187static ModuleTypeInfo *
188g_type_module_find_type_info (GTypeModule *module,
189 GType type)
190{
191 GSList *tmp_list = module->type_infos;
192 while (tmp_list)
193 {
194 ModuleTypeInfo *type_info = tmp_list->data;
195 if (type_info->type == type)
196 return type_info;
197
198 tmp_list = tmp_list->next;
199 }
200
201 return NULL;
202}
203
204static ModuleInterfaceInfo *
205g_type_module_find_interface_info (GTypeModule *module,
206 GType instance_type,
207 GType interface_type)
208{
209 GSList *tmp_list = module->interface_infos;
210 while (tmp_list)
211 {
212 ModuleInterfaceInfo *interface_info = tmp_list->data;
213 if (interface_info->instance_type == instance_type &&
214 interface_info->interface_type == interface_type)
215 return interface_info;
216
217 tmp_list = tmp_list->next;
218 }
219
220 return NULL;
221}
222
223/**
224 * g_type_module_use:
225 * @module: a #GTypeModule
226 *
227 * Increases the use count of a #GTypeModule by one. If the
228 * use count was zero before, the plugin will be loaded.
229 * If loading the plugin fails, the use count is reset to
230 * its prior value.
231 *
232 * Returns: %FALSE if the plugin needed to be loaded and
233 * loading the plugin failed.
234 */
235gboolean
236g_type_module_use (GTypeModule *module)
237{
238 g_return_val_if_fail (G_IS_TYPE_MODULE (module), FALSE);
239
240 module->use_count++;
241 if (module->use_count == 1)
242 {
243 GSList *tmp_list;
244
245 if (!G_TYPE_MODULE_GET_CLASS (module)->load (module))
246 {
247 module->use_count--;
248 return FALSE;
249 }
250
251 tmp_list = module->type_infos;
252 while (tmp_list)
253 {
254 ModuleTypeInfo *type_info = tmp_list->data;
255 if (!type_info->loaded)
256 {
257 g_warning ("plugin '%s' failed to register type '%s'",
258 module->name ? module->name : "(unknown)",
259 g_type_name (type_info->type));
260 module->use_count--;
261 return FALSE;
262 }
263
264 tmp_list = tmp_list->next;
265 }
266 }
267
268 return TRUE;
269}
270
271/**
272 * g_type_module_unuse:
273 * @module: a #GTypeModule
274 *
275 * Decreases the use count of a #GTypeModule by one. If the
276 * result is zero, the module will be unloaded. (However, the
277 * #GTypeModule will not be freed, and types associated with the
278 * #GTypeModule are not unregistered. Once a #GTypeModule is
279 * initialized, it must exist forever.)
280 */
281void
282g_type_module_unuse (GTypeModule *module)
283{
284 g_return_if_fail (G_IS_TYPE_MODULE (module));
285 g_return_if_fail (module->use_count > 0);
286
287 module->use_count--;
288
289 if (module->use_count == 0)
290 {
291 GSList *tmp_list;
292
293 G_TYPE_MODULE_GET_CLASS (module)->unload (module);
294
295 tmp_list = module->type_infos;
296 while (tmp_list)
297 {
298 ModuleTypeInfo *type_info = tmp_list->data;
299 type_info->loaded = FALSE;
300
301 tmp_list = tmp_list->next;
302 }
303 }
304}
305
306static void
307g_type_module_use_plugin (GTypePlugin *plugin)
308{
309 GTypeModule *module = G_TYPE_MODULE (plugin);
310
311 if (!g_type_module_use (module))
312 {
313 g_warning ("Fatal error - Could not reload previously loaded plugin '%s'",
314 module->name ? module->name : "(unknown)");
315 exit (status: 1);
316 }
317}
318
319static void
320g_type_module_complete_type_info (GTypePlugin *plugin,
321 GType g_type,
322 GTypeInfo *info,
323 GTypeValueTable *value_table)
324{
325 GTypeModule *module = G_TYPE_MODULE (plugin);
326 ModuleTypeInfo *module_type_info = g_type_module_find_type_info (module, type: g_type);
327
328 *info = module_type_info->info;
329
330 if (module_type_info->info.value_table)
331 *value_table = *module_type_info->info.value_table;
332}
333
334static void
335g_type_module_complete_interface_info (GTypePlugin *plugin,
336 GType instance_type,
337 GType interface_type,
338 GInterfaceInfo *info)
339{
340 GTypeModule *module = G_TYPE_MODULE (plugin);
341 ModuleInterfaceInfo *module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
342
343 *info = module_interface_info->info;
344}
345
346/**
347 * g_type_module_register_type:
348 * @module: (nullable): a #GTypeModule
349 * @parent_type: the type for the parent class
350 * @type_name: name for the type
351 * @type_info: type information structure
352 * @flags: flags field providing details about the type
353 *
354 * Looks up or registers a type that is implemented with a particular
355 * type plugin. If a type with name @type_name was previously registered,
356 * the #GType identifier for the type is returned, otherwise the type
357 * is newly registered, and the resulting #GType identifier returned.
358 *
359 * When reregistering a type (typically because a module is unloaded
360 * then reloaded, and reinitialized), @module and @parent_type must
361 * be the same as they were previously.
362 *
363 * As long as any instances of the type exist, the type plugin will
364 * not be unloaded.
365 *
366 * Since 2.56 if @module is %NULL this will call g_type_register_static()
367 * instead. This can be used when making a static build of the module.
368 *
369 * Returns: the new or existing type ID
370 */
371GType
372g_type_module_register_type (GTypeModule *module,
373 GType parent_type,
374 const gchar *type_name,
375 const GTypeInfo *type_info,
376 GTypeFlags flags)
377{
378 ModuleTypeInfo *module_type_info = NULL;
379 GType type;
380
381 g_return_val_if_fail (type_name != NULL, 0);
382 g_return_val_if_fail (type_info != NULL, 0);
383
384 if (module == NULL)
385 {
386 /* Cannot pass type_info directly to g_type_register_static() here because
387 * it has class_finalize != NULL and that's forbidden for static types */
388 return g_type_register_static_simple (parent_type,
389 type_name,
390 class_size: type_info->class_size,
391 class_init: type_info->class_init,
392 instance_size: type_info->instance_size,
393 instance_init: type_info->instance_init,
394 flags);
395 }
396
397 type = g_type_from_name (name: type_name);
398 if (type)
399 {
400 GTypePlugin *old_plugin = g_type_get_plugin (type);
401
402 if (old_plugin != G_TYPE_PLUGIN (module))
403 {
404 g_warning ("Two different plugins tried to register '%s'.", type_name);
405 return 0;
406 }
407 }
408
409 if (type)
410 {
411 module_type_info = g_type_module_find_type_info (module, type);
412
413 if (module_type_info->parent_type != parent_type)
414 {
415 const gchar *parent_type_name = g_type_name (type: parent_type);
416
417 g_warning ("Type '%s' recreated with different parent type."
418 "(was '%s', now '%s')", type_name,
419 g_type_name (module_type_info->parent_type),
420 parent_type_name ? parent_type_name : "(unknown)");
421 return 0;
422 }
423
424 if (module_type_info->info.value_table)
425 g_free (mem: (GTypeValueTable *) module_type_info->info.value_table);
426 }
427 else
428 {
429 module_type_info = g_new (ModuleTypeInfo, 1);
430
431 module_type_info->parent_type = parent_type;
432 module_type_info->type = g_type_register_dynamic (parent_type, type_name, G_TYPE_PLUGIN (module), flags);
433
434 module->type_infos = g_slist_prepend (list: module->type_infos, data: module_type_info);
435 }
436
437 module_type_info->loaded = TRUE;
438 module_type_info->info = *type_info;
439 if (type_info->value_table)
440 module_type_info->info.value_table = g_memdup2 (mem: type_info->value_table,
441 byte_size: sizeof (GTypeValueTable));
442
443 return module_type_info->type;
444}
445
446/**
447 * g_type_module_add_interface:
448 * @module: (nullable): a #GTypeModule
449 * @instance_type: type to which to add the interface.
450 * @interface_type: interface type to add
451 * @interface_info: type information structure
452 *
453 * Registers an additional interface for a type, whose interface lives
454 * in the given type plugin. If the interface was already registered
455 * for the type in this plugin, nothing will be done.
456 *
457 * As long as any instances of the type exist, the type plugin will
458 * not be unloaded.
459 *
460 * Since 2.56 if @module is %NULL this will call g_type_add_interface_static()
461 * instead. This can be used when making a static build of the module.
462 */
463void
464g_type_module_add_interface (GTypeModule *module,
465 GType instance_type,
466 GType interface_type,
467 const GInterfaceInfo *interface_info)
468{
469 ModuleInterfaceInfo *module_interface_info = NULL;
470
471 g_return_if_fail (interface_info != NULL);
472
473 if (module == NULL)
474 {
475 g_type_add_interface_static (instance_type, interface_type, info: interface_info);
476 return;
477 }
478
479 if (g_type_is_a (type: instance_type, is_a_type: interface_type))
480 {
481 GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type,
482 interface_type);
483
484 if (!old_plugin)
485 {
486 g_warning ("Interface '%s' for '%s' was previously registered statically or for a parent type.",
487 g_type_name (interface_type), g_type_name (instance_type));
488 return;
489 }
490 else if (old_plugin != G_TYPE_PLUGIN (module))
491 {
492 g_warning ("Two different plugins tried to register interface '%s' for '%s'.",
493 g_type_name (interface_type), g_type_name (instance_type));
494 return;
495 }
496
497 module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
498
499 g_assert (module_interface_info);
500 }
501 else
502 {
503 module_interface_info = g_new (ModuleInterfaceInfo, 1);
504
505 module_interface_info->instance_type = instance_type;
506 module_interface_info->interface_type = interface_type;
507
508 g_type_add_interface_dynamic (instance_type, interface_type, G_TYPE_PLUGIN (module));
509
510 module->interface_infos = g_slist_prepend (list: module->interface_infos, data: module_interface_info);
511 }
512
513 module_interface_info->loaded = TRUE;
514 module_interface_info->info = *interface_info;
515}
516
517/**
518 * g_type_module_register_enum:
519 * @module: (nullable): a #GTypeModule
520 * @name: name for the type
521 * @const_static_values: an array of #GEnumValue structs for the
522 * possible enumeration values. The array is
523 * terminated by a struct with all members being
524 * 0.
525 *
526 * Looks up or registers an enumeration that is implemented with a particular
527 * type plugin. If a type with name @type_name was previously registered,
528 * the #GType identifier for the type is returned, otherwise the type
529 * is newly registered, and the resulting #GType identifier returned.
530 *
531 * As long as any instances of the type exist, the type plugin will
532 * not be unloaded.
533 *
534 * Since 2.56 if @module is %NULL this will call g_type_register_static()
535 * instead. This can be used when making a static build of the module.
536 *
537 * Since: 2.6
538 *
539 * Returns: the new or existing type ID
540 */
541GType
542g_type_module_register_enum (GTypeModule *module,
543 const gchar *name,
544 const GEnumValue *const_static_values)
545{
546 GTypeInfo enum_type_info = { 0, };
547
548 g_return_val_if_fail (module == NULL || G_IS_TYPE_MODULE (module), 0);
549 g_return_val_if_fail (name != NULL, 0);
550 g_return_val_if_fail (const_static_values != NULL, 0);
551
552 g_enum_complete_type_info (G_TYPE_ENUM,
553 info: &enum_type_info, const_values: const_static_values);
554
555 return g_type_module_register_type (G_TYPE_MODULE (module),
556 G_TYPE_ENUM, type_name: name, type_info: &enum_type_info, flags: 0);
557}
558
559/**
560 * g_type_module_register_flags:
561 * @module: (nullable): a #GTypeModule
562 * @name: name for the type
563 * @const_static_values: an array of #GFlagsValue structs for the
564 * possible flags values. The array is
565 * terminated by a struct with all members being
566 * 0.
567 *
568 * Looks up or registers a flags type that is implemented with a particular
569 * type plugin. If a type with name @type_name was previously registered,
570 * the #GType identifier for the type is returned, otherwise the type
571 * is newly registered, and the resulting #GType identifier returned.
572 *
573 * As long as any instances of the type exist, the type plugin will
574 * not be unloaded.
575 *
576 * Since 2.56 if @module is %NULL this will call g_type_register_static()
577 * instead. This can be used when making a static build of the module.
578 *
579 * Since: 2.6
580 *
581 * Returns: the new or existing type ID
582 */
583GType
584g_type_module_register_flags (GTypeModule *module,
585 const gchar *name,
586 const GFlagsValue *const_static_values)
587{
588 GTypeInfo flags_type_info = { 0, };
589
590 g_return_val_if_fail (module == NULL || G_IS_TYPE_MODULE (module), 0);
591 g_return_val_if_fail (name != NULL, 0);
592 g_return_val_if_fail (const_static_values != NULL, 0);
593
594 g_flags_complete_type_info (G_TYPE_FLAGS,
595 info: &flags_type_info, const_values: const_static_values);
596
597 return g_type_module_register_type (G_TYPE_MODULE (module),
598 G_TYPE_FLAGS, type_name: name, type_info: &flags_type_info, flags: 0);
599}
600

source code of gtk/subprojects/glib/gobject/gtypemodule.c