Branch data Line data Source code
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
17 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : */
19 : :
20 : : #include "config.h"
21 : :
22 : : #include "gtypeplugin.h"
23 : :
24 : :
25 : : /**
26 : : * GTypePlugin:
27 : : *
28 : : * An interface that handles the lifecycle of dynamically loaded types.
29 : : *
30 : : * The GObject type system supports dynamic loading of types.
31 : : * It goes as follows:
32 : : *
33 : : * 1. The type is initially introduced (usually upon loading the module
34 : : * the first time, or by your main application that knows what modules
35 : : * introduces what types), like this:
36 : : * ```c
37 : : * new_type_id = g_type_register_dynamic (parent_type_id,
38 : : * "TypeName",
39 : : * new_type_plugin,
40 : : * type_flags);
41 : : * ```
42 : : * where `new_type_plugin` is an implementation of the
43 : : * `GTypePlugin` interface.
44 : : *
45 : : * 2. The type's implementation is referenced, e.g. through
46 : : * [func@GObject.TypeClass.ref] or through [func@GObject.type_create_instance]
47 : : * (this is being called by [ctor@GObject.Object.new]) or through one of the above
48 : : * done on a type derived from `new_type_id`.
49 : : *
50 : : * 3. This causes the type system to load the type's implementation by calling
51 : : * [method@GObject.TypePlugin.use] and [method@GObject.TypePlugin.complete_type_info]
52 : : * on `new_type_plugin`.
53 : : *
54 : : * 4. At some point the type's implementation isn't required anymore, e.g. after
55 : : * [method@GObject.TypeClass.unref] or [func@GObject.type_free_instance]
56 : : * (called when the reference count of an instance drops to zero).
57 : : *
58 : : * 5. This causes the type system to throw away the information retrieved
59 : : * from [method@GObject.TypePlugin.complete_type_info] and then it calls
60 : : * [method@GObject.TypePlugin.unuse] on `new_type_plugin`.
61 : : *
62 : : * 6. Things may repeat from the second step.
63 : : *
64 : : * So basically, you need to implement a `GTypePlugin` type that
65 : : * carries a use_count, once use_count goes from zero to one, you need
66 : : * to load the implementation to successfully handle the upcoming
67 : : * [method@GObject.TypePlugin.complete_type_info] call. Later, maybe after
68 : : * succeeding use/unuse calls, once use_count drops to zero, you can
69 : : * unload the implementation again. The type system makes sure to call
70 : : * [method@GObject.TypePlugin.use] and [method@GObject.TypePlugin.complete_type_info]
71 : : * again when the type is needed again.
72 : : *
73 : : * [class@GObject.TypeModule] is an implementation of `GTypePlugin` that
74 : : * already implements most of this except for the actual module loading and
75 : : * unloading. It even handles multiple registered types per module.
76 : : */
77 : :
78 : :
79 : : /* --- functions --- */
80 : : GType
81 : 604 : g_type_plugin_get_type (void)
82 : : {
83 : : static GType type_plugin_type = 0;
84 : :
85 : 604 : if (!type_plugin_type)
86 : : {
87 : 545 : const GTypeInfo type_plugin_info = {
88 : : sizeof (GTypePluginClass),
89 : : NULL, /* base_init */
90 : : NULL, /* base_finalize */
91 : : 0, /* class_init */
92 : : NULL, /* class_destroy */
93 : : NULL, /* class_data */
94 : : 0, /* instance_size */
95 : : 0, /* n_preallocs */
96 : : NULL, /* instance_init */
97 : : NULL, /* value_table */
98 : : };
99 : :
100 : 545 : type_plugin_type = g_type_register_static (G_TYPE_INTERFACE, g_intern_static_string ("GTypePlugin"), &type_plugin_info, 0);
101 : : }
102 : :
103 : 604 : return type_plugin_type;
104 : : }
105 : :
106 : : /**
107 : : * g_type_plugin_use:
108 : : * @plugin: a #GTypePlugin
109 : : *
110 : : * Calls the @use_plugin function from the #GTypePluginClass of
111 : : * @plugin. There should be no need to use this function outside of
112 : : * the GObject type system itself.
113 : : */
114 : : void
115 : 6 : g_type_plugin_use (GTypePlugin *plugin)
116 : : {
117 : : GTypePluginClass *iface;
118 : :
119 : 6 : g_return_if_fail (G_IS_TYPE_PLUGIN (plugin));
120 : :
121 : 6 : iface = G_TYPE_PLUGIN_GET_CLASS (plugin);
122 : 6 : iface->use_plugin (plugin);
123 : : }
124 : :
125 : : /**
126 : : * g_type_plugin_unuse:
127 : : * @plugin: a #GTypePlugin
128 : : *
129 : : * Calls the @unuse_plugin function from the #GTypePluginClass of
130 : : * @plugin. There should be no need to use this function outside of
131 : : * the GObject type system itself.
132 : : */
133 : : void
134 : 0 : g_type_plugin_unuse (GTypePlugin *plugin)
135 : : {
136 : : GTypePluginClass *iface;
137 : :
138 : 0 : g_return_if_fail (G_IS_TYPE_PLUGIN (plugin));
139 : :
140 : 0 : iface = G_TYPE_PLUGIN_GET_CLASS (plugin);
141 : 0 : iface->unuse_plugin (plugin);
142 : : }
143 : :
144 : : /**
145 : : * g_type_plugin_complete_type_info:
146 : : * @plugin: a #GTypePlugin
147 : : * @g_type: the #GType whose info is completed
148 : : * @info: the #GTypeInfo struct to fill in
149 : : * @value_table: the #GTypeValueTable to fill in
150 : : *
151 : : * Calls the @complete_type_info function from the #GTypePluginClass of @plugin.
152 : : * There should be no need to use this function outside of the GObject
153 : : * type system itself.
154 : : */
155 : : void
156 : 4 : g_type_plugin_complete_type_info (GTypePlugin *plugin,
157 : : GType g_type,
158 : : GTypeInfo *info,
159 : : GTypeValueTable *value_table)
160 : : {
161 : : GTypePluginClass *iface;
162 : :
163 : 4 : g_return_if_fail (G_IS_TYPE_PLUGIN (plugin));
164 : 4 : g_return_if_fail (info != NULL);
165 : 4 : g_return_if_fail (value_table != NULL);
166 : :
167 : 4 : iface = G_TYPE_PLUGIN_GET_CLASS (plugin);
168 : 4 : iface->complete_type_info (plugin,
169 : : g_type,
170 : : info,
171 : : value_table);
172 : : }
173 : :
174 : : /**
175 : : * g_type_plugin_complete_interface_info:
176 : : * @plugin: the #GTypePlugin
177 : : * @instance_type: the #GType of an instantiatable type to which the interface
178 : : * is added
179 : : * @interface_type: the #GType of the interface whose info is completed
180 : : * @info: the #GInterfaceInfo to fill in
181 : : *
182 : : * Calls the @complete_interface_info function from the
183 : : * #GTypePluginClass of @plugin. There should be no need to use this
184 : : * function outside of the GObject type system itself.
185 : : */
186 : : void
187 : 2 : g_type_plugin_complete_interface_info (GTypePlugin *plugin,
188 : : GType instance_type,
189 : : GType interface_type,
190 : : GInterfaceInfo *info)
191 : : {
192 : : GTypePluginClass *iface;
193 : :
194 : 2 : g_return_if_fail (G_IS_TYPE_PLUGIN (plugin));
195 : 2 : g_return_if_fail (info != NULL);
196 : :
197 : 2 : iface = G_TYPE_PLUGIN_GET_CLASS (plugin);
198 : 2 : iface->complete_interface_info (plugin,
199 : : instance_type,
200 : : interface_type,
201 : : info);
202 : : }
|