fixed a bag full of subtle bugs of immensive screw-up potential in
[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 "gvaluecollector.h"
23 #include "gsignal.h"
24 #include <string.h>
25
26
27 #define DEBUG_OBJECTS
28
29
30 /* --- macros --- */
31 #define PARAM_SPEC_PARAM_ID(pspec)      (GPOINTER_TO_UINT (g_param_spec_get_qdata ((pspec), quark_param_id)))
32
33
34 /* --- prototypes --- */
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 static void     g_value_object_init                     (GValue         *value);
47 static void     g_value_object_free_value               (GValue         *value);
48 static void     g_value_object_copy_value               (const GValue   *src_value,
49                                                          GValue         *dest_value);
50 static gpointer g_value_object_peek_pointer             (const GValue   *value);
51 static gchar*   g_value_object_collect_value            (GValue         *value,
52                                                          guint           nth_value,
53                                                          GType          *collect_type,
54                                                          GTypeCValue    *collect_value);
55 static gchar*   g_value_object_lcopy_value              (const GValue   *value,
56                                                          guint           nth_value,
57                                                          GType          *collect_type,
58                                                          GTypeCValue    *collect_value);
59
60
61 /* --- variables --- */
62 static GQuark            quark_param_id = 0;
63 static GQuark            quark_param_changed_queue = 0;
64 static GQuark            quark_closure_array = 0;
65 static GHashTable       *param_spec_hash_table = NULL;
66
67
68 /* --- functions --- */
69 #ifdef  DEBUG_OBJECTS
70
71 /* We need an actual method for handling debug keys in GLib.
72  * For now, we'll simply use, as a method
73  * 'extern gboolean glib_debug_objects'
74  */
75 gboolean glib_debug_objects = FALSE;
76
77 static guint              debug_objects_count = 0;
78 static GHashTable        *debug_objects_ht = NULL;
79 static void
80 debug_objects_foreach (gpointer key,
81                        gpointer value,
82                        gpointer user_data)
83 {
84   GObject *object = value;
85   
86   g_message ("[%p] stale %s\tref_count=%u",
87              object,
88              G_OBJECT_TYPE_NAME (object),
89              object->ref_count);
90 }
91 static void
92 debug_objects_atexit (void)
93 {
94   if (glib_debug_objects)
95     {
96       if (debug_objects_ht)
97         {
98           g_message ("stale GObjects: %u", debug_objects_count);
99           g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
100         }
101     }
102 }
103 #endif /* DEBUG_OBJECTS */
104
105 void
106 g_object_type_init (void)       /* sync with gtype.c */
107 {
108   static gboolean initialized = FALSE;
109   static const GTypeFundamentalInfo finfo = {
110     G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE,
111   };
112   static GTypeInfo info = {
113     sizeof (GObjectClass),
114     (GBaseInitFunc) g_object_base_class_init,
115     (GBaseFinalizeFunc) g_object_base_class_finalize,
116     (GClassInitFunc) g_object_do_class_init,
117     NULL        /* class_destroy */,
118     NULL        /* class_data */,
119     sizeof (GObject),
120     0           /* n_preallocs */,
121     (GInstanceInitFunc) g_object_do_init,
122     NULL,       /* value_table */
123   };
124   static const GTypeValueTable value_table = {
125     g_value_object_init,          /* value_init */
126     g_value_object_free_value,    /* value_free */
127     g_value_object_copy_value,    /* value_copy */
128     g_value_object_peek_pointer,  /* value_peek_pointer */
129     G_VALUE_COLLECT_POINTER,      /* collect_type */
130     g_value_object_collect_value, /* collect_value */
131     G_VALUE_COLLECT_POINTER,      /* lcopy_type */
132     g_value_object_lcopy_value,   /* lcopy_value */
133   };
134   GType type;
135   
136   g_return_if_fail (initialized == FALSE);
137   initialized = TRUE;
138   
139   /* G_TYPE_OBJECT
140    */
141   info.value_table = &value_table;
142   type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &info, &finfo, 0);
143   g_assert (type == G_TYPE_OBJECT);
144   
145 #ifdef  DEBUG_OBJECTS
146   g_atexit (debug_objects_atexit);
147 #endif /* DEBUG_OBJECTS */
148 }
149
150 static void
151 g_object_base_class_init (GObjectClass *class)
152 {
153   /* reset instance specific fields and methods that don't get inherited */
154   class->n_param_specs = 0;
155   class->param_specs = NULL;
156   class->get_param = NULL;
157   class->set_param = NULL;
158 }
159
160 static void
161 g_object_base_class_finalize (GObjectClass *class)
162 {
163   guint i;
164   
165   g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
166
167   _g_signals_destroy (G_OBJECT_CLASS_TYPE (class));
168   
169   for (i = 0; i < class->n_param_specs; i++)
170     {
171       GParamSpec *pspec = class->param_specs[i];
172       
173       g_param_spec_hash_table_remove (param_spec_hash_table, pspec);
174       g_param_spec_set_qdata (pspec, quark_param_id, NULL);
175       g_param_spec_unref (pspec);
176     }
177   class->n_param_specs = 0;
178   g_free (class->param_specs);
179   class->param_specs = NULL;
180 }
181
182 static void
183 g_object_do_class_init (GObjectClass *class)
184 {
185   quark_param_id = g_quark_from_static_string ("glib-object-param-id");
186   quark_param_changed_queue = g_quark_from_static_string ("glib-object-param-changed-queue");
187   quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
188   param_spec_hash_table = g_param_spec_hash_table_new ();
189   
190   class->queue_param_changed = g_object_do_queue_param_changed;
191   class->dispatch_param_changed = g_object_do_dispatch_param_changed;
192   class->shutdown = g_object_do_shutdown;
193   class->finalize = g_object_do_finalize;
194 }
195
196 void
197 g_object_class_install_param (GObjectClass *class,
198                               guint         param_id,
199                               GParamSpec   *pspec /* 1 ref_count taken over */)
200 {
201   guint i;
202   
203   g_return_if_fail (G_IS_OBJECT_CLASS (class));
204   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
205   if (pspec->flags & G_PARAM_WRITABLE)
206     g_return_if_fail (class->set_param != NULL);
207   if (pspec->flags & G_PARAM_READABLE)
208     g_return_if_fail (class->get_param != NULL);
209   g_return_if_fail (param_id > 0);
210   g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0);  /* paranoid */
211   
212   /* expensive paranoia checks ;( */
213   for (i = 0; i < class->n_param_specs; i++)
214     if (PARAM_SPEC_PARAM_ID (class->param_specs[i]) == param_id)
215       {
216         g_warning (G_STRLOC ": class `%s' already contains a parameter `%s' with id %u, "
217                    "cannot install parameter `%s'",
218                    G_OBJECT_CLASS_NAME (class),
219                    class->param_specs[i]->name,
220                    param_id,
221                    pspec->name);
222         return;
223       }
224   if (g_object_class_find_param_spec (class, pspec->name))
225     {
226       g_warning (G_STRLOC ": class `%s' already contains a parameter named `%s'",
227                  G_OBJECT_CLASS_NAME (class),
228                  pspec->name);
229       return;
230     }
231   
232   g_param_spec_set_qdata (pspec, quark_param_id, GUINT_TO_POINTER (param_id));
233   g_param_spec_hash_table_insert (param_spec_hash_table, pspec, G_OBJECT_CLASS_TYPE (class));
234   i = class->n_param_specs++;
235   class->param_specs = g_renew (GParamSpec*, class->param_specs, class->n_param_specs);
236   class->param_specs[i] = pspec;
237 }
238
239 GParamSpec*
240 g_object_class_find_param_spec (GObjectClass *class,
241                                 const gchar  *param_name)
242 {
243   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
244   g_return_val_if_fail (param_name != NULL, NULL);
245   
246   return g_param_spec_hash_table_lookup (param_spec_hash_table,
247                                          param_name,
248                                          G_OBJECT_CLASS_TYPE (class),
249                                          TRUE, NULL);
250 }
251
252 static void
253 g_object_do_init (GObject *object)
254 {
255   object->ref_count = 1;
256   object->qdata = NULL;
257   
258 #ifdef  DEBUG_OBJECTS
259   if (glib_debug_objects)
260     {
261       if (!debug_objects_ht)
262         debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
263       debug_objects_count++;
264       g_hash_table_insert (debug_objects_ht, object, object);
265     }
266 #endif /* DEBUG_OBJECTS */
267 }
268
269 static void
270 g_object_last_unref (GObject *object)
271 {
272   g_return_if_fail (object->ref_count > 0);
273   
274   if (object->ref_count == 1)   /* may have been re-referenced meanwhile */
275     G_OBJECT_GET_CLASS (object)->shutdown (object);
276   
277   object->ref_count -= 1;
278   
279   if (object->ref_count == 0)   /* may have been re-referenced meanwhile */
280     {
281       G_OBJECT_GET_CLASS (object)->finalize (object);
282       g_type_free_instance ((GTypeInstance*) object);
283     }
284 }
285
286 static void
287 g_object_do_shutdown (GObject *object)
288 {
289   /* this function needs to be always present for unconditional
290    * chaining, we also might add some code here later.
291    * beware though, subclasses may invoke shutdown() arbitrarily.
292    */
293 }
294
295 static void
296 g_object_do_finalize (GObject *object)
297 {
298   g_signal_handlers_destroy (object);
299   g_datalist_clear (&object->qdata);
300   
301 #ifdef  DEBUG_OBJECTS
302   if (glib_debug_objects)
303     {
304       g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
305       
306       g_hash_table_remove (debug_objects_ht, object);
307       debug_objects_count--;
308     }
309 #endif /* DEBUG_OBJECTS */
310 }
311
312 gpointer
313 g_object_new (GType        object_type,
314               const gchar *first_param_name,
315               ...)
316 {
317   GObject *object;
318   va_list var_args;
319   
320   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
321   
322   va_start (var_args, first_param_name);
323   object = g_object_new_valist (object_type, first_param_name, var_args);
324   va_end (var_args);
325   
326   return object;
327 }
328
329 gpointer
330 g_object_new_valist (GType        object_type,
331                      const gchar *first_param_name,
332                      va_list      var_args)
333 {
334   GObject *object;
335   
336   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
337   
338   object = (GObject*) g_type_create_instance (object_type);
339   if (first_param_name)
340     g_object_set_valist (object, first_param_name, var_args);
341   
342   return object;
343 }
344
345 static void
346 g_object_do_dispatch_param_changed (GObject    *object,
347                                     GParamSpec *pspec)
348 {
349 /*  g_message ("NOTIFICATION: parameter `%s' changed on object `%s'",
350              pspec->name,
351              G_OBJECT_TYPE_NAME (object));*/
352 }
353
354 static gboolean
355 notify_param_changed_handler (gpointer data)
356 {
357   GObject *object;
358   GObjectClass *class;
359   GSList *slist;
360   
361   /* FIXME: need GDK_THREADS lock */
362   
363   object = G_OBJECT (data);
364   class = G_OBJECT_GET_CLASS (object);
365   slist = g_datalist_id_get_data (&object->qdata, quark_param_changed_queue);
366   
367   /* a reference count is still being held */
368   
369   for (; slist; slist = slist->next)
370     if (slist->data)
371       {
372         GParamSpec *pspec = slist->data;
373         
374         slist->data = NULL;
375         class->dispatch_param_changed (object, pspec);
376       }
377   
378   g_datalist_id_set_data (&object->qdata, quark_param_changed_queue, NULL);
379   
380   return FALSE;
381 }
382
383 static void
384 g_object_do_queue_param_changed (GObject    *object,
385                                  GParamSpec *pspec)
386 {
387   GSList *slist, *last = NULL;
388   
389   /* if this is a recursive call on this object (i.e. pspecs are queued
390    * for notification, while param_changed notification is currently in
391    * progress), we simply add them to the queue that is currently being
392    * dispatched. otherwise, we later dispatch parameter changed notification
393    * asyncronously from an idle handler untill the queue is completely empty.
394    */
395   
396   slist = g_datalist_id_get_data (&object->qdata, quark_param_changed_queue);
397   for (; slist; last = slist, slist = last->next)
398     if (slist->data == pspec)
399       return;
400   
401   if (!last)
402     {
403       g_object_ref (object);
404       g_idle_add_full (G_NOTIFY_PRIORITY,
405                        notify_param_changed_handler,
406                        object,
407                        (GDestroyNotify) g_object_unref);
408       g_object_set_qdata_full (object,
409                                quark_param_changed_queue,
410                                g_slist_prepend (NULL, pspec),
411                                (GDestroyNotify) g_slist_free);
412     }
413   else
414     last->next = g_slist_prepend (NULL, pspec);
415 }
416
417 static inline void
418 object_get_param (GObject     *object,
419                   GValue      *value,
420                   GParamSpec  *pspec,
421                   const gchar *trailer)
422 {
423   GObjectClass *class;
424   
425   g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type));   /* paranoid */
426   
427   class = g_type_class_peek (pspec->owner_type);
428   
429   class->get_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
430 }
431
432 static inline void
433 object_set_param (GObject     *object,
434                   GValue      *value,
435                   GParamSpec  *pspec,
436                   const gchar *trailer)
437 {
438   GObjectClass *class;
439   
440   g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type));   /* paranoid */
441   
442   class = g_type_class_peek (pspec->owner_type);
443   
444   class->set_param (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
445   
446   class->queue_param_changed (object, pspec);
447 }
448
449 void
450 g_object_set_valist (GObject     *object,
451                      const gchar *first_param_name,
452                      va_list      var_args)
453 {
454   const gchar *name;
455   
456   g_return_if_fail (G_IS_OBJECT (object));
457   
458   g_object_ref (object);
459   
460   name = first_param_name;
461   
462   while (name)
463     {
464       const gchar *trailer = NULL;
465       GValue value = { 0, };
466       GParamSpec *pspec;
467       gchar *error = NULL;
468       
469       pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
470                                               name,
471                                               G_OBJECT_TYPE (object),
472                                               TRUE,
473                                               &trailer);
474       if (!pspec)
475         {
476           g_warning ("%s: object class `%s' has no parameter named `%s'",
477                      G_STRLOC,
478                      G_OBJECT_TYPE_NAME (object),
479                      name);
480           break;
481         }
482       if (!(pspec->flags & G_PARAM_WRITABLE))
483         {
484           g_warning ("%s: parameter `%s' of object class `%s' is not writable",
485                      G_STRLOC,
486                      pspec->name,
487                      G_OBJECT_TYPE_NAME (object));
488           break;
489         }
490       
491       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
492       
493       G_VALUE_COLLECT (&value, var_args, &error);
494       if (error)
495         {
496           g_warning ("%s: %s", G_STRLOC, error);
497           g_free (error);
498           
499           /* we purposely leak the value here, it might not be
500            * in a sane state if an error condition occoured
501            */
502           break;
503         }
504       
505       object_set_param (object, &value, pspec, trailer);
506       
507       g_value_unset (&value);
508       
509       name = va_arg (var_args, gchar*);
510     }
511   
512   g_object_unref (object);
513 }
514
515 void
516 g_object_get_valist (GObject     *object,
517                      const gchar *first_param_name,
518                      va_list      var_args)
519 {
520   const gchar *name;
521   
522   g_return_if_fail (G_IS_OBJECT (object));
523   
524   g_object_ref (object);
525   
526   name = first_param_name;
527   
528   while (name)
529     {
530       const gchar *trailer = NULL;
531       GValue value = { 0, };
532       GParamSpec *pspec;
533       gchar *error = NULL;
534       
535       pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
536                                               name,
537                                               G_OBJECT_TYPE (object),
538                                               TRUE,
539                                               &trailer);
540       if (!pspec)
541         {
542           g_warning ("%s: object class `%s' has no parameter named `%s'",
543                      G_STRLOC,
544                      G_OBJECT_TYPE_NAME (object),
545                      name);
546           break;
547         }
548       if (!(pspec->flags & G_PARAM_READABLE))
549         {
550           g_warning ("%s: parameter `%s' of object class `%s' is not readable",
551                      G_STRLOC,
552                      pspec->name,
553                      G_OBJECT_TYPE_NAME (object));
554           break;
555         }
556       
557       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
558       
559       object_get_param (object, &value, pspec, trailer);
560       
561       G_VALUE_LCOPY (&value, var_args, &error);
562       if (error)
563         {
564           g_warning ("%s: %s", G_STRLOC, error);
565           g_free (error);
566           
567           /* we purposely leak the value here, it might not be
568            * in a sane state if an error condition occoured
569            */
570           break;
571         }
572       
573       g_value_unset (&value);
574       
575       name = va_arg (var_args, gchar*);
576     }
577   
578   g_object_unref (object);
579 }
580
581 void
582 g_object_set (GObject     *object,
583               const gchar *first_param_name,
584               ...)
585 {
586   va_list var_args;
587   
588   g_return_if_fail (G_IS_OBJECT (object));
589   
590   va_start (var_args, first_param_name);
591   g_object_set_valist (object, first_param_name, var_args);
592   va_end (var_args);
593 }
594
595 void
596 g_object_get (GObject     *object,
597               const gchar *first_param_name,
598               ...)
599 {
600   va_list var_args;
601   
602   g_return_if_fail (G_IS_OBJECT (object));
603   
604   va_start (var_args, first_param_name);
605   g_object_get_valist (object, first_param_name, var_args);
606   va_end (var_args);
607 }
608
609 void
610 g_object_set_param (GObject      *object,
611                     const gchar  *param_name,
612                     const GValue *value)
613 {
614   GParamSpec *pspec;
615   const gchar *trailer;
616   
617   g_return_if_fail (G_IS_OBJECT (object));
618   g_return_if_fail (param_name != NULL);
619   g_return_if_fail (G_IS_VALUE (value));
620   
621   g_object_ref (object);
622   
623   pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
624                                           param_name,
625                                           G_OBJECT_TYPE (object),
626                                           TRUE,
627                                           &trailer);
628   if (!pspec)
629     g_warning ("%s: object class `%s' has no parameter named `%s'",
630                G_STRLOC,
631                G_OBJECT_TYPE_NAME (object),
632                param_name);
633   else
634     {
635       GValue tmp_value = { 0, };
636       
637       /* provide a copy to work from and convert if necessary */
638       g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
639       
640       if (!g_value_convert (value, &tmp_value) ||
641           g_param_value_validate (pspec, &tmp_value))
642         g_warning ("%s: cannot convert `%s' value to parameter `%s' value of type `%s'",
643                    G_STRLOC,
644                    G_VALUE_TYPE_NAME (value),
645                    pspec->name,
646                    g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
647       else
648         object_set_param (object, &tmp_value, pspec, trailer);
649       
650       g_value_unset (&tmp_value);
651     }
652   
653   g_object_unref (object);
654 }
655
656 void
657 g_object_get_param (GObject     *object,
658                     const gchar *param_name,
659                     GValue      *value)
660 {
661   GParamSpec *pspec;
662   const gchar *trailer;
663   
664   g_return_if_fail (G_IS_OBJECT (object));
665   g_return_if_fail (param_name != NULL);
666   g_return_if_fail (G_IS_VALUE (value));
667   
668   g_object_ref (object);
669   
670   pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
671                                           param_name,
672                                           G_OBJECT_TYPE (object),
673                                           TRUE,
674                                           &trailer);
675   if (!pspec)
676     g_warning ("%s: object class `%s' has no parameter named `%s'",
677                G_STRLOC,
678                G_OBJECT_TYPE_NAME (object),
679                param_name);
680   else
681     {
682       GValue tmp_value = { 0, };
683       
684       /* provide a copy to work from and later convert if necessary, so
685        * _get_param() implementations need *not* care about freeing values
686        * that might be already set in the parameter to get.
687        * (though, at this point, GValue should exclusively be modified
688        * through the accessor functions anyways)
689        */
690       g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
691       
692       if (!g_value_types_exchangable (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
693         g_warning ("%s: can't retrive parameter `%s' value of type `%s' as value of type `%s'",
694                    G_STRLOC,
695                    pspec->name,
696                    g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
697                    G_VALUE_TYPE_NAME (value));
698       else
699         {
700           object_get_param (object, &tmp_value, pspec, trailer);
701           g_value_convert (&tmp_value, value);
702           /* g_value_validate (value, pspec); */
703         }
704       
705       g_value_unset (&tmp_value);
706     }
707   
708   g_object_unref (object);
709 }
710
711 void
712 g_object_queue_param_changed (GObject     *object,
713                               const gchar *param_name)
714 {
715   GParamSpec *pspec;
716   
717   g_return_if_fail (G_IS_OBJECT (object));
718   g_return_if_fail (param_name != NULL);
719   
720   pspec = g_param_spec_hash_table_lookup (param_spec_hash_table,
721                                           param_name,
722                                           G_OBJECT_TYPE (object),
723                                           TRUE, NULL);
724   if (!pspec)
725     g_warning ("%s: object class `%s' has no parameter named `%s'",
726                G_STRLOC,
727                G_OBJECT_TYPE_NAME (object),
728                param_name);
729   else
730     G_OBJECT_GET_CLASS (object)->queue_param_changed (object, pspec);
731 }
732
733 GObject*
734 g_object_ref (GObject *object)
735 {
736   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
737   g_return_val_if_fail (object->ref_count > 0, NULL);
738   
739   object->ref_count += 1;
740   
741   return object;
742 }
743
744 void
745 g_object_unref (GObject *object)
746 {
747   g_return_if_fail (G_IS_OBJECT (object));
748   g_return_if_fail (object->ref_count > 0);
749   
750   if (object->ref_count > 1)
751     object->ref_count -= 1;
752   else
753     g_object_last_unref (object);
754 }
755
756 gpointer
757 g_object_get_qdata (GObject *object,
758                     GQuark   quark)
759 {
760   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
761   
762   return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
763 }
764
765 void
766 g_object_set_qdata (GObject *object,
767                     GQuark   quark,
768                     gpointer data)
769 {
770   g_return_if_fail (G_IS_OBJECT (object));
771   g_return_if_fail (quark > 0);
772   
773   g_datalist_id_set_data (&object->qdata, quark, data);
774 }
775
776 void
777 g_object_set_qdata_full (GObject       *object,
778                          GQuark         quark,
779                          gpointer       data,
780                          GDestroyNotify destroy)
781 {
782   g_return_if_fail (G_IS_OBJECT (object));
783   g_return_if_fail (quark > 0);
784   
785   g_datalist_id_set_data_full (&object->qdata, quark, data, data ? destroy : NULL);
786 }
787
788 gpointer
789 g_object_steal_qdata (GObject *object,
790                       GQuark   quark)
791 {
792   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
793   g_return_val_if_fail (quark > 0, NULL);
794   
795   return g_datalist_id_remove_no_notify (&object->qdata, quark);
796 }
797
798 static void
799 g_value_object_init (GValue *value)
800 {
801   value->data[0].v_pointer = NULL;
802 }
803
804 static void
805 g_value_object_free_value (GValue *value)
806 {
807   if (value->data[0].v_pointer)
808     g_object_unref (value->data[0].v_pointer);
809 }
810
811 static void
812 g_value_object_copy_value (const GValue *src_value,
813                            GValue       *dest_value)
814 {
815   if (src_value->data[0].v_pointer)
816     dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
817   else
818     dest_value->data[0].v_pointer = NULL;
819 }
820
821 static gpointer
822 g_value_object_peek_pointer (const GValue *value)
823 {
824   return value->data[0].v_pointer;
825 }
826
827 static gchar*
828 g_value_object_collect_value (GValue      *value,
829                               guint        nth_value,
830                               GType       *collect_type,
831                               GTypeCValue *collect_value)
832 {
833   if (collect_value->v_pointer)
834     {
835       GObject *object = collect_value->v_pointer;
836       
837       if (object->g_type_instance.g_class == NULL)
838         return g_strconcat ("invalid unclassed object pointer for value type `",
839                             G_VALUE_TYPE_NAME (value),
840                             "'",
841                             NULL);
842       else if (!g_type_is_a (G_OBJECT_TYPE (object), G_VALUE_TYPE (value)))
843         return g_strconcat ("invalid object type `",
844                             G_OBJECT_TYPE_NAME (object),
845                             "' for value type `",
846                             G_VALUE_TYPE_NAME (value),
847                             "'",
848                             NULL);
849       value->data[0].v_pointer = g_object_ref (object);
850     }
851   else
852     value->data[0].v_pointer = NULL;
853   
854   *collect_type = 0;
855   return NULL;
856 }
857
858 static gchar*
859 g_value_object_lcopy_value (const GValue *value,
860                             guint         nth_value,
861                             GType        *collect_type,
862                             GTypeCValue  *collect_value)
863 {
864   GObject **object_p = collect_value->v_pointer;
865   
866   if (!object_p)
867     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
868   
869   *object_p = value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
870   
871   *collect_type = 0;
872   return NULL;
873 }
874
875 void
876 g_value_set_object (GValue  *value,
877                     GObject *v_object)
878 {
879   g_return_if_fail (G_IS_VALUE_OBJECT (value));
880   if (v_object)
881     g_return_if_fail (G_IS_OBJECT (v_object));
882   
883   if (value->data[0].v_pointer)
884     g_object_unref (value->data[0].v_pointer);
885   value->data[0].v_pointer = v_object;
886   if (value->data[0].v_pointer)
887     g_object_ref (value->data[0].v_pointer);
888 }
889
890 GObject*
891 g_value_get_object (const GValue *value)
892 {
893   g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
894   
895   return value->data[0].v_pointer;
896 }
897
898 GObject*
899 g_value_dup_object (const GValue *value)
900 {
901   g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
902   
903   return value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
904 }
905
906 typedef struct {
907   GObject  *object;
908   guint     n_closures;
909   GClosure *closures[1]; /* flexible array */
910 } CArray;
911
912 static void
913 object_remove_closure (gpointer  data,
914                        GClosure *closure)
915 {
916   GObject *object = data;
917   CArray *carray = g_object_get_qdata (object, quark_closure_array);
918   guint i;
919   
920   for (i = 0; i < carray->n_closures; i++)
921     if (carray->closures[i] == closure)
922       {
923         carray->n_closures--;
924         if (i < carray->n_closures)
925           carray->closures[i] = carray->closures[carray->n_closures];
926         return;
927       }
928   g_assert_not_reached ();
929 }
930
931 static void
932 destroy_closure_array (gpointer data)
933 {
934   CArray *carray = data;
935   GObject *object = carray->object;
936   guint i, n = carray->n_closures;
937   
938   for (i = 0; i < n; i++)
939     {
940       GClosure *closure = carray->closures[i];
941       
942       /* removing object_remove_closure() upfront is probably faster than
943        * letting it fiddle with quark_closure_array which is empty anyways
944        */
945       g_closure_remove_inotify (closure, object, object_remove_closure);
946       g_closure_invalidate (closure);
947     }
948   g_free (carray);
949 }
950
951 void
952 g_object_watch_closure (GObject  *object,
953                         GClosure *closure)
954 {
955   CArray *carray;
956   
957   g_return_if_fail (G_IS_OBJECT (object));
958   g_return_if_fail (closure != NULL);
959   g_return_if_fail (closure->is_invalid == FALSE);
960   g_return_if_fail (closure->in_marshal == FALSE);
961   g_return_if_fail (object->ref_count > 0);     /* this doesn't work on finalizing objects */
962   
963   g_closure_add_inotify (closure, object, object_remove_closure);
964   g_closure_add_marshal_guards (closure,
965                                 object, (GClosureNotify) g_object_ref,
966                                 object, (GClosureNotify) g_object_unref);
967   carray = g_object_steal_qdata (object, quark_closure_array);
968   if (!carray)
969     {
970       carray = g_renew (CArray, NULL, 1);
971       carray->object = object;
972       carray->n_closures = 1;
973       carray->closures[0] = closure;
974       g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
975     }
976   else
977     {
978       guint i = carray->n_closures++;
979       
980       carray = g_realloc (carray, sizeof (*carray) + sizeof (carray->closures[0]) * i);
981       carray->closures[i] = closure;
982       g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
983     }
984 }
985
986 GClosure*
987 g_closure_new_object (guint    sizeof_closure,
988                       GObject *object)
989 {
990   GClosure *closure;
991
992   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
993   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
994
995   closure = g_closure_new_simple (sizeof_closure, object);
996   g_object_watch_closure (object, closure);
997
998   return closure;
999 }
1000
1001 GClosure*
1002 g_cclosure_new_object (GCallback callback_func,
1003                        gpointer  _object)
1004 {
1005   GObject *object = _object;
1006   GClosure *closure;
1007
1008   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1009   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
1010   g_return_val_if_fail (callback_func != NULL, NULL);
1011
1012   closure = g_cclosure_new (callback_func, object, NULL);
1013   g_object_watch_closure (object, closure);
1014
1015   return closure;
1016 }
1017
1018 GClosure*
1019 g_cclosure_new_object_swap (GCallback callback_func,
1020                             gpointer  _object)
1021 {
1022   GObject *object = _object;
1023   GClosure *closure;
1024
1025   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1026   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
1027   g_return_val_if_fail (callback_func != NULL, NULL);
1028
1029   closure = g_cclosure_new_swap (callback_func, object, NULL);
1030   g_object_watch_closure (object, closure);
1031
1032   return closure;
1033 }