Add a testcase for the previous fix.
[glib.git] / gobject / gtypemodule.c
blob4ecb6ca03069ce4daedaef87f46d62c145cddc7f
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2000 Red Hat, Inc.
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.
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.
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.
20 #include <stdlib.h>
22 #include "gobjectalias.h"
23 #include "gtypeplugin.h"
24 #include "gtypemodule.h"
26 typedef struct _ModuleTypeInfo ModuleTypeInfo;
27 typedef struct _ModuleInterfaceInfo ModuleInterfaceInfo;
29 struct _ModuleTypeInfo
31 gboolean loaded;
32 GType type;
33 GType parent_type;
34 GTypeInfo info;
37 struct _ModuleInterfaceInfo
39 gboolean loaded;
40 GType instance_type;
41 GType interface_type;
42 GInterfaceInfo info;
45 static void g_type_module_use_plugin (GTypePlugin *plugin);
46 static void g_type_module_complete_type_info (GTypePlugin *plugin,
47 GType g_type,
48 GTypeInfo *info,
49 GTypeValueTable *value_table);
50 static void g_type_module_complete_interface_info (GTypePlugin *plugin,
51 GType instance_type,
52 GType interface_type,
53 GInterfaceInfo *info);
55 static gpointer parent_class = NULL;
57 static void
58 g_type_module_dispose (GObject *object)
60 GTypeModule *module = G_TYPE_MODULE (object);
62 if (module->type_infos || module->interface_infos)
64 g_warning (G_STRLOC ": unsolicitated invocation of g_object_dispose() on GTypeModule");
66 g_object_ref (object);
69 G_OBJECT_CLASS (parent_class)->dispose (object);
72 static void
73 g_type_module_finalize (GObject *object)
75 GTypeModule *module = G_TYPE_MODULE (object);
77 g_free (module->name);
79 G_OBJECT_CLASS (parent_class)->finalize (object);
82 static void
83 g_type_module_class_init (GTypeModuleClass *class)
85 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
87 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class));
89 gobject_class->dispose = g_type_module_dispose;
90 gobject_class->finalize = g_type_module_finalize;
93 static void
94 g_type_module_iface_init (GTypePluginClass *iface)
96 iface->use_plugin = g_type_module_use_plugin;
97 iface->unuse_plugin = (void (*) (GTypePlugin *))g_type_module_unuse;
98 iface->complete_type_info = g_type_module_complete_type_info;
99 iface->complete_interface_info = g_type_module_complete_interface_info;
102 GType
103 g_type_module_get_type (void)
105 static GType type_module_type = 0;
107 if (!type_module_type)
109 static const GTypeInfo type_module_info = {
110 sizeof (GTypeModuleClass),
111 NULL, /* base_init */
112 NULL, /* base_finalize */
113 (GClassInitFunc) g_type_module_class_init,
114 NULL, /* class_finalize */
115 NULL, /* class_data */
116 sizeof (GTypeModule),
117 0, /* n_preallocs */
118 NULL, /* instance_init */
120 static const GInterfaceInfo iface_info = {
121 (GInterfaceInitFunc) g_type_module_iface_init,
122 NULL, /* interface_finalize */
123 NULL, /* interface_data */
126 type_module_type = g_type_register_static (G_TYPE_OBJECT, "GTypeModule", &type_module_info, G_TYPE_FLAG_ABSTRACT);
128 g_type_add_interface_static (type_module_type, G_TYPE_TYPE_PLUGIN, &iface_info);
131 return type_module_type;
134 void
135 g_type_module_set_name (GTypeModule *module,
136 const gchar *name)
138 g_return_if_fail (G_IS_TYPE_MODULE (module));
140 g_free (module->name);
141 module->name = g_strdup (name);
144 static ModuleTypeInfo *
145 g_type_module_find_type_info (GTypeModule *module,
146 GType type)
148 GSList *tmp_list = module->type_infos;
149 while (tmp_list)
151 ModuleTypeInfo *type_info = tmp_list->data;
152 if (type_info->type == type)
153 return type_info;
155 tmp_list = tmp_list->next;
158 return NULL;
161 static ModuleInterfaceInfo *
162 g_type_module_find_interface_info (GTypeModule *module,
163 GType instance_type,
164 GType interface_type)
166 GSList *tmp_list = module->interface_infos;
167 while (tmp_list)
169 ModuleInterfaceInfo *interface_info = tmp_list->data;
170 if (interface_info->instance_type == instance_type &&
171 interface_info->interface_type == interface_type)
172 return interface_info;
174 tmp_list = tmp_list->next;
177 return NULL;
180 gboolean
181 g_type_module_use (GTypeModule *module)
183 g_return_val_if_fail (G_IS_TYPE_MODULE (module), FALSE);
185 module->use_count++;
186 if (module->use_count == 1)
188 GSList *tmp_list;
190 if (!G_TYPE_MODULE_GET_CLASS (module)->load (module))
192 module->use_count--;
193 return FALSE;
196 tmp_list = module->type_infos;
197 while (tmp_list)
199 ModuleTypeInfo *type_info = tmp_list->data;
200 if (!type_info->loaded)
202 g_warning ("plugin '%s' failed to register type '%s'\n",
203 module->name ? module->name : "(unknown)",
204 g_type_name (type_info->type));
205 return FALSE;
208 tmp_list = tmp_list->next;
212 return TRUE;
215 void
216 g_type_module_unuse (GTypeModule *module)
218 g_return_if_fail (G_IS_TYPE_MODULE (module));
219 g_return_if_fail (module->use_count > 0);
221 module->use_count--;
223 if (module->use_count == 0)
225 GSList *tmp_list;
227 G_TYPE_MODULE_GET_CLASS (module)->unload (module);
229 tmp_list = module->type_infos;
230 while (tmp_list)
232 ModuleTypeInfo *type_info = tmp_list->data;
233 type_info->loaded = FALSE;
235 tmp_list = tmp_list->next;
240 static void
241 g_type_module_use_plugin (GTypePlugin *plugin)
243 GTypeModule *module = G_TYPE_MODULE (plugin);
245 if (!g_type_module_use (module))
247 g_warning ("Fatal error - Could not reload previously loaded plugin '%s'\n",
248 module->name ? module->name : "(unknown)");
249 exit (1);
253 static void
254 g_type_module_complete_type_info (GTypePlugin *plugin,
255 GType g_type,
256 GTypeInfo *info,
257 GTypeValueTable *value_table)
259 GTypeModule *module = G_TYPE_MODULE (plugin);
260 ModuleTypeInfo *module_type_info = g_type_module_find_type_info (module, g_type);
262 *info = module_type_info->info;
264 if (module_type_info->info.value_table)
265 *value_table = *module_type_info->info.value_table;
268 static void
269 g_type_module_complete_interface_info (GTypePlugin *plugin,
270 GType instance_type,
271 GType interface_type,
272 GInterfaceInfo *info)
274 GTypeModule *module = G_TYPE_MODULE (plugin);
275 ModuleInterfaceInfo *module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
277 *info = module_interface_info->info;
280 GType
281 g_type_module_register_type (GTypeModule *module,
282 GType parent_type,
283 const gchar *type_name,
284 const GTypeInfo *type_info,
285 GTypeFlags flags)
287 ModuleTypeInfo *module_type_info = NULL;
288 GType type;
290 g_return_val_if_fail (module != NULL, 0);
291 g_return_val_if_fail (type_name != NULL, 0);
292 g_return_val_if_fail (type_info != NULL, 0);
294 type = g_type_from_name (type_name);
295 if (type)
297 GTypePlugin *old_plugin = g_type_get_plugin (type);
299 if (old_plugin != G_TYPE_PLUGIN (module))
301 g_warning ("Two different plugins tried to register '%s'.", type_name);
302 return 0;
306 if (type)
308 module_type_info = g_type_module_find_type_info (module, type);
310 if (module_type_info->parent_type != parent_type)
312 const gchar *parent_type_name = g_type_name (parent_type);
314 g_warning ("Type '%s' recreated with different parent type.\n"
315 "(was '%s', now '%s')", type_name,
316 g_type_name (module_type_info->parent_type),
317 parent_type_name ? parent_type_name : "(unknown)");
318 return 0;
321 if (module_type_info->info.value_table)
322 g_free ((GTypeValueTable *) module_type_info->info.value_table);
324 else
326 module_type_info = g_new (ModuleTypeInfo, 1);
328 module_type_info->parent_type = parent_type;
329 module_type_info->type = g_type_register_dynamic (parent_type, type_name, G_TYPE_PLUGIN (module), flags);
331 module->type_infos = g_slist_prepend (module->type_infos, module_type_info);
334 module_type_info->loaded = TRUE;
335 module_type_info->info = *type_info;
336 if (type_info->value_table)
337 module_type_info->info.value_table = g_memdup (type_info->value_table,
338 sizeof (type_info->value_table));
340 return module_type_info->type;
343 void
344 g_type_module_add_interface (GTypeModule *module,
345 GType instance_type,
346 GType interface_type,
347 const GInterfaceInfo *interface_info)
349 ModuleInterfaceInfo *module_interface_info = NULL;
351 g_return_if_fail (module != NULL);
352 g_return_if_fail (interface_info != NULL);
354 if (g_type_is_a (instance_type, interface_type))
356 GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type,
357 interface_type);
359 if (!old_plugin)
361 g_warning ("Interface '%s' for '%s' was previously registered statically or for a parent type.",
362 g_type_name (interface_type), g_type_name (instance_type));
363 return;
365 else if (old_plugin != G_TYPE_PLUGIN (module))
367 g_warning ("Two different plugins tried to register interface '%s' for '%s'.",
368 g_type_name (interface_type), g_type_name (instance_type));
369 return;
372 module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
374 g_assert (module_interface_info);
376 else
378 module_interface_info = g_new (ModuleInterfaceInfo, 1);
380 module_interface_info->instance_type = instance_type;
381 module_interface_info->interface_type = interface_type;
383 g_type_add_interface_dynamic (instance_type, interface_type, G_TYPE_PLUGIN (module));
385 module->interface_infos = g_slist_prepend (module->interface_infos, module_interface_info);
388 module_interface_info->loaded = TRUE;
389 module_interface_info->info = *interface_info;
392 GType
393 g_type_module_register_enum (GTypeModule *module,
394 const gchar *name,
395 const GEnumValue *const_static_values)
397 GTypeInfo enum_type_info = { 0, };
399 g_return_val_if_fail (G_IS_TYPE_MODULE (module), 0);
400 g_return_val_if_fail (name != NULL, 0);
401 g_return_val_if_fail (const_static_values != NULL, 0);
403 g_enum_complete_type_info (G_TYPE_ENUM,
404 &enum_type_info, const_static_values);
406 return g_type_module_register_type (G_TYPE_MODULE (module),
407 G_TYPE_ENUM, name, &enum_type_info, 0);
410 GType
411 g_type_module_register_flags (GTypeModule *module,
412 const gchar *name,
413 const GFlagsValue *const_static_values)
415 GTypeInfo flags_type_info = { 0, };
417 g_return_val_if_fail (G_IS_TYPE_MODULE (module), 0);
418 g_return_val_if_fail (name != NULL, 0);
419 g_return_val_if_fail (const_static_values != NULL, 0);
421 g_flags_complete_type_info (G_TYPE_FLAGS,
422 &flags_type_info, const_static_values);
424 return g_type_module_register_type (G_TYPE_MODULE (module),
425 G_TYPE_FLAGS, name, &flags_type_info, 0);