gtypemodule.c revision 07c4d80d55c6b818c3cc4a9535015b0d235b1776
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 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, write to the 16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 * Boston, MA 02111-1307, USA. 18 */ 19 20#include <stdlib.h> 21 22#include "gtypeplugin.h" 23#include "gtypemodule.h" 24#include "gobjectalias.h" 25 26typedef struct _ModuleTypeInfo ModuleTypeInfo; 27typedef struct _ModuleInterfaceInfo ModuleInterfaceInfo; 28 29struct _ModuleTypeInfo 30{ 31 gboolean loaded; 32 GType type; 33 GType parent_type; 34 GTypeInfo info; 35}; 36 37struct _ModuleInterfaceInfo 38{ 39 gboolean loaded; 40 GType instance_type; 41 GType interface_type; 42 GInterfaceInfo info; 43}; 44 45static void g_type_module_use_plugin (GTypePlugin *plugin); 46static void g_type_module_complete_type_info (GTypePlugin *plugin, 47 GType g_type, 48 GTypeInfo *info, 49 GTypeValueTable *value_table); 50static void g_type_module_complete_interface_info (GTypePlugin *plugin, 51 GType instance_type, 52 GType interface_type, 53 GInterfaceInfo *info); 54 55static gpointer parent_class = NULL; 56 57static void 58g_type_module_dispose (GObject *object) 59{ 60 GTypeModule *module = G_TYPE_MODULE (object); 61 62 if (module->type_infos || module->interface_infos) 63 { 64 g_warning (G_STRLOC ": unsolicitated invocation of g_object_dispose() on GTypeModule"); 65 66 g_object_ref (object); 67 } 68 69 G_OBJECT_CLASS (parent_class)->dispose (object); 70} 71 72static void 73g_type_module_finalize (GObject *object) 74{ 75 GTypeModule *module = G_TYPE_MODULE (object); 76 77 g_free (module->name); 78 79 G_OBJECT_CLASS (parent_class)->finalize (object); 80} 81 82static void 83g_type_module_class_init (GTypeModuleClass *class) 84{ 85 GObjectClass *gobject_class = G_OBJECT_CLASS (class); 86 87 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class)); 88 89 gobject_class->dispose = g_type_module_dispose; 90 gobject_class->finalize = g_type_module_finalize; 91} 92 93static void 94g_type_module_iface_init (GTypePluginClass *iface) 95{ 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; 100} 101 102GType 103g_type_module_get_type (void) 104{ 105 static GType type_module_type = 0; 106 107 if (!type_module_type) 108 { 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 */ 119 }; 120 static const GInterfaceInfo iface_info = { 121 (GInterfaceInitFunc) g_type_module_iface_init, 122 NULL, /* interface_finalize */ 123 NULL, /* interface_data */ 124 }; 125 126 type_module_type = g_type_register_static (G_TYPE_OBJECT, g_intern_static_string ("GTypeModule"), &type_module_info, G_TYPE_FLAG_ABSTRACT); 127 128 g_type_add_interface_static (type_module_type, G_TYPE_TYPE_PLUGIN, &iface_info); 129 } 130 131 return type_module_type; 132} 133 134void 135g_type_module_set_name (GTypeModule *module, 136 const gchar *name) 137{ 138 g_return_if_fail (G_IS_TYPE_MODULE (module)); 139 140 g_free (module->name); 141 module->name = g_strdup (name); 142} 143 144static ModuleTypeInfo * 145g_type_module_find_type_info (GTypeModule *module, 146 GType type) 147{ 148 GSList *tmp_list = module->type_infos; 149 while (tmp_list) 150 { 151 ModuleTypeInfo *type_info = tmp_list->data; 152 if (type_info->type == type) 153 return type_info; 154 155 tmp_list = tmp_list->next; 156 } 157 158 return NULL; 159} 160 161static ModuleInterfaceInfo * 162g_type_module_find_interface_info (GTypeModule *module, 163 GType instance_type, 164 GType interface_type) 165{ 166 GSList *tmp_list = module->interface_infos; 167 while (tmp_list) 168 { 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; 173 174 tmp_list = tmp_list->next; 175 } 176 177 return NULL; 178} 179 180gboolean 181g_type_module_use (GTypeModule *module) 182{ 183 g_return_val_if_fail (G_IS_TYPE_MODULE (module), FALSE); 184 185 module->use_count++; 186 if (module->use_count == 1) 187 { 188 GSList *tmp_list; 189 190 if (!G_TYPE_MODULE_GET_CLASS (module)->load (module)) 191 { 192 module->use_count--; 193 return FALSE; 194 } 195 196 tmp_list = module->type_infos; 197 while (tmp_list) 198 { 199 ModuleTypeInfo *type_info = tmp_list->data; 200 if (!type_info->loaded) 201 { 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; 206 } 207 208 tmp_list = tmp_list->next; 209 } 210 } 211 212 return TRUE; 213} 214 215void 216g_type_module_unuse (GTypeModule *module) 217{ 218 g_return_if_fail (G_IS_TYPE_MODULE (module)); 219 g_return_if_fail (module->use_count > 0); 220 221 module->use_count--; 222 223 if (module->use_count == 0) 224 { 225 GSList *tmp_list; 226 227 G_TYPE_MODULE_GET_CLASS (module)->unload (module); 228 229 tmp_list = module->type_infos; 230 while (tmp_list) 231 { 232 ModuleTypeInfo *type_info = tmp_list->data; 233 type_info->loaded = FALSE; 234 235 tmp_list = tmp_list->next; 236 } 237 } 238} 239 240static void 241g_type_module_use_plugin (GTypePlugin *plugin) 242{ 243 GTypeModule *module = G_TYPE_MODULE (plugin); 244 245 if (!g_type_module_use (module)) 246 { 247 g_warning ("Fatal error - Could not reload previously loaded plugin '%s'\n", 248 module->name ? module->name : "(unknown)"); 249 exit (1); 250 } 251} 252 253static void 254g_type_module_complete_type_info (GTypePlugin *plugin, 255 GType g_type, 256 GTypeInfo *info, 257 GTypeValueTable *value_table) 258{ 259 GTypeModule *module = G_TYPE_MODULE (plugin); 260 ModuleTypeInfo *module_type_info = g_type_module_find_type_info (module, g_type); 261 262 *info = module_type_info->info; 263 264 if (module_type_info->info.value_table) 265 *value_table = *module_type_info->info.value_table; 266} 267 268static void 269g_type_module_complete_interface_info (GTypePlugin *plugin, 270 GType instance_type, 271 GType interface_type, 272 GInterfaceInfo *info) 273{ 274 GTypeModule *module = G_TYPE_MODULE (plugin); 275 ModuleInterfaceInfo *module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type); 276 277 *info = module_interface_info->info; 278} 279 280GType 281g_type_module_register_type (GTypeModule *module, 282 GType parent_type, 283 const gchar *type_name, 284 const GTypeInfo *type_info, 285 GTypeFlags flags) 286{ 287 ModuleTypeInfo *module_type_info = NULL; 288 GType type; 289 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); 293 294 type = g_type_from_name (type_name); 295 if (type) 296 { 297 GTypePlugin *old_plugin = g_type_get_plugin (type); 298 299 if (old_plugin != G_TYPE_PLUGIN (module)) 300 { 301 g_warning ("Two different plugins tried to register '%s'.", type_name); 302 return 0; 303 } 304 } 305 306 if (type) 307 { 308 module_type_info = g_type_module_find_type_info (module, type); 309 310 if (module_type_info->parent_type != parent_type) 311 { 312 const gchar *parent_type_name = g_type_name (parent_type); 313 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; 319 } 320 321 if (module_type_info->info.value_table) 322 g_free ((GTypeValueTable *) module_type_info->info.value_table); 323 } 324 else 325 { 326 module_type_info = g_new (ModuleTypeInfo, 1); 327 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); 330 331 module->type_infos = g_slist_prepend (module->type_infos, module_type_info); 332 } 333 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)); 339 340 return module_type_info->type; 341} 342 343void 344g_type_module_add_interface (GTypeModule *module, 345 GType instance_type, 346 GType interface_type, 347 const GInterfaceInfo *interface_info) 348{ 349 ModuleInterfaceInfo *module_interface_info = NULL; 350 351 g_return_if_fail (module != NULL); 352 g_return_if_fail (interface_info != NULL); 353 354 if (g_type_is_a (instance_type, interface_type)) 355 { 356 GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type, 357 interface_type); 358 359 if (!old_plugin) 360 { 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; 364 } 365 else if (old_plugin != G_TYPE_PLUGIN (module)) 366 { 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; 370 } 371 372 module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type); 373 374 g_assert (module_interface_info); 375 } 376 else 377 { 378 module_interface_info = g_new (ModuleInterfaceInfo, 1); 379 380 module_interface_info->instance_type = instance_type; 381 module_interface_info->interface_type = interface_type; 382 383 g_type_add_interface_dynamic (instance_type, interface_type, G_TYPE_PLUGIN (module)); 384 385 module->interface_infos = g_slist_prepend (module->interface_infos, module_interface_info); 386 } 387 388 module_interface_info->loaded = TRUE; 389 module_interface_info->info = *interface_info; 390} 391 392GType 393g_type_module_register_enum (GTypeModule *module, 394 const gchar *name, 395 const GEnumValue *const_static_values) 396{ 397 GTypeInfo enum_type_info = { 0, }; 398 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); 402 403 g_enum_complete_type_info (G_TYPE_ENUM, 404 &enum_type_info, const_static_values); 405 406 return g_type_module_register_type (G_TYPE_MODULE (module), 407 G_TYPE_ENUM, name, &enum_type_info, 0); 408} 409 410GType 411g_type_module_register_flags (GTypeModule *module, 412 const gchar *name, 413 const GFlagsValue *const_static_values) 414{ 415 GTypeInfo flags_type_info = { 0, }; 416 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); 420 421 g_flags_complete_type_info (G_TYPE_FLAGS, 422 &flags_type_info, const_static_values); 423 424 return g_type_module_register_type (G_TYPE_MODULE (module), 425 G_TYPE_FLAGS, name, &flags_type_info, 0); 426} 427 428 429#define __G_TYPE_MODULE_C__ 430#include "gobjectaliasdef.c" 431