add reserved fundamental ids for gtk types (for transition time). added
[platform/upstream/glib.git] / gobject / gobject.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1998, 1999, 2000 Tim Janik and 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
15  * Public 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 #include        "gobject.h"
20
21
22 #include        "gvalue.h"
23 #include        "gvaluecollector.h"
24
25
26 #define DEBUG_OBJECTS
27
28
29 /* --- macros --- */
30 #define PARAM_SPEC_PARAM_ID(pspec)      (GPOINTER_TO_UINT (g_param_spec_get_qdata ((pspec), quark_param_id)))
31
32
33 /* --- prototypes --- */
34 extern void     g_object_type_init                      (void);
35 static void     g_object_base_class_init                (GObjectClass   *class);
36 static void     g_object_base_class_finalize            (GObjectClass   *class);
37 static void     g_object_do_class_init                  (GObjectClass   *class);
38 static void     g_object_do_init                        (GObject        *object);
39 static void     g_object_do_queue_param_changed         (GObject        *object,
40                                                          GParamSpec     *pspec);
41 static void     g_object_do_dispatch_param_changed      (GObject        *object,
42                                                          GParamSpec     *pspec);
43 static void     g_object_last_unref                     (GObject        *object);
44 static void     g_object_do_shutdown                    (GObject        *object);
45 static void     g_object_do_finalize                    (GObject        *object);
46
47
48 /* --- variables --- */
49 static GQuark            quark_param_id = 0;
50 static GQuark            quark_param_changed_queue = 0;
51 static GHashTable       *param_spec_hash_table = NULL;
52
53
54 /* --- functions --- */
55 #ifdef  DEBUG_OBJECTS
56 static guint              debug_objects_count = 0;
57 static GHashTable        *debug_objects_ht = NULL;
58 static void
59 debug_objects_foreach (gpointer key,
60                        gpointer value,
61                        gpointer user_data)
62 {
63   GObject *object = value;
64
65   g_message ("[%p] stale %s\tref_count=%u",
66              object,
67              G_OBJECT_TYPE_NAME (object),
68              object->ref_count);
69 }
70 static void
71 debug_objects_atexit (void)
72 {
73   if (debug_objects_ht)
74     {
75       g_message ("stale GObjects: %u", debug_objects_count);
76       g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
77     }
78 }
79 #endif  DEBUG_OBJECTS
80
81 void
82 g_object_type_init (void)       /* sync with glib-gtype.c */
83 {
84   static gboolean initialized = FALSE;
85   static const GTypeFundamentalInfo finfo = {
86     G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE,
87     0       /* n_collect_bytes */,
88     NULL    /* GTypeParamCollector */,
89   };
90   static GTypeInfo info = {
91     sizeof (GObjectClass),
92     (GBaseInitFunc) g_object_base_class_init,
93     (GBaseFinalizeFunc) g_object_base_class_finalize,
94     (GClassInitFunc) g_object_do_class_init,
95     NULL        /* class_destroy */,
96     NULL        /* class_data */,
97     sizeof (GObject),
98     0           /* n_preallocs */,
99     (GInstanceInitFunc) g_object_do_init,
100   };
101   GType type;
102   
103   g_return_if_fail (initialized == FALSE);
104   initialized = TRUE;
105   
106   /* G_TYPE_OBJECT
107    */
108   type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &finfo, &info);
109   g_assert (type == G_TYPE_OBJECT);
110
111 #ifdef  DEBUG_OBJECTS
112   g_atexit (debug_objects_atexit);
113 #endif  DEBUG_OBJECTS
114 }
115
116 static void
117 g_object_base_class_init (GObjectClass *class)
118 {
119   /* reset instance specific fields and methods that don't get inherited */
120   class->n_param_specs = 0;
121   class->param_specs = NULL;
122   class->get_param = NULL;
123   class->set_param = NULL;
124 }
125
126 static void
127 g_object_base_class_finalize (GObjectClass *class)
128 {
129   guint i;
130
131   g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
132   
133   for (i = 0; i < class->n_param_specs; i++)
134     {
135       GParamSpec *pspec = class->param_specs[i];
136       
137       g_param_spec_hash_table_remove (param_spec_hash_table, pspec);
138       g_param_spec_set_qdata (pspec, quark_param_id, NULL);
139       g_param_spec_unref (pspec);
140     }
141   class->n_param_specs = 0;
142   g_free (class->param_specs);
143   class->param_specs = NULL;
144 }
145
146 static void
147 g_object_do_class_init (GObjectClass *class)
148 {
149   quark_param_id = g_quark_from_static_string ("glib-object-param-id");
150   quark_param_changed_queue = g_quark_from_static_string ("glib-object-param-changed-queue");
151   param_spec_hash_table = g_param_spec_hash_table_new ();
152   
153   class->queue_param_changed = g_object_do_queue_param_changed;
154   class->dispatch_param_changed = g_object_do_dispatch_param_changed;
155   class->shutdown = g_object_do_shutdown;
156   class->finalize = g_object_do_finalize;
157 }
158
159 void
160 g_object_class_install_param (GObjectClass *class,
161                               guint         param_id,
162                               GParamSpec   *pspec /* 1 ref_count taken over */)
163 {
164   guint i;
165
166   g_return_if_fail (G_IS_OBJECT_CLASS (class));
167   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
168   if (pspec->flags & G_PARAM_WRITABLE)
169     g_return_if_fail (class->set_param != NULL);
170   if (pspec->flags & G_PARAM_READABLE)
171     g_return_if_fail (class->get_param != NULL);
172   g_return_if_fail (param_id > 0);
173   g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0);  /* paranoid */
174
175   /* expensive paranoia checks ;( */
176   for (i = 0; i < class->n_param_specs; i++)
177     if (PARAM_SPEC_PARAM_ID (class->param_specs[i]) == param_id)
178       {
179         g_warning (G_STRLOC ": class `%s' already contains a parameter `%s' with id %u, "
180                    "cannot install parameter `%s'",
181                    G_OBJECT_CLASS_NAME (class),
182                    class->param_specs[i]->name,
183                    param_id,
184                    pspec->name);
185         return;
186       }
187   if (g_object_class_find_param_spec (class, pspec->name))
188     {
189       g_warning (G_STRLOC ": class `%s' already contains a parameter named `%s'",
190                  G_OBJECT_CLASS_NAME (class),
191                  pspec->name);
192       return;
193     }
194
195   g_param_spec_set_qdata (pspec, quark_param_id, GUINT_TO_POINTER (param_id));
196   g_param_spec_hash_table_insert (param_spec_hash_table, pspec, G_OBJECT_CLASS_TYPE (class));
197   i = class->n_param_specs++;
198   class->param_specs = g_renew (GParamSpec*, class->param_specs, class->n_param_specs);
199   class->param_specs[i] = pspec;
200 }
201
202 GParamSpec*
203 g_object_class_find_param_spec (GObjectClass *class,
204                                 const gchar  *param_name)
205 {
206   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
207   g_return_val_if_fail (param_name != NULL, NULL);
208
209   return g_param_spec_hash_table_lookup (param_spec_hash_table,
210                                          param_name,
211                                          G_OBJECT_CLASS_TYPE (class),
212                                          TRUE, NULL);
213 }
214
215 static void
216 g_object_do_init (GObject *object)
217 {
218   object->ref_count = 1;
219   object->qdata = NULL;
220
221 #ifdef  DEBUG_OBJECTS
222   if (!debug_objects_ht)
223     debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
224   debug_objects_count++;
225   g_hash_table_insert (debug_objects_ht, object, object);
226 #endif  DEBUG_OBJECTS
227 }
228
229 static void
230 g_object_last_unref (GObject *object)
231 {
232   g_return_if_fail (object->ref_count > 0);
233
234   if (object->ref_count == 1)   /* may have been re-referenced meanwhile */
235     G_OBJECT_GET_CLASS (object)->shutdown (object);
236
237   object->ref_count -= 1;
238
239   if (object->ref_count == 0)   /* may have been re-referenced meanwhile */
240     G_OBJECT_GET_CLASS (object)->finalize (object);
241 }
242
243 static void
244 g_object_do_shutdown (GObject *object)
245 {
246   /* this function needs to be always present for unconditional
247    * chaining, we also might add some code here later.
248    * beware though, subclasses may invoke shutdown() arbitrarily.
249    */
250 }
251
252 static void
253 g_object_do_finalize (GObject *object)
254 {
255   g_datalist_clear (&object->qdata);
256   
257 #ifdef  DEBUG_OBJECTS
258   g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
259   
260   g_hash_table_remove (debug_objects_ht, object);
261   debug_objects_count--;
262 #endif  DEBUG_OBJECTS
263   
264   g_type_free_instance ((GTypeInstance*) object);
265 }
266
267 gpointer
268 g_object_new (GType        object_type,
269               const gchar *first_param_name,
270               ...)
271 {
272   GObject *object;
273   va_list var_args;
274
275   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
276
277   va_start (var_args, first_param_name);
278   object = g_object_new_valist (object_type, first_param_name, var_args);
279   va_end (var_args);
280
281   return object;
282 }
283
284 gpointer
285 g_object_new_valist (GType        object_type,
286                      const gchar *first_param_name,
287                      va_list      var_args)
288 {
289   GObject *object;
290
291   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
292
293   object = (GObject*) g_type_create_instance (object_type);
294   if (first_param_name)
295     g_object_set_valist (object, first_param_name, var_args);
296   
297   return object;
298 }
299
300 static void
301 g_object_do_dispatch_param_changed (GObject    *object,
302                                     GParamSpec *pspec)
303 {
304   g_message ("NOTIFICATION: parameter `%s' changed on object `%s'",
305              pspec->name,
306              G_OBJECT_TYPE_NAME (object));
307 }
308
309 static gboolean
310 notify_param_changed_handler (gpointer data)
311 {
312   GObject *object;
313   GObjectClass *class;
314   GSList *slist;
315
316   /* FIXME: need GDK_THREADS lock */
317
318   object = G_OBJECT (data);
319   class = G_OBJECT_GET_CLASS (object);
320   slist = g_datalist_id_get_data (&object->qdata, quark_param_changed_queue);
321
322   /* a reference count is still being held */
323
324   for (; slist; slist = slist->next)
325     if (slist->data)
326       {
327         GParamSpec *pspec = slist->data;
328         
329         slist->data = NULL;
330         class->dispatch_param_changed (object, pspec);
331       }
332   
333   g_datalist_id_set_data (&object->qdata, quark_param_changed_queue, NULL);
334   
335   return FALSE;
336 }
337
338 static void
339 g_object_do_queue_param_changed (GObject    *object,
340                                  GParamSpec *pspec)
341 {
342   GSList *slist, *last = NULL;
343   
344   /* if this is a recursive call on this object (i.e. pspecs are queued
345    * for notification, while param_changed notification is currently in
346    * progress), we simply add them to the queue that is currently being
347    * dispatched. otherwise, we later dispatch parameter changed notification
348    * asyncronously from an idle handler untill the queue is completely empty.
349    */
350   
351   slist = g_datalist_id_get_data (&object->qdata, quark_param_changed_queue);
352   for (; slist; last = slist, slist = last->next)
353     if (slist->data == pspec)
354       return;
355   
356   if (!last)
357     {
358       g_object_ref (object);
359       g_idle_add_full (G_NOTIFY_PRIORITY,
360                        notify_param_changed_handler,
361                        object,
362                        (GDestroyNotify) g_object_unref);
363       g_object_set_qdata_full (object,
364                                quark_param_changed_queue,
365                                g_slist_prepend (NULL, pspec),
366                                (GDestroyNotify) g_slist_free);
367     }
368   else
369     last->next = g_slist_prepend (NULL, pspec);
370 }
371
372 static inline void
373 object_get_param (GObject     *object,
374                   GValue      *value,
375                   GParamSpec  *pspec,
376                   const gchar *trailer)
377 {
378   GObjectClass *class;
379
380   g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type));   /* paranoid */
381
382   class = g_type_class_peek (pspec->owner_type);
383
384   class->get_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
385 }
386
387 static inline void
388 object_set_param (GObject     *object,
389                   GValue      *value,
390                   GParamSpec  *pspec,
391                   const gchar *trailer)
392 {
393   GObjectClass *class;
394
395   g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type));   /* paranoid */
396
397   class = g_type_class_peek (pspec->owner_type);
398
399   class->set_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
400
401   class->queue_param_changed (object, pspec);
402 }
403
404 void
405 g_object_set_valist (GObject     *object,
406                      const gchar *first_param_name,
407                      va_list      var_args)
408 {
409   const gchar *name;
410
411   g_return_if_fail (G_IS_OBJECT (object));
412
413   g_object_ref (object);
414
415   name = first_param_name;
416
417   while (name)
418     {
419       const gchar *trailer = NULL;
420       GValue value = { 0, };
421       GParamSpec *pspec;
422       gchar *error = NULL;
423
424       pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
425                                               name,
426                                               G_OBJECT_TYPE (object),
427                                               TRUE,
428                                               &trailer);
429       if (!pspec)
430         {
431           g_warning ("%s: object class `%s' has no parameter named `%s'",
432                      G_STRLOC,
433                      G_OBJECT_TYPE_NAME (object),
434                      name);
435           break;
436         }
437       if (!(pspec->flags & G_PARAM_WRITABLE))
438         {
439           g_warning ("%s: parameter `%s' of object class `%s' is not writable",
440                      G_STRLOC,
441                      pspec->name,
442                      G_OBJECT_TYPE_NAME (object));
443           break;
444         }
445
446       g_value_init (&value, G_PARAM_SPEC_TYPE (pspec));
447
448       G_PARAM_COLLECT_VALUE (&value, pspec, var_args, &error);
449       if (error)
450         {
451           g_warning ("%s: %s", G_STRLOC, error);
452           g_free (error);
453           
454           /* we purposely leak the value here, it might not be
455            * in a sane state if an error condition occoured
456            */
457           break;
458         }
459
460       object_set_param (object, &value, pspec, trailer);
461       
462       g_value_unset (&value);
463
464       name = va_arg (var_args, gchar*);
465     }
466
467   g_object_unref (object);
468 }
469
470 void
471 g_object_get_valist (GObject     *object,
472                      const gchar *first_param_name,
473                      va_list      var_args)
474 {
475   const gchar *name;
476
477   g_return_if_fail (G_IS_OBJECT (object));
478
479   g_object_ref (object);
480
481   name = first_param_name;
482
483   while (name)
484     {
485       const gchar *trailer = NULL;
486       GValue value = { 0, };
487       GParamSpec *pspec;
488       gchar *error = NULL;
489
490       pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
491                                               name,
492                                               G_OBJECT_TYPE (object),
493                                               TRUE,
494                                               &trailer);
495       if (!pspec)
496         {
497           g_warning ("%s: object class `%s' has no parameter named `%s'",
498                      G_STRLOC,
499                      G_OBJECT_TYPE_NAME (object),
500                      name);
501           break;
502         }
503       if (!(pspec->flags & G_PARAM_READABLE))
504         {
505           g_warning ("%s: parameter `%s' of object class `%s' is not readable",
506                      G_STRLOC,
507                      pspec->name,
508                      G_OBJECT_TYPE_NAME (object));
509           break;
510         }
511
512       g_value_init (&value, G_PARAM_SPEC_TYPE (pspec));
513
514       object_get_param (object, &value, pspec, trailer);
515
516       G_PARAM_LCOPY_VALUE (&value, pspec, var_args, &error);
517       if (error)
518         {
519           g_warning ("%s: %s", G_STRLOC, error);
520           g_free (error);
521           
522           /* we purposely leak the value here, it might not be
523            * in a sane state if an error condition occoured
524            */
525           break;
526         }
527       
528       g_value_unset (&value);
529
530       name = va_arg (var_args, gchar*);
531     }
532
533   g_object_unref (object);
534 }
535
536 void
537 g_object_set (GObject     *object,
538               const gchar *first_param_name,
539               ...)
540 {
541   va_list var_args;
542
543   g_return_if_fail (G_IS_OBJECT (object));
544
545   va_start (var_args, first_param_name);
546   g_object_set_valist (object, first_param_name, var_args);
547   va_end (var_args);
548 }
549
550 void
551 g_object_get (GObject     *object,
552               const gchar *first_param_name,
553               ...)
554 {
555   va_list var_args;
556
557   g_return_if_fail (G_IS_OBJECT (object));
558
559   va_start (var_args, first_param_name);
560   g_object_get_valist (object, first_param_name, var_args);
561   va_end (var_args);
562 }
563
564 void
565 g_object_set_param (GObject      *object,
566                     const gchar  *param_name,
567                     const GValue *value)
568 {
569   GParamSpec *pspec;
570   const gchar *trailer;
571
572   g_return_if_fail (G_IS_OBJECT (object));
573   g_return_if_fail (param_name != NULL);
574   g_return_if_fail (G_IS_VALUE (value));
575
576   g_object_ref (object);
577
578   pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
579                                           param_name,
580                                           G_OBJECT_TYPE (object),
581                                           TRUE,
582                                           &trailer);
583   if (!pspec)
584     g_warning ("%s: object class `%s' has no parameter named `%s'",
585                G_STRLOC,
586                G_OBJECT_TYPE_NAME (object),
587                param_name);
588   else
589     {
590       GValue tmp_value = { 0, };
591
592       /* provide a copy to work from and convert if necessary */
593       g_value_init (&tmp_value, G_PARAM_SPEC_TYPE (pspec));
594
595       if (!g_value_convert (value, &tmp_value) ||
596           g_value_validate (&tmp_value, pspec))
597         g_warning ("%s: can't convert `%s' value to parameter `%s' of type `%s'",
598                    G_STRLOC,
599                    G_VALUE_TYPE_NAME (value),
600                    pspec->name,
601                    G_PARAM_SPEC_TYPE_NAME (pspec));
602       else
603         object_set_param (object, &tmp_value, pspec, trailer);
604       
605       g_value_unset (&tmp_value);
606     }
607   
608   g_object_unref (object);
609 }
610
611 void
612 g_object_get_param (GObject     *object,
613                     const gchar *param_name,
614                     GValue      *value)
615 {
616   GParamSpec *pspec;
617   const gchar *trailer;
618   
619   g_return_if_fail (G_IS_OBJECT (object));
620   g_return_if_fail (param_name != NULL);
621   g_return_if_fail (G_IS_VALUE (value));
622   
623   g_object_ref (object);
624   
625   pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
626                                           param_name,
627                                           G_OBJECT_TYPE (object),
628                                           TRUE,
629                                           &trailer);
630   if (!pspec)
631     g_warning ("%s: object class `%s' has no parameter named `%s'",
632                G_STRLOC,
633                G_OBJECT_TYPE_NAME (object),
634                param_name);
635   else
636     {
637       GValue tmp_value = { 0, };
638       
639       /* provide a copy to work from and later convert if necessary, so
640        * _get_param() implementations need *not* care about freeing values
641        * that might be already set in the parameter to get.
642        * (though, at this point, GValue should exclusively be modified
643        * through the accessor functions anyways)
644        */
645       g_value_init (&tmp_value, G_PARAM_SPEC_TYPE (pspec));
646       
647       if (!g_value_types_exchangable (G_VALUE_TYPE (value), G_PARAM_SPEC_TYPE (pspec)))
648         g_warning ("%s: can't retrive parameter `%s' of type `%s' as value of type `%s'",
649                    G_STRLOC,
650                    pspec->name,
651                    G_PARAM_SPEC_TYPE_NAME (pspec),
652                    G_VALUE_TYPE_NAME (value));
653       else
654         {
655           object_get_param (object, &tmp_value, pspec, trailer);
656           g_value_convert (&tmp_value, value);
657           /* g_value_validate (value, pspec); */
658         }
659       
660       g_value_unset (&tmp_value);
661     }
662   
663   g_object_unref (object);
664 }
665
666 void
667 g_object_queue_param_changed (GObject     *object,
668                               const gchar *param_name)
669 {
670   GParamSpec *pspec;
671   
672   g_return_if_fail (G_IS_OBJECT (object));
673   g_return_if_fail (param_name != NULL);
674
675   pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
676                                           param_name,
677                                           G_OBJECT_TYPE (object),
678                                           TRUE, NULL);
679   if (!pspec)
680     g_warning ("%s: object class `%s' has no parameter named `%s'",
681                G_STRLOC,
682                G_OBJECT_TYPE_NAME (object),
683                param_name);
684   else
685     G_OBJECT_GET_CLASS (object)->queue_param_changed (object, pspec);
686 }
687
688 GObject*
689 g_object_ref (GObject *object)
690 {
691   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
692   g_return_val_if_fail (object->ref_count > 0, NULL);
693
694   object->ref_count += 1;
695
696   return object;
697 }
698
699 void
700 g_object_unref (GObject *object)
701 {
702   g_return_if_fail (G_IS_OBJECT (object));
703   g_return_if_fail (object->ref_count > 0);
704
705   if (object->ref_count > 1)
706     object->ref_count -= 1;
707   else
708     g_object_last_unref (object);
709 }
710
711 gpointer
712 g_object_get_qdata (GObject *object,
713                     GQuark   quark)
714 {
715   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
716
717   return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
718 }
719
720 void
721 g_object_set_qdata (GObject *object,
722                     GQuark   quark,
723                     gpointer data)
724 {
725   g_return_if_fail (G_IS_OBJECT (object));
726   g_return_if_fail (quark > 0);
727   
728   g_datalist_id_set_data (&object->qdata, quark, data);
729 }
730
731 void
732 g_object_set_qdata_full (GObject       *object,
733                          GQuark         quark,
734                          gpointer       data,
735                          GDestroyNotify destroy)
736 {
737   g_return_if_fail (G_IS_OBJECT (object));
738   g_return_if_fail (quark > 0);
739   
740   g_datalist_id_set_data_full (&object->qdata, quark, data, data ? destroy : NULL);
741 }
742
743 gpointer
744 g_object_steal_qdata (GObject *object,
745                       GQuark   quark)
746 {
747   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
748   g_return_val_if_fail (quark > 0, NULL);
749   
750   return g_datalist_id_remove_no_notify (&object->qdata, quark);
751 }