source: trunk/third/glib2/gobject/gtypemodule.c @ 20721

Revision 20721, 10.4 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20720, which included commits to RCS files with non-trunk default branches.
Line 
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
25typedef struct _ModuleTypeInfo ModuleTypeInfo;
26typedef struct _ModuleInterfaceInfo ModuleInterfaceInfo;
27
28struct _ModuleTypeInfo
29{
30  gboolean  loaded;
31  GType     type;
32  GType     parent_type;
33  GTypeInfo info;
34};
35
36struct _ModuleInterfaceInfo
37{
38  gboolean       loaded;
39  GType          instance_type;
40  GType          interface_type;
41  GInterfaceInfo info;
42};
43
44static void g_type_module_use_plugin              (GTypePlugin     *plugin);
45static void g_type_module_complete_type_info      (GTypePlugin     *plugin,
46                                                   GType            g_type,
47                                                   GTypeInfo       *info,
48                                                   GTypeValueTable *value_table);
49static void g_type_module_complete_interface_info (GTypePlugin     *plugin,
50                                                   GType            instance_type,
51                                                   GType            interface_type,
52                                                   GInterfaceInfo  *info);
53 
54static gpointer parent_class = NULL;
55
56static void
57g_type_module_dispose (GObject *object)
58{
59  GTypeModule *module = G_TYPE_MODULE (object);
60 
61  if (module->type_infos || module->interface_infos)
62    {
63      g_warning (G_STRLOC ": unsolicitated invocation of g_object_dispose() on GTypeModule");
64             
65      g_object_ref (object);
66    }
67
68  G_OBJECT_CLASS (parent_class)->dispose (object);
69}
70
71static void
72g_type_module_finalize (GObject *object)
73{
74  GTypeModule *module = G_TYPE_MODULE (object);
75
76  g_free (module->name);
77
78  G_OBJECT_CLASS (parent_class)->finalize (object);
79}
80
81static void
82g_type_module_class_init (GTypeModuleClass *class)
83{
84  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
85
86  parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class));
87 
88  gobject_class->dispose = g_type_module_dispose;
89  gobject_class->finalize = g_type_module_finalize;
90}
91
92static void
93g_type_module_iface_init (GTypePluginClass *iface)
94{
95  iface->use_plugin = g_type_module_use_plugin;
96  iface->unuse_plugin = (void (*) (GTypePlugin *))g_type_module_unuse;
97  iface->complete_type_info = g_type_module_complete_type_info;
98  iface->complete_interface_info = g_type_module_complete_interface_info;
99}
100
101GType
102g_type_module_get_type (void)
103{
104  static GType type_module_type = 0;
105
106  if (!type_module_type)
107    {
108      static const GTypeInfo type_module_info = {
109        sizeof (GTypeModuleClass),
110        NULL,           /* base_init */
111        NULL,           /* base_finalize */
112        (GClassInitFunc) g_type_module_class_init,
113        NULL,           /* class_finalize */
114        NULL,           /* class_data */
115        sizeof (GTypeModule),
116        0,              /* n_preallocs */
117        NULL,           /* instance_init */
118      };
119      static const GInterfaceInfo iface_info = {
120        (GInterfaceInitFunc) g_type_module_iface_init,
121        NULL,               /* interface_finalize */
122        NULL,               /* interface_data */
123      };
124
125      type_module_type = g_type_register_static (G_TYPE_OBJECT, "GTypeModule", &type_module_info, G_TYPE_FLAG_ABSTRACT);
126
127      g_type_add_interface_static (type_module_type, G_TYPE_TYPE_PLUGIN, &iface_info);
128    }
129 
130  return type_module_type;
131}
132
133void
134g_type_module_set_name (GTypeModule  *module,
135                        const gchar  *name)
136{
137  g_return_if_fail (G_IS_TYPE_MODULE (module));
138
139  g_free (module->name);
140  module->name = g_strdup (name);
141}
142
143static ModuleTypeInfo *
144g_type_module_find_type_info (GTypeModule *module,
145                              GType        type)
146{
147  GSList *tmp_list = module->type_infos;
148  while (tmp_list)
149    {
150      ModuleTypeInfo *type_info = tmp_list->data;
151      if (type_info->type == type)
152        return type_info;
153     
154      tmp_list = tmp_list->next;
155    }
156
157  return NULL;
158}
159
160static ModuleInterfaceInfo *
161g_type_module_find_interface_info (GTypeModule *module,
162                                   GType        instance_type,
163                                   GType        interface_type)
164{
165  GSList *tmp_list = module->interface_infos;
166  while (tmp_list)
167    {
168      ModuleInterfaceInfo *interface_info = tmp_list->data;
169      if (interface_info->instance_type == instance_type &&
170          interface_info->interface_type == interface_type)
171        return interface_info;
172     
173      tmp_list = tmp_list->next;
174    }
175
176  return NULL;
177}
178
179gboolean
180g_type_module_use (GTypeModule *module)
181{
182  g_return_val_if_fail (G_IS_TYPE_MODULE (module), FALSE);
183
184  module->use_count++;
185  if (module->use_count == 1)
186    {
187      GSList *tmp_list;
188     
189      if (!G_TYPE_MODULE_GET_CLASS (module)->load (module))
190        {
191          module->use_count--;
192          return FALSE;
193        }
194
195      tmp_list = module->type_infos;
196      while (tmp_list)
197        {
198          ModuleTypeInfo *type_info = tmp_list->data;
199          if (!type_info->loaded)
200            {
201              g_warning ("plugin '%s' failed to register type '%s'\n",
202                         module->name ? module->name : "(unknown)",
203                         g_type_name (type_info->type));
204              return FALSE;
205            }
206         
207          tmp_list = tmp_list->next;
208        }
209    }
210 
211  return TRUE;
212}
213
214void
215g_type_module_unuse (GTypeModule *module)
216{
217  g_return_if_fail (G_IS_TYPE_MODULE (module));
218  g_return_if_fail (module->use_count > 0);
219
220  module->use_count--;
221
222  if (module->use_count == 0)
223    {
224      GSList *tmp_list;
225
226      G_TYPE_MODULE_GET_CLASS (module)->unload (module);
227
228      tmp_list = module->type_infos;
229      while (tmp_list)
230        {
231          ModuleTypeInfo *type_info = tmp_list->data;
232          type_info->loaded = FALSE;
233
234          tmp_list = tmp_list->next;
235        }
236    }
237}
238       
239static void
240g_type_module_use_plugin (GTypePlugin *plugin)
241{
242  GTypeModule *module = G_TYPE_MODULE (plugin);
243
244  if (!g_type_module_use (module))
245    {
246      g_warning ("Fatal error - Could not reload previously loaded plugin '%s'\n",
247                 module->name ? module->name : "(unknown)");
248      exit (1);
249    }
250}
251
252static void
253g_type_module_complete_type_info (GTypePlugin     *plugin,
254                                  GType            g_type,
255                                  GTypeInfo       *info,
256                                  GTypeValueTable *value_table)
257{
258  GTypeModule *module = G_TYPE_MODULE (plugin);
259  ModuleTypeInfo *module_type_info = g_type_module_find_type_info (module, g_type);
260
261  *info = module_type_info->info;
262 
263  if (module_type_info->info.value_table)
264    *value_table = *module_type_info->info.value_table;
265}
266
267static void
268g_type_module_complete_interface_info (GTypePlugin    *plugin,
269                                       GType           instance_type,
270                                       GType           interface_type,
271                                       GInterfaceInfo *info)
272{
273  GTypeModule *module = G_TYPE_MODULE (plugin);
274  ModuleInterfaceInfo *module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
275
276  *info = module_interface_info->info;
277}
278
279GType
280g_type_module_register_type (GTypeModule     *module,
281                             GType            parent_type,
282                             const gchar     *type_name,
283                             const GTypeInfo *type_info,
284                             GTypeFlags       flags)
285{
286  ModuleTypeInfo *module_type_info = NULL;
287  GType type;
288 
289  g_return_val_if_fail (module != NULL, 0);
290  g_return_val_if_fail (type_name != NULL, 0);
291  g_return_val_if_fail (type_info != NULL, 0);
292
293  type = g_type_from_name (type_name);
294  if (type)
295    {
296      GTypePlugin *old_plugin = g_type_get_plugin (type);
297
298      if (old_plugin != G_TYPE_PLUGIN (module))
299        {
300          g_warning ("Two different plugins tried to register '%s'.", type_name);
301          return 0;
302        }
303    }
304
305  if (type)
306    {
307      module_type_info = g_type_module_find_type_info (module, type);
308
309      if (module_type_info->parent_type != parent_type)
310        {
311          const gchar *parent_type_name = g_type_name (parent_type);
312         
313          g_warning ("Type '%s' recreated with different parent type.\n"
314                     "(was '%s', now '%s')", type_name,
315                     g_type_name (module_type_info->parent_type),
316                     parent_type_name ? parent_type_name : "(unknown)");
317          return 0;
318        }
319
320      if (module_type_info->info.value_table)
321        g_free ((GTypeValueTable *) module_type_info->info.value_table);
322    }
323  else
324    {
325      module_type_info = g_new (ModuleTypeInfo, 1);
326     
327      module_type_info->parent_type = parent_type;
328      module_type_info->type = g_type_register_dynamic (parent_type, type_name, G_TYPE_PLUGIN (module), flags);
329     
330      module->type_infos = g_slist_prepend (module->type_infos, module_type_info);
331    }
332
333  module_type_info->loaded = TRUE;
334  module_type_info->info = *type_info;
335  if (type_info->value_table)
336    module_type_info->info.value_table = g_memdup (type_info->value_table,
337                                                   sizeof (type_info->value_table));
338
339  return module_type_info->type;
340}
341
342void
343g_type_module_add_interface (GTypeModule          *module,
344                             GType                 instance_type,
345                             GType                 interface_type,
346                             const GInterfaceInfo *interface_info)
347{
348  ModuleInterfaceInfo *module_interface_info = NULL;
349 
350  g_return_if_fail (module != NULL);
351  g_return_if_fail (interface_info != NULL);
352
353  if (g_type_is_a (instance_type, interface_type))
354    {
355      GTypePlugin *old_plugin = g_type_interface_get_plugin (instance_type,
356                                                             interface_type);
357
358      if (!old_plugin)
359        {
360          g_warning ("Interface '%s' for '%s' was previously registered statically or for a parent type.",
361                     g_type_name (interface_type), g_type_name (instance_type));
362          return;
363        }
364      else if (old_plugin != G_TYPE_PLUGIN (module))
365        {
366          g_warning ("Two different plugins tried to register interface '%s' for '%s'.",
367                     g_type_name (interface_type), g_type_name (instance_type));
368          return;
369        }
370     
371      module_interface_info = g_type_module_find_interface_info (module, instance_type, interface_type);
372
373      g_assert (module_interface_info);
374    }
375  else
376    {
377      module_interface_info = g_new (ModuleInterfaceInfo, 1);
378     
379      module_interface_info->instance_type = instance_type;
380      module_interface_info->interface_type = interface_type;
381     
382      g_type_add_interface_dynamic (instance_type, interface_type, G_TYPE_PLUGIN (module));
383     
384      module->interface_infos = g_slist_prepend (module->interface_infos, module_interface_info);
385    }
386 
387  module_interface_info->loaded = TRUE;
388  module_interface_info->info = *interface_info;
389}
Note: See TracBrowser for help on using the repository browser.