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 |
15 | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | #include "config.h" |
19 | |
20 | #include "gtypeplugin.h" |
21 | |
22 | |
23 | /** |
24 | * SECTION:gtypeplugin |
25 | * @short_description: An interface for dynamically loadable types |
26 | * @see_also: #GTypeModule and g_type_register_dynamic(). |
27 | * @title: GTypePlugin |
28 | * |
29 | * The GObject type system supports dynamic loading of types. |
30 | * The #GTypePlugin interface is used to handle the lifecycle |
31 | * of dynamically loaded types. 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 | * |[<!-- language="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 | * g_type_class_ref() or through g_type_create_instance() (this is |
47 | * being called by g_object_new()) or through one of the above done on |
48 | * a type derived from @new_type_id. |
49 | * |
50 | * 3. This causes the type system to load the type's implementation by |
51 | * calling g_type_plugin_use() and g_type_plugin_complete_type_info() |
52 | * on @new_type_plugin. |
53 | * |
54 | * 4. At some point the type's implementation isn't required anymore, |
55 | * e.g. after g_type_class_unref() or g_type_free_instance() (called |
56 | * 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 g_type_plugin_complete_type_info() and then it calls |
60 | * g_type_plugin_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 | * g_type_plugin_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 | * g_type_plugin_use() and g_type_plugin_complete_type_info() again |
71 | * when the type is needed again. |
72 | * |
73 | * #GTypeModule is an implementation of #GTypePlugin that already |
74 | * 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 | g_type_plugin_get_type (void) |
82 | { |
83 | static GType type_plugin_type = 0; |
84 | |
85 | if (!type_plugin_type) |
86 | { |
87 | 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 | type_plugin_type = g_type_register_static (G_TYPE_INTERFACE, type_name: g_intern_static_string (string: "GTypePlugin" ), info: &type_plugin_info, flags: 0); |
101 | } |
102 | |
103 | 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 | g_type_plugin_use (GTypePlugin *plugin) |
116 | { |
117 | GTypePluginClass *iface; |
118 | |
119 | g_return_if_fail (G_IS_TYPE_PLUGIN (plugin)); |
120 | |
121 | iface = G_TYPE_PLUGIN_GET_CLASS (plugin); |
122 | 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 | g_type_plugin_unuse (GTypePlugin *plugin) |
135 | { |
136 | GTypePluginClass *iface; |
137 | |
138 | g_return_if_fail (G_IS_TYPE_PLUGIN (plugin)); |
139 | |
140 | iface = G_TYPE_PLUGIN_GET_CLASS (plugin); |
141 | 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 | 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 | g_return_if_fail (G_IS_TYPE_PLUGIN (plugin)); |
164 | g_return_if_fail (info != NULL); |
165 | g_return_if_fail (value_table != NULL); |
166 | |
167 | iface = G_TYPE_PLUGIN_GET_CLASS (plugin); |
168 | 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 | 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 | g_return_if_fail (G_IS_TYPE_PLUGIN (plugin)); |
195 | g_return_if_fail (info != NULL); |
196 | |
197 | iface = G_TYPE_PLUGIN_GET_CLASS (plugin); |
198 | iface->complete_interface_info (plugin, |
199 | instance_type, |
200 | interface_type, |
201 | info); |
202 | } |
203 | |