1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2000 Red Hat, Inc.
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23
24 #include "gtypeplugin.h"
25 #include "gtypemodule.h"
26
27
28 /**
29 * GTypeModule:
30 * @name: the name of the module
31 *
32 * `GTypeModule` provides a simple implementation of the `GTypePlugin`
33 * interface.
34 *
35 * The model of `GTypeModule` is a dynamically loaded module which
36 * implements some number of types and interface implementations.
37 *
38 * When the module is loaded, it registers its types and interfaces
39 * using [method@GObject.TypeModule.register_type] and
40 * [method@GObject.TypeModule.add_interface].
41 * As long as any instances of these types and interface implementations
42 * are in use, the module is kept loaded. When the types and interfaces
43 * are gone, the module may be unloaded. If the types and interfaces
44 * become used again, the module will be reloaded. Note that the last
45 * reference cannot be released from within the module code, since that
46 * would lead to the caller's code being unloaded before `g_object_unref()`
47 * returns to it.
48 *
49 * Keeping track of whether the module should be loaded or not is done by
50 * using a use count - it starts at zero, and whenever it is greater than
51 * zero, the module is loaded. The use count is maintained internally by
52 * the type system, but also can be explicitly controlled by
53 * [method@GObject.TypeModule.use] and [method@GObject.TypeModule.unuse].
54 * Typically, when loading a module for the first type, `g_type_module_use()`
55 * will be used to load it so that it can initialize its types. At some later
56 * point, when the module no longer needs to be loaded except for the type
57 * implementations it contains, `g_type_module_unuse()` is called.
58 *
59 * `GTypeModule` does not actually provide any implementation of module
60 * loading and unloading. To create a particular module type you must
61 * derive from `GTypeModule` and implement the load and unload functions
62 * in `GTypeModuleClass`.
63 */
64
65 typedef struct _ModuleTypeInfo ModuleTypeInfo;
66 typedef struct _ModuleInterfaceInfo ModuleInterfaceInfo;
67
68 struct _ModuleTypeInfo
69 {
70 gboolean loaded;
71 GType type;
72 GType parent_type;
73 GTypeInfo info;
74 };
75
76 struct _ModuleInterfaceInfo
77 {
78 gboolean loaded;
79 GType instance_type;
80 GType interface_type;
81 GInterfaceInfo info;
82 };
83
84 static void g_type_module_use_plugin (GTypePlugin *plugin);
85 static void g_type_module_complete_type_info (GTypePlugin *plugin,
86 GType g_type,
87 GTypeInfo *info,
88 GTypeValueTable *value_table);
89 static void g_type_module_complete_interface_info (GTypePlugin *plugin,
90 GType instance_type,
91 GType interface_type,
92 GInterfaceInfo *info);
93
94 static gpointer parent_class = NULL;
95
96 static void
97 g_type_module_dispose (GObject *object)
98 {
99 GTypeModule *module = G_TYPE_MODULE (object);
100
101 if (module->type_infos || module->interface_infos)
102 {
103 g_critical (G_STRLOC ": unsolicitated invocation of g_object_run_dispose() on GTypeModule");
104
105 g_object_ref (object);
106 }
107
108 G_OBJECT_CLASS (parent_class)->dispose (object);
109 }
110
111 static void
112 g_type_module_finalize (GObject *object)
113 {
114 GTypeModule *module = G_TYPE_MODULE (object);
115
116 g_free (module->name);
117
118 /* in case a subclass does not chain-up to parent in dispose() */
119 g_assert (module->type_infos == NULL);
120 g_assert (module->interface_infos == NULL);
121
122 G_OBJECT_CLASS (parent_class)->finalize (object);
123 }
124
125 static void
126 g_type_module_class_init (GTypeModuleClass *class)
127 {
128 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
129
130 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class));
131
132 gobject_class->dispose = g_type_module_dispose;
133 gobject_class->finalize = g_type_module_finalize;
134 }
135
136 static void
137 g_type_module_iface_init (GTypePluginClass *iface)
138 {
139 iface->use_plugin = g_type_module_use_plugin;
140 iface->unuse_plugin = (void (*) (GTypePlugin *))g_type_module_unuse;
141 iface->complete_type_info = g_type_module_complete_type_info;
142 iface->complete_interface_info = g_type_module_complete_interface_info;
143 }
144
145 GType
146 g_type_module_get_type (void)
147 {
148 static GType type_module_type = 0;
149
150 if (!type_module_type)
151 {
152 const GTypeInfo type_module_info = {
153 sizeof (GTypeModuleClass),
154 NULL, /* base_init */
155 NULL, /* base_finalize */
156 (GClassInitFunc) g_type_module_class_init,
157 NULL, /* class_finalize */
158 NULL, /* class_data */
159 sizeof (GTypeModule),
160 0, /* n_preallocs */
161 NULL, /* instance_init */
162 NULL, /* value_table */
163 };
164 const GInterfaceInfo iface_info = {
165 (GInterfaceInitFunc) g_type_module_iface_init,
166 NULL, /* interface_finalize */
167 NULL, /* interface_data */
168 };
169
170 type_module_type = g_type_register_static (G_TYPE_OBJECT, g_intern_static_string ("GTypeModule"), &type_module_info, G_TYPE_FLAG_ABSTRACT);
171
172 g_type_add_interface_static (type_module_type, G_TYPE_TYPE_PLUGIN, &iface_info);
173 }
174
175 return type_module_type;
176 }
177
178 /**
179 * g_type_module_set_name:
180 * @module: a #GTypeModule.
181 * @name: a human-readable name to use in error messages.
182 *
183 * Sets the name for a #GTypeModule
184 */
185 void
186 g_type_module_set_name (GTypeModule *module,
187 const gchar *name)
188 {
189 g_return_if_fail (G_IS_TYPE_MODULE (module));
190
191 g_free (module->name);
192 module->name = g_strdup (name);
193 }
194
195 static ModuleTypeInfo *
196 g_type_module_find_type_info (GTypeModule *module,
197 GType type)
198 {
199 GSList *tmp_list = module->type_infos;
200 while (tmp_list)
201 {
202 ModuleTypeInfo *type_info = tmp_list->data;
203 if (type_info->type == type)
204 return type_info;
205
206 tmp_list = tmp_list->next;
207 }
208
209 return NULL;
210 }
211
212 static ModuleInterfaceInfo *
213 g_type_module_find_interface_info (GTypeModule *module,
214 GType instance_type,
215 GType interface_type)
216 {
217 GSList *tmp_list = module->interface_infos;
218 while (tmp_list)
219 {
220 ModuleInterfaceInfo *interface_info = tmp_list->data;
221 if (interface_info->instance_type == instance_type &&
222 interface_info->interface_type == interface_type)
223 return interface_info;
224
225 tmp_list = tmp_list->next;
226 }
227
228 return NULL;
229 }
230
231 /**
232 * g_type_module_use:
233 * @module: a #GTypeModule
234 *
235 * Increases the use count of a #GTypeModule by one. If the
236 * use count was zero before, the plugin will be loaded.
237 * If loading the plugin fails, the use count is reset to
238 * its prior value.
239 *
240 * Returns: %FALSE if the plugin needed to be loaded and
241 * loading the plugin failed.
242 */
243 gboolean
244 g_type_module_use (GTypeModule *module)
245 {
246 g_return_val_if_fail (G_IS_TYPE_MODULE (module), FALSE);
247
248 module->use_count++;
249 if (module->use_count == 1)
250 {
251 GSList *tmp_list;
252
253 if (!G_TYPE_MODULE_GET_CLASS (module)->load (module))
254 {
255 module->use_count--;
256 return FALSE;
257 }
258
259 tmp_list = module->type_infos;
260 while (tmp_list)
261 {
262 ModuleTypeInfo *type_info = tmp_list->data;
263 if (!type_info->loaded)
264 {
265 g_critical ("plugin '%s' failed to register type '%s'",
266 module->name ? module->name : "(unknown)",
267 g_type_name (type_info->type));
268 module->use_count--;
269 return FALSE;
270 }
271
272 tmp_list = tmp_list->next;
273 }
274 }
275
276 return TRUE;
277 }
278
279 /**
280 * g_type_module_unuse:
281 * @module: a #GTypeModule
282 *
283 * Decreases the use count of a #GTypeModule by one. If the
284 * result is zero, the module will be unloaded. (However, the
285 * #GTypeModule will not be freed, and types associated with the
286 * #GTypeModule are not unregistered. Once a #GTypeModule is
287 * initialized, it must exist forever.)
288 */
289 void
290 g_type_module_unuse (GTypeModule *module)
291 {
292 g_return_if_fail (G_IS_TYPE_MODULE (module));
293 g_return_if_fail (module->use_count > 0);
294
295 module->use_count--;
296
297 if (module->use_count == 0)
298 {
299 GSList *tmp_list;
300
301 G_TYPE_MODULE_GET_CLASS (module)->unload (module);
302
303 tmp_list = module->type_infos;
304 while (tmp_list)
305 {
306 ModuleTypeInfo *type_info = tmp_list->data;
307 type_info->loaded = FALSE;
308
309 tmp_list = tmp_list->next;
310 }
311 }
312 }
313
314 static void
315 g_type_module_use_plugin (GTypePlugin *plugin)
316 {
317 GTypeModule *module = G_TYPE_MODULE (plugin);
318
319 if (!g_type_module_use (module))
320 {
321 g_error ("Fatal error - Could not reload previously loaded plugin '%s'",
322 module->name ? module->name : "(unknown)");
323 }
324 }
325
326 static void
327 g_type_module_complete_type_info (GTypePlugin *plugin,
328 GType g_type,
329 GTypeInfo *info,
330 GTypeValueTable *value_table)
331 {
332 GTypeModule *module = G_TYPE_MODULE (plugin);
333 ModuleTypeInfo *module_type_info = g_type_module_find_type_info (module, g_type);
334
335 *info = module_type_info->info;
336
337 if (module_type_info->info.value_table)
338 *value_table = *module_type_info->info.value_table;
339 }
340
341 static void
342 g_type_module_complete_interface_info (GTypePlugin *plugin,
343 GType instance_type,
344 GType interface_type,
345 GInterfaceInfo *info)
346 {
347 GTypeModule *module = G_TYPE_MODULE (plugin);
348 ModuleInterfaceInfo *module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
349
350 *info = module_interface_info->info;
351 }
352
353 /**
354 * g_type_module_register_type:
355 * @module: (nullable): a #GTypeModule
356 * @parent_type: the type for the parent class
357 * @type_name: name for the type
358 * @type_info: type information structure
359 * @flags: flags field providing details about the type
360 *
361 * Looks up or registers a type that is implemented with a particular
362 * type plugin. If a type with name @type_name was previously registered,
363 * the #GType identifier for the type is returned, otherwise the type
364 * is newly registered, and the resulting #GType identifier returned.
365 *
366 * When reregistering a type (typically because a module is unloaded
367 * then reloaded, and reinitialized), @module and @parent_type must
368 * be the same as they were previously.
369 *
370 * As long as any instances of the type exist, the type plugin will
371 * not be unloaded.
372 *
373 * Since 2.56 if @module is %NULL this will call g_type_register_static()
374 * instead. This can be used when making a static build of the module.
375 *
376 * Returns: the new or existing type ID
377 */
378 GType
379 g_type_module_register_type (GTypeModule *module,
380 GType parent_type,
381 const gchar *type_name,
382 const GTypeInfo *type_info,
383 GTypeFlags flags)
384 {
385 ModuleTypeInfo *module_type_info = NULL;
386 GType type;
387
388 g_return_val_if_fail (type_name != NULL, 0);
389 g_return_val_if_fail (type_info != NULL, 0);
390
391 if (module == NULL)
392 {
393 /* Cannot pass type_info directly to g_type_register_static() here because
394 * it has class_finalize != NULL and that's forbidden for static types */
395 return g_type_register_static_simple (parent_type,
396 type_name,
397 type_info->class_size,
398 type_info->class_init,
399 type_info->instance_size,
400 type_info->instance_init,
401 flags);
402 }
403
404 type = g_type_from_name (type_name);
405 if (type)
406 {
407 GTypePlugin *old_plugin = g_type_get_plugin (type);
408
409 if (old_plugin != G_TYPE_PLUGIN (module))
410 {
411 g_critical ("Two different plugins tried to register '%s'.", type_name);
412 return 0;
413 }
414 }
415
416 if (type)
417 {
418 module_type_info = g_type_module_find_type_info (module, type);
419
420 if (module_type_info->parent_type != parent_type)
421 {
422 const gchar *parent_type_name = g_type_name (parent_type);
423
424 g_critical ("Type '%s' recreated with different parent type."
425 "(was '%s', now '%s')", type_name,
426 g_type_name (module_type_info->parent_type),
427 parent_type_name ? parent_type_name : "(unknown)");
428 return 0;
429 }
430
431 if (module_type_info->info.value_table)
432 g_free ((GTypeValueTable *) module_type_info->info.value_table);
433 }
434 else
435 {
436 module_type_info = g_new (ModuleTypeInfo, 1);
437
438 module_type_info->parent_type = parent_type;
439 module_type_info->type = g_type_register_dynamic (parent_type, type_name, G_TYPE_PLUGIN (module), flags);
440
441 module->type_infos = g_slist_prepend (module->type_infos, module_type_info);
442 }
443
444 module_type_info->loaded = TRUE;
445 module_type_info->info = *type_info;
446 if (type_info->value_table)
447 module_type_info->info.value_table = g_memdup2 (type_info->value_table,
448 sizeof (GTypeValueTable));
449
450 return module_type_info->type;
451 }
452
453 /**
454 * g_type_module_add_interface:
455 * @module: (nullable): a #GTypeModule
456 * @instance_type: type to which to add the interface.
457 * @interface_type: interface type to add
458 * @interface_info: type information structure
459 *
460 * Registers an additional interface for a type, whose interface lives
461 * in the given type plugin. If the interface was already registered
462 * for the type in this plugin, nothing will be done.
463 *
464 * As long as any instances of the type exist, the type plugin will
465 * not be unloaded.
466 *
467 * Since 2.56 if @module is %NULL this will call g_type_add_interface_static()
468 * instead. This can be used when making a static build of the module.
469 */
470 void
471 g_type_module_add_interface (GTypeModule *module,
472 GType instance_type,
473 GType interface_type,
474 const GInterfaceInfo *interface_info)
475 {
476 ModuleInterfaceInfo *module_interface_info = NULL;
477
478 g_return_if_fail (interface_info != NULL);
479
480 if (module == NULL)
481 {
482 g_type_add_interface_static (instance_type, interface_type, interface_info);
483 return;
484 }
485
486 if (g_type_is_a (instance_type, interface_type))
487 {
488 GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type,
489 interface_type);
490
491 if (!old_plugin)
492 {
493 g_critical ("Interface '%s' for '%s' was previously registered statically or for a parent type.",
494 g_type_name (interface_type), g_type_name (instance_type));
495 return;
496 }
497 else if (old_plugin != G_TYPE_PLUGIN (module))
498 {
499 g_critical ("Two different plugins tried to register interface '%s' for '%s'.",
500 g_type_name (interface_type), g_type_name (instance_type));
501 return;
502 }
503
504 module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
505
506 g_assert (module_interface_info);
507 }
508 else
509 {
510 module_interface_info = g_new (ModuleInterfaceInfo, 1);
511
512 module_interface_info->instance_type = instance_type;
513 module_interface_info->interface_type = interface_type;
514
515 g_type_add_interface_dynamic (instance_type, interface_type, G_TYPE_PLUGIN (module));
516
517 module->interface_infos = g_slist_prepend (module->interface_infos, module_interface_info);
518 }
519
520 module_interface_info->loaded = TRUE;
521 module_interface_info->info = *interface_info;
522 }
523
524 /**
525 * g_type_module_register_enum:
526 * @module: (nullable): a #GTypeModule
527 * @name: name for the type
528 * @const_static_values: an array of #GEnumValue structs for the
529 * possible enumeration values. The array is
530 * terminated by a struct with all members being
531 * 0.
532 *
533 * Looks up or registers an enumeration that is implemented with a particular
534 * type plugin. If a type with name @type_name was previously registered,
535 * the #GType identifier for the type is returned, otherwise the type
536 * is newly registered, and the resulting #GType identifier returned.
537 *
538 * As long as any instances of the type exist, the type plugin will
539 * not be unloaded.
540 *
541 * Since 2.56 if @module is %NULL this will call g_type_register_static()
542 * instead. This can be used when making a static build of the module.
543 *
544 * Since: 2.6
545 *
546 * Returns: the new or existing type ID
547 */
548 GType
549 g_type_module_register_enum (GTypeModule *module,
550 const gchar *name,
551 const GEnumValue *const_static_values)
552 {
553 GTypeInfo enum_type_info = { 0, };
554
555 g_return_val_if_fail (module == NULL || G_IS_TYPE_MODULE (module), 0);
556 g_return_val_if_fail (name != NULL, 0);
557 g_return_val_if_fail (const_static_values != NULL, 0);
558
559 g_enum_complete_type_info (G_TYPE_ENUM,
560 &enum_type_info, const_static_values);
561
562 return g_type_module_register_type (G_TYPE_MODULE (module),
563 G_TYPE_ENUM, name, &enum_type_info, 0);
564 }
565
566 /**
567 * g_type_module_register_flags:
568 * @module: (nullable): a #GTypeModule
569 * @name: name for the type
570 * @const_static_values: an array of #GFlagsValue structs for the
571 * possible flags values. The array is
572 * terminated by a struct with all members being
573 * 0.
574 *
575 * Looks up or registers a flags type that is implemented with a particular
576 * type plugin. If a type with name @type_name was previously registered,
577 * the #GType identifier for the type is returned, otherwise the type
578 * is newly registered, and the resulting #GType identifier returned.
579 *
580 * As long as any instances of the type exist, the type plugin will
581 * not be unloaded.
582 *
583 * Since 2.56 if @module is %NULL this will call g_type_register_static()
584 * instead. This can be used when making a static build of the module.
585 *
586 * Since: 2.6
587 *
588 * Returns: the new or existing type ID
589 */
590 GType
591 g_type_module_register_flags (GTypeModule *module,
592 const gchar *name,
593 const GFlagsValue *const_static_values)
594 {
595 GTypeInfo flags_type_info = { 0, };
596
597 g_return_val_if_fail (module == NULL || G_IS_TYPE_MODULE (module), 0);
598 g_return_val_if_fail (name != NULL, 0);
599 g_return_val_if_fail (const_static_values != NULL, 0);
600
601 g_flags_complete_type_info (G_TYPE_FLAGS,
602 &flags_type_info, const_static_values);
603
604 return g_type_module_register_type (G_TYPE_MODULE (module),
605 G_TYPE_FLAGS, name, &flags_type_info, 0);
606 }