use g_signal_newc
[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        "gparamspecs.h"
25 #include        "gvaluetypes.h"
26 #include        <string.h>
27
28
29 #define PREALLOC_CPARAMS        (8)
30 #define DEBUG_OBJECTS
31
32
33 /* --- macros --- */
34 #define PARAM_SPEC_PARAM_ID(pspec)      (GPOINTER_TO_UINT (g_param_spec_get_qdata ((pspec), quark_property_id)))
35
36
37 /* --- signals --- */
38 enum {
39   PROPERTIES_CHANGED,
40   NOTIFY,
41   LAST_SIGNAL
42 };
43
44
45 /* --- properties --- */
46 enum {
47   PROP_NONE,
48   PROP_DATA,
49   PROP_SIGNAL,
50   PROP_SWAPPED_SIGNAL,
51   PROP_SIGNAL_AFTER,
52   PROP_SWAPPED_SIGNAL_AFTER
53 };
54
55
56 /* --- typedefs --- */
57 typedef struct _NotifyQueue NotifyQueue;
58
59
60 /* --- prototypes --- */
61 static void     g_object_base_class_init                (GObjectClass   *class);
62 static void     g_object_base_class_finalize            (GObjectClass   *class);
63 static void     g_object_do_class_init                  (GObjectClass   *class);
64 static void     g_object_init                           (GObject        *object);
65 static GObject* g_object_constructor                    (GType                  type,
66                                                          guint                  n_construct_properties,
67                                                          GObjectConstructParam *construct_params);
68 static void     g_object_last_unref                     (GObject        *object);
69 static void     g_object_shutdown                       (GObject        *object);
70 static void     g_object_finalize                       (GObject        *object);
71 static void     g_object_do_set_property                (GObject        *object,
72                                                          guint           property_id,
73                                                          const GValue   *value,
74                                                          GParamSpec     *pspec,
75                                                          const gchar    *trailer);
76 static void     g_object_do_get_property                (GObject        *object,
77                                                          guint           property_id,
78                                                          GValue         *value,
79                                                          GParamSpec     *pspec,
80                                                          const gchar    *trailer);
81 static void     g_value_object_init                     (GValue         *value);
82 static void     g_value_object_free_value               (GValue         *value);
83 static void     g_value_object_copy_value               (const GValue   *src_value,
84                                                          GValue         *dest_value);
85 static gpointer g_value_object_peek_pointer             (const GValue   *value);
86 static gchar*   g_value_object_collect_value            (GValue         *value,
87                                                          guint           nth_value,
88                                                          GType          *collect_type,
89                                                          GTypeCValue    *collect_value);
90 static gchar*   g_value_object_lcopy_value              (const GValue   *value,
91                                                          guint           nth_value,
92                                                          GType          *collect_type,
93                                                          GTypeCValue    *collect_value);
94 static void     g_object_dispatch_properties_changed    (GObject        *object,
95                                                          guint           n_pspecs,
96                                                          GParamSpec    **pspecs);
97 static void     g_object_properties_changed             (GObject        *object,
98                                                          guint           n_pspecs,
99                                                          GParamSpec    **pspecs);
100 static void     g_object_notify_property_changed        (GObject        *object,
101                                                          GParamSpec     *pspec);
102 static inline NotifyQueue* object_freeze_notifies       (GObject        *object);
103 static inline void         object_queue_property        (GObject        *object,
104                                                          GParamSpec     *pspec,
105                                                          NotifyQueue    *nqueue);
106 static inline void         object_thaw_notifies         (GObject        *object,
107                                                          NotifyQueue    *nqueue);
108 static inline void         object_get_property          (GObject        *object,
109                                                          GValue         *value,
110                                                          GParamSpec     *pspec,
111                                                          const gchar    *trailer);
112 static inline void         object_set_property          (GObject        *object,
113                                                          GValue         *value,
114                                                          GParamSpec     *pspec,
115                                                          const gchar    *trailer,
116                                                          NotifyQueue    *nqueue);
117
118
119 /* --- structures --- */
120 struct _NotifyQueue
121 {
122   GSList *pspecs;
123   guint   n_pspecs;
124   guint   freeze_count;
125 };
126
127
128 /* --- variables --- */
129 static GQuark          quark_notify_queue = 0;
130 static GQuark          quark_property_id = 0;
131 static GQuark          quark_closure_array = 0;
132 static GParamSpecPool *pspec_pool = NULL;
133 static gulong          gobject_signals[LAST_SIGNAL] = { 0, };
134
135
136 /* --- functions --- */
137 #ifdef  DEBUG_OBJECTS
138
139 /* We need an actual method for handling debug keys in GLib.
140  * For now, we'll simply use, as a method
141  * 'extern gboolean glib_debug_objects'
142  */
143 gboolean glib_debug_objects = FALSE;
144
145 static guint              debug_objects_count = 0;
146 static GHashTable        *debug_objects_ht = NULL;
147 static void
148 debug_objects_foreach (gpointer key,
149                        gpointer value,
150                        gpointer user_data)
151 {
152   GObject *object = value;
153   
154   g_message ("[%p] stale %s\tref_count=%u",
155              object,
156              G_OBJECT_TYPE_NAME (object),
157              object->ref_count);
158 }
159 static void
160 debug_objects_atexit (void)
161 {
162   if (glib_debug_objects)
163     {
164       if (debug_objects_ht)
165         {
166           g_message ("stale GObjects: %u", debug_objects_count);
167           g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
168         }
169     }
170 }
171 #endif /* DEBUG_OBJECTS */
172
173 void
174 g_object_type_init (void)       /* sync with gtype.c */
175 {
176   static gboolean initialized = FALSE;
177   static const GTypeFundamentalInfo finfo = {
178     G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE,
179   };
180   static GTypeInfo info = {
181     sizeof (GObjectClass),
182     (GBaseInitFunc) g_object_base_class_init,
183     (GBaseFinalizeFunc) g_object_base_class_finalize,
184     (GClassInitFunc) g_object_do_class_init,
185     NULL        /* class_destroy */,
186     NULL        /* class_data */,
187     sizeof (GObject),
188     0           /* n_preallocs */,
189     (GInstanceInitFunc) g_object_init,
190     NULL,       /* value_table */
191   };
192   static const GTypeValueTable value_table = {
193     g_value_object_init,          /* value_init */
194     g_value_object_free_value,    /* value_free */
195     g_value_object_copy_value,    /* value_copy */
196     g_value_object_peek_pointer,  /* value_peek_pointer */
197     G_VALUE_COLLECT_POINTER,      /* collect_type */
198     g_value_object_collect_value, /* collect_value */
199     G_VALUE_COLLECT_POINTER,      /* lcopy_type */
200     g_value_object_lcopy_value,   /* lcopy_value */
201   };
202   GType type;
203   
204   g_return_if_fail (initialized == FALSE);
205   initialized = TRUE;
206   
207   /* G_TYPE_OBJECT
208    */
209   info.value_table = &value_table;
210   type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &info, &finfo, 0);
211   g_assert (type == G_TYPE_OBJECT);
212   
213 #ifdef  DEBUG_OBJECTS
214   g_atexit (debug_objects_atexit);
215 #endif /* DEBUG_OBJECTS */
216 }
217
218 static void
219 g_object_base_class_init (GObjectClass *class)
220 {
221   GObjectClass *pclass = g_type_class_peek_parent (class);
222
223   /* reset instance specific fields and methods that don't get inherited */
224   class->n_property_specs = 0;
225   class->property_specs = NULL;
226   class->construct_properties = pclass ? g_slist_copy (pclass->construct_properties) : NULL;
227   class->get_property = NULL;
228   class->set_property = NULL;
229 }
230
231 static void
232 g_object_base_class_finalize (GObjectClass *class)
233 {
234   guint i;
235   
236   g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
237
238   _g_signals_destroy (G_OBJECT_CLASS_TYPE (class));
239
240   g_slist_free (class->construct_properties);
241   class->construct_properties = NULL;
242   for (i = 0; i < class->n_property_specs; i++)
243     {
244       GParamSpec *pspec = class->property_specs[i];
245       
246       g_param_spec_pool_remove (pspec_pool, pspec);
247       g_param_spec_set_qdata (pspec, quark_property_id, NULL);
248       g_param_spec_unref (pspec);
249     }
250   class->n_property_specs = 0;
251   g_free (class->property_specs);
252   class->property_specs = NULL;
253 }
254
255 static void
256 g_object_do_class_init (GObjectClass *class)
257 {
258   quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
259   quark_property_id = g_quark_from_static_string ("GObject-property-id");
260   quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
261   pspec_pool = g_param_spec_pool_new (TRUE);
262   
263   class->constructor = g_object_constructor;
264   class->set_property = g_object_do_set_property;
265   class->get_property = g_object_do_get_property;
266   class->shutdown = g_object_shutdown;
267   class->finalize = g_object_finalize;
268   class->dispatch_properties_changed = g_object_dispatch_properties_changed;
269   class->properties_changed = g_object_properties_changed;
270   class->notify = g_object_notify_property_changed;
271
272   g_object_class_install_property (class,
273                                    PROP_DATA,
274                                    g_param_spec_pointer ("data", "Named Data",
275                                                          "Named anonymous pointers",
276                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
277   g_object_class_install_property (class,
278                                    PROP_SIGNAL,
279                                    g_param_spec_ccallback ("signal", "Signal Connection",
280                                                            "Signal connection consisting of a callback function "
281                                                            "and a data pointer",
282                                                            G_PARAM_WRITABLE));
283   g_object_class_install_property (class,
284                                    PROP_SWAPPED_SIGNAL,
285                                    g_param_spec_ccallback ("swapped_signal", "Swapped Signal Connection",
286                                                            "Signal connection consisting of a callback function "
287                                                            "and a data pointer",
288                                                            G_PARAM_WRITABLE));
289   g_object_class_install_property (class,
290                                    PROP_SIGNAL_AFTER,
291                                    g_param_spec_ccallback ("signal_after", "Signal After Connection",
292                                                            "Signal connection consisting of a callback function "
293                                                            "and a data pointer",
294                                                            G_PARAM_WRITABLE));
295   g_object_class_install_property (class,
296                                    PROP_SWAPPED_SIGNAL_AFTER,
297                                    g_param_spec_ccallback ("swapped_signal_after", "Swapped Signal After Connection",
298                                                            "Signal connection consisting of a callback function "
299                                                            "and a data pointer",
300                                                            G_PARAM_WRITABLE));
301   gobject_signals[PROPERTIES_CHANGED] =
302     g_signal_newc ("properties_changed",
303                    G_TYPE_FROM_CLASS (class),
304                    G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
305                    G_STRUCT_OFFSET (GObjectClass, properties_changed),
306                    NULL, /* accumulator */
307                    g_cclosure_marshal_VOID__UINT_POINTER,
308                    G_TYPE_NONE,
309                    2, G_TYPE_UINT, G_TYPE_POINTER);
310   gobject_signals[NOTIFY] =
311     g_signal_newc ("notify",
312                    G_TYPE_FROM_CLASS (class),
313                    G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
314                    G_STRUCT_OFFSET (GObjectClass, notify),
315                    NULL, /* accumulator */
316                    g_cclosure_marshal_VOID__PARAM,
317                    G_TYPE_NONE,
318                    1, G_TYPE_PARAM);
319 }
320
321 void
322 g_object_class_install_property (GObjectClass *class,
323                                  guint         property_id,
324                                  GParamSpec   *pspec)
325 {
326   guint i;
327   
328   g_return_if_fail (G_IS_OBJECT_CLASS (class));
329   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
330   if (pspec->flags & G_PARAM_WRITABLE)
331     g_return_if_fail (class->set_property != NULL);
332   if (pspec->flags & G_PARAM_READABLE)
333     g_return_if_fail (class->get_property != NULL);
334   g_return_if_fail (property_id > 0);
335   g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0);  /* paranoid */
336   if (pspec->flags & G_PARAM_CONSTRUCT)
337     g_return_if_fail ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
338   if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
339     g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
340
341   /* expensive paranoia checks ;( */
342   for (i = 0; i < class->n_property_specs; i++)
343     if (PARAM_SPEC_PARAM_ID (class->property_specs[i]) == property_id)
344       {
345         g_warning (G_STRLOC ": class `%s' already contains a property `%s' with id %u, "
346                    "cannot install property `%s'",
347                    G_OBJECT_CLASS_NAME (class),
348                    class->property_specs[i]->name,
349                    property_id,
350                    pspec->name);
351         return;
352       }
353   if (g_param_spec_pool_lookup (pspec_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE, NULL))
354     {
355       g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
356                  G_OBJECT_CLASS_NAME (class),
357                  pspec->name);
358       return;
359     }
360
361   g_param_spec_ref (pspec);
362   g_param_spec_sink (pspec);
363   g_param_spec_set_qdata (pspec, quark_property_id, GUINT_TO_POINTER (property_id));
364   g_param_spec_pool_insert (pspec_pool, pspec, G_OBJECT_CLASS_TYPE (class));
365   i = class->n_property_specs++;
366   class->property_specs = g_renew (GParamSpec*, class->property_specs, class->n_property_specs);
367   class->property_specs[i] = pspec;
368   if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
369     class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
370
371   /* for property overrides of construct poperties, we have to get rid
372    * of the overidden inherited construct property
373    */
374   pspec = g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type_parent (G_OBJECT_CLASS_TYPE (class)), TRUE, NULL);
375   if (pspec && pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
376     class->construct_properties = g_slist_remove (class->construct_properties, pspec);
377 }
378
379 GParamSpec*
380 g_object_class_find_property (GObjectClass *class,
381                               const gchar  *property_name)
382 {
383   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
384   g_return_val_if_fail (property_name != NULL, NULL);
385   
386   return g_param_spec_pool_lookup (pspec_pool,
387                                    property_name,
388                                    G_OBJECT_CLASS_TYPE (class),
389                                    TRUE, NULL);
390 }
391
392 static void
393 free_notify_queue (gpointer data)
394 {
395   NotifyQueue *nqueue = data;
396   
397   g_slist_free (nqueue->pspecs);
398   g_free (nqueue);
399 }
400
401 static inline NotifyQueue*
402 object_freeze_notifies (GObject *object)
403 {
404   NotifyQueue *nqueue;
405
406   nqueue = g_object_get_qdata (object, quark_notify_queue);
407   if (!nqueue)
408     {
409       nqueue = g_new0 (NotifyQueue, 1);
410       g_object_set_qdata_full (object, quark_notify_queue, nqueue, free_notify_queue);
411     }
412   nqueue->freeze_count++;
413
414   return nqueue;
415 }
416
417 static inline void
418 object_queue_property (GObject     *object,
419                        GParamSpec  *pspec,
420                        NotifyQueue *nqueue)
421 {
422   /* we will dedup later */
423   nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
424   nqueue->n_pspecs++;
425 }
426
427 static void
428 g_object_init (GObject *object)
429 {
430   object->ref_count = 1;
431   g_datalist_init (&object->qdata);
432   
433   /* freeze object's notification queue, g_object_new_valist() takes care of that */
434   object_freeze_notifies (object);
435
436 #ifdef  DEBUG_OBJECTS
437   if (glib_debug_objects)
438     {
439       if (!debug_objects_ht)
440         debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
441       debug_objects_count++;
442       g_hash_table_insert (debug_objects_ht, object, object);
443     }
444 #endif /* DEBUG_OBJECTS */
445 }
446
447 static void
448 g_object_do_set_property (GObject      *object,
449                           guint         property_id,
450                           const GValue *value,
451                           GParamSpec   *pspec,
452                           const gchar  *trailer)
453 {
454   guint i = 0;
455   
456   switch (property_id)
457     {
458       gboolean swapped, after;
459       gpointer callback, data;
460     case PROP_DATA:
461       g_return_if_fail (trailer != NULL);
462
463       g_object_set_data (object, trailer, g_value_get_pointer (value));
464       break;
465     case PROP_SWAPPED_SIGNAL_AFTER:
466       i++;
467     case PROP_SIGNAL_AFTER:
468       i++;
469     case PROP_SWAPPED_SIGNAL:
470       i++;
471     case PROP_SIGNAL:
472       after = i > 2;
473       swapped = i & 1;
474       g_return_if_fail (trailer != NULL);
475
476       g_value_get_ccallback (value, &callback, &data);
477       g_signal_connect_data (object, trailer,
478                              callback, data, NULL,
479                              swapped, after);
480       break;
481     default:
482       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
483       break;
484     }
485 }
486
487 static void
488 g_object_do_get_property (GObject     *object,
489                           guint        property_id,
490                           GValue      *value,
491                           GParamSpec  *pspec,
492                           const gchar *trailer)
493 {
494   switch (property_id)
495     {
496     case PROP_DATA:
497       g_return_if_fail (trailer != NULL);
498
499       g_value_set_pointer (value, g_object_get_data (object, trailer));
500       break;
501     default:
502       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
503       break;
504     }
505 }
506
507 static void
508 g_object_last_unref (GObject *object)
509 {
510   g_return_if_fail (object->ref_count > 0);
511   
512   if (object->ref_count == 1)   /* may have been re-referenced meanwhile */
513     G_OBJECT_GET_CLASS (object)->shutdown (object);
514   
515   object->ref_count -= 1;
516   
517   if (object->ref_count == 0)   /* may have been re-referenced meanwhile */
518     {
519       G_OBJECT_GET_CLASS (object)->finalize (object);
520 #ifdef  DEBUG_OBJECTS
521       if (glib_debug_objects && debug_objects_ht)
522         g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
523 #endif /* DEBUG_OBJECTS */
524       g_type_free_instance ((GTypeInstance*) object);
525     }
526 }
527
528 static void
529 g_object_shutdown (GObject *object)
530 {
531   /* this function needs to be always present for unconditional
532    * chaining, we also might add some code here later.
533    * beware though, subclasses may invoke shutdown() arbitrarily.
534    */
535 }
536
537 static void
538 g_object_finalize (GObject *object)
539 {
540   g_signal_handlers_destroy (object);
541   g_datalist_clear (&object->qdata);
542   
543 #ifdef  DEBUG_OBJECTS
544   if (glib_debug_objects)
545     {
546       g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
547       
548       g_hash_table_remove (debug_objects_ht, object);
549       debug_objects_count--;
550     }
551 #endif /* DEBUG_OBJECTS */
552 }
553
554 static inline void
555 object_thaw_notifies (GObject     *object,
556                       NotifyQueue *nqueue)
557 {
558   GParamSpec **pspecs;
559   GSList *slist;
560   guint n_pspecs = 0;
561   
562   nqueue->freeze_count--;
563   if (nqueue->freeze_count)
564     return;
565   g_return_if_fail (object->ref_count > 0);
566   
567   pspecs = g_new (GParamSpec*, nqueue->n_pspecs);
568   for (slist = nqueue->pspecs; slist; slist = slist->next)
569     {
570       GParamSpec *pspec = slist->data;
571       gint i = 0;
572       
573       /* dedup, make pspecs in the list unique */
574     redo_dedup_check:
575       if (pspecs[i] == pspec)
576         continue;
577       if (++i < n_pspecs)
578         goto redo_dedup_check;
579       
580       pspecs[n_pspecs++] = pspec;
581     }
582   g_object_set_qdata (object, quark_notify_queue, NULL);
583   
584   if (n_pspecs)
585     G_OBJECT_GET_CLASS (object)->dispatch_properties_changed (object, n_pspecs, pspecs);
586   
587   g_free (pspecs);
588 }
589
590 static void
591 g_object_dispatch_properties_changed (GObject     *object,
592                                       guint        n_pspecs,
593                                       GParamSpec **pspecs)
594 {
595   g_signal_emit (object, gobject_signals[PROPERTIES_CHANGED], 0, n_pspecs, pspecs);
596 }
597
598 static void
599 g_object_properties_changed (GObject     *object,
600                              guint        n_pspecs,
601                              GParamSpec **pspecs)
602 {
603   guint i;
604
605   for (i = 0; i < n_pspecs; i++)
606     g_signal_emit (object, gobject_signals[NOTIFY], g_quark_from_string (pspecs[i]->name), pspecs[i]);
607 }
608
609 static void
610 g_object_notify_property_changed (GObject    *object,
611                                   GParamSpec *pspec)
612 {
613   if (0) /* FIXME */
614     g_message ("NOTIFICATION: property `%s' changed on object `%s'",
615                pspec->name,
616                G_OBJECT_TYPE_NAME (object));
617 }
618
619 void
620 g_object_freeze_notify (GObject *object)
621 {
622   g_return_if_fail (G_IS_OBJECT (object));
623   if (!object->ref_count)
624     return;
625
626   g_object_ref (object);
627   object_freeze_notifies (object);
628   g_object_unref (object);
629 }
630
631 void
632 g_object_notify (GObject     *object,
633                  const gchar *property_name)
634 {
635   GParamSpec *pspec;
636   
637   g_return_if_fail (G_IS_OBJECT (object));
638   g_return_if_fail (property_name != NULL);
639   if (!object->ref_count)
640     return;
641   
642   g_object_ref (object);
643   pspec = g_param_spec_pool_lookup (pspec_pool,
644                                     property_name,
645                                     G_OBJECT_TYPE (object),
646                                     TRUE, NULL);
647   if (!pspec)
648     g_warning ("%s: object class `%s' has no property named `%s'",
649                G_STRLOC,
650                G_OBJECT_TYPE_NAME (object),
651                property_name);
652   else
653     {
654       NotifyQueue *nqueue = object_freeze_notifies (object);
655
656       object_queue_property (object, pspec, nqueue);
657       object_thaw_notifies (object, nqueue);
658     }
659   g_object_unref (object);
660 }
661
662 void
663 g_object_thaw_notify (GObject *object)
664 {
665   NotifyQueue *nqueue;
666   
667   g_return_if_fail (G_IS_OBJECT (object));
668   if (!object->ref_count)
669     return;
670   
671   g_object_ref (object);
672   nqueue = g_object_get_qdata (object, quark_notify_queue);
673   if (!nqueue || !nqueue->freeze_count)
674     g_warning (G_STRLOC ": property-changed notification for %s(%p) is not frozen",
675                G_OBJECT_TYPE_NAME (object), object);
676   else
677     object_thaw_notifies (object, nqueue);
678   g_object_unref (object);
679 }
680
681 static inline void
682 object_get_property (GObject     *object,
683                      GValue      *value,
684                      GParamSpec  *pspec,
685                      const gchar *trailer)
686 {
687   GObjectClass *class;
688   
689   g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type));   /* paranoid */
690   
691   class = g_type_class_peek (pspec->owner_type);
692   
693   class->get_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
694 }
695
696 static inline void
697 object_set_property (GObject     *object,
698                      GValue      *value,
699                      GParamSpec  *pspec,
700                      const gchar *trailer,
701                      NotifyQueue *nqueue)
702 {
703   GObjectClass *class;
704   
705   g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type));   /* paranoid */
706   
707   class = g_type_class_peek (pspec->owner_type);
708   
709   class->set_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
710   object_queue_property (object, pspec, nqueue);
711 }
712
713 gpointer
714 g_object_new (GType        object_type,
715               const gchar *first_property_name,
716               ...)
717 {
718   GObject *object;
719   va_list var_args;
720   
721   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
722   
723   va_start (var_args, first_property_name);
724   object = g_object_new_valist (object_type, first_property_name, var_args);
725   va_end (var_args);
726   
727   return object;
728 }
729
730 gpointer
731 g_object_new_valist (GType        object_type,
732                      const gchar *first_property_name,
733                      va_list      var_args)
734 {
735   NotifyQueue *nqueue;
736   GObject *object;
737   GObjectClass *class;
738   const gchar *name;
739   GObjectConstructParam *cparams = NULL, *nparams = NULL;
740   guint n_cparams = 0, n_nparams = 0;
741   GSList *clist;
742   
743   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
744
745   class = g_type_class_ref (object_type);
746   clist = g_slist_copy (class->construct_properties);
747
748   /* collect parameters, sort into construction and normal ones */
749   name = first_property_name;
750   while (name)
751     {
752       const gchar *trailer = NULL;
753       GValue *value;
754       GParamSpec *pspec;
755       gchar *error = NULL;
756       
757       pspec = g_param_spec_pool_lookup (pspec_pool,
758                                         name,
759                                         object_type,
760                                         TRUE,
761                                         &trailer);
762       if (!pspec)
763         {
764           g_warning ("%s: object class `%s' has no property named `%s'",
765                      G_STRLOC,
766                      g_type_name (object_type),
767                      name);
768           break;
769         }
770       if (!(pspec->flags & G_PARAM_WRITABLE))
771         {
772           g_warning ("%s: property `%s' of object class `%s' is not writable",
773                      G_STRLOC,
774                      pspec->name,
775                      g_type_name (object_type));
776           break;
777         }
778
779       value = g_new (GValue, 1);
780       value->g_type = 0;
781       g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
782       G_VALUE_COLLECT (value, var_args, &error);
783       if (error)
784         {
785           g_warning ("%s: %s", G_STRLOC, error);
786           g_free (error);
787
788           /* we purposely leak the value here, it might not be
789            * in a sane state if an error condition occoured
790            */
791           break;
792         }
793       if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
794         {
795           guint i;
796
797           if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
798             cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
799           cparams[n_cparams].pspec = pspec;
800           cparams[n_cparams].value = value;
801           cparams[n_cparams].trailer = trailer;
802           for (i = 0; i < n_cparams; i++)       /* picky, aren't we? ;) */
803             if (cparams[i].pspec == pspec)
804               g_warning (G_STRLOC ": construct property \"%s\" for object `%s' is being set twice",
805                          pspec->name, g_type_name (object_type));
806           n_cparams++;
807           clist = g_slist_remove (clist, pspec);   /* FIXME: unique */
808         }
809       else
810         {
811           if (!n_nparams || n_nparams >= PREALLOC_CPARAMS)
812             nparams = g_renew (GObjectConstructParam, nparams, MAX (n_nparams + 1, PREALLOC_CPARAMS));
813           nparams[n_nparams].pspec = pspec;
814           nparams[n_nparams].value = value;
815           nparams[n_nparams].trailer = trailer;
816           n_nparams++;
817         }
818
819       name = va_arg (var_args, gchar*);
820     }
821
822   /* construct object from construction parameters */
823   while (clist)
824     {
825       GSList *tmp = clist->next;
826       GParamSpec *pspec = clist->data;
827       GValue *value = g_new (GValue, 1);
828
829       value->g_type = 0;
830       g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
831       g_param_value_set_default (pspec, value);
832
833       if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
834         cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
835       cparams[n_cparams].pspec = pspec;
836       cparams[n_cparams].value = value;
837       cparams[n_cparams].trailer = NULL;
838       n_cparams++;
839
840       g_slist_free_1 (clist);
841       clist = tmp;
842     }
843   object = class->constructor (object_type, n_cparams, cparams);
844
845   /* free construction values */
846   while (n_cparams--)
847     {
848       g_value_unset (cparams[n_cparams].value);
849       g_free (cparams[n_cparams].value);
850     }
851   g_free (cparams);
852   
853   /* release g_object_init() notification queue freeze_count */
854   nqueue = object_freeze_notifies (object);
855   nqueue->freeze_count--;
856   
857   /* set remaining properties */
858   cparams = nparams;
859   while (n_nparams--)
860     {
861       GValue *value = nparams->value;
862       GParamSpec *pspec = nparams->pspec;
863       const gchar *trailer = nparams++->trailer;
864
865       /* convert if necessary */
866       if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
867         {
868           GValue tmp_value = { 0, };
869
870           g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
871           if (!g_value_convert (value, &tmp_value) ||
872               g_param_value_validate (pspec, &tmp_value))
873             g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
874                        G_STRLOC,
875                        G_VALUE_TYPE_NAME (value),
876                        pspec->name,
877                        g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
878           else
879             object_set_property (object, &tmp_value, pspec, trailer, nqueue);
880           g_value_unset (&tmp_value);
881         }
882       else
883         object_set_property (object, value, pspec, trailer, nqueue);
884       
885       g_value_unset (value);
886       g_free (value);
887     }
888   g_free (cparams);
889
890   g_type_class_unref (class);
891
892   /* release our own freeze count and handle notifications */
893   object_thaw_notifies (object, nqueue);
894   
895   return object;
896 }
897
898 static GObject*
899 g_object_constructor (GType                  type,
900                       guint                  n_construct_properties,
901                       GObjectConstructParam *construct_params)
902 {
903   GObject *object;
904
905   /* create object */
906   object = (GObject*) g_type_create_instance (type);
907
908   /* set construction parameters */
909   if (n_construct_properties)
910     {
911       NotifyQueue *nqueue = object_freeze_notifies (object);
912       
913       /* set construct properties */
914       while (n_construct_properties--)
915         {
916           GValue *value = construct_params->value;
917           GParamSpec *pspec = construct_params->pspec;
918           const gchar *trailer = construct_params++->trailer;
919           
920           /* convert if necessary */
921           if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
922             {
923               GValue tmp_value = { 0, };
924               
925               g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
926               if (!g_value_convert (value, &tmp_value) ||
927                   g_param_value_validate (pspec, &tmp_value))
928                 g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
929                            G_STRLOC,
930                            G_VALUE_TYPE_NAME (value),
931                            pspec->name,
932                            g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
933               else
934                 object_set_property (object, &tmp_value, pspec, trailer, nqueue);
935               g_value_unset (&tmp_value);
936             }
937           else
938             object_set_property (object, value, pspec, trailer, nqueue);
939         }
940       nqueue->freeze_count--;
941       /* the notification queue is still frozen from g_object_init(), so
942        * we don't need to handle it here, g_object_new_valist() takes
943        * care of that
944        */
945     }
946
947   return object;
948 }
949
950 void
951 g_object_set_valist (GObject     *object,
952                      const gchar *first_property_name,
953                      va_list      var_args)
954 {
955   NotifyQueue *nqueue;
956   const gchar *name;
957   
958   g_return_if_fail (G_IS_OBJECT (object));
959   
960   g_object_ref (object);
961   nqueue = object_freeze_notifies (object);
962   
963   name = first_property_name;
964   while (name)
965     {
966       const gchar *trailer = NULL;
967       GValue value = { 0, };
968       GParamSpec *pspec;
969       gchar *error = NULL;
970       
971       pspec = g_param_spec_pool_lookup (pspec_pool,
972                                         name,
973                                         G_OBJECT_TYPE (object),
974                                         TRUE,
975                                         &trailer);
976       if (!pspec)
977         {
978           g_warning ("%s: object class `%s' has no property named `%s'",
979                      G_STRLOC,
980                      G_OBJECT_TYPE_NAME (object),
981                      name);
982           break;
983         }
984       if (!(pspec->flags & G_PARAM_WRITABLE))
985         {
986           g_warning ("%s: property `%s' of object class `%s' is not writable",
987                      G_STRLOC,
988                      pspec->name,
989                      G_OBJECT_TYPE_NAME (object));
990           break;
991         }
992       
993       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
994       
995       G_VALUE_COLLECT (&value, var_args, &error);
996       if (error)
997         {
998           g_warning ("%s: %s", G_STRLOC, error);
999           g_free (error);
1000           
1001           /* we purposely leak the value here, it might not be
1002            * in a sane state if an error condition occoured
1003            */
1004           break;
1005         }
1006       
1007       object_set_property (object, &value, pspec, trailer, nqueue);
1008       
1009       g_value_unset (&value);
1010       
1011       name = va_arg (var_args, gchar*);
1012     }
1013
1014   object_thaw_notifies (object, nqueue);
1015   g_object_unref (object);
1016 }
1017
1018 void
1019 g_object_get_valist (GObject     *object,
1020                      const gchar *first_property_name,
1021                      va_list      var_args)
1022 {
1023   const gchar *name;
1024   
1025   g_return_if_fail (G_IS_OBJECT (object));
1026   
1027   g_object_ref (object);
1028   
1029   name = first_property_name;
1030   
1031   while (name)
1032     {
1033       const gchar *trailer = NULL;
1034       GValue value = { 0, };
1035       GParamSpec *pspec;
1036       gchar *error;
1037       
1038       pspec = g_param_spec_pool_lookup (pspec_pool,
1039                                         name,
1040                                         G_OBJECT_TYPE (object),
1041                                         TRUE,
1042                                         &trailer);
1043       if (!pspec)
1044         {
1045           g_warning ("%s: object class `%s' has no property named `%s'",
1046                      G_STRLOC,
1047                      G_OBJECT_TYPE_NAME (object),
1048                      name);
1049           break;
1050         }
1051       if (!(pspec->flags & G_PARAM_READABLE))
1052         {
1053           g_warning ("%s: property `%s' of object class `%s' is not readable",
1054                      G_STRLOC,
1055                      pspec->name,
1056                      G_OBJECT_TYPE_NAME (object));
1057           break;
1058         }
1059       
1060       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1061       
1062       object_get_property (object, &value, pspec, trailer);
1063       
1064       G_VALUE_LCOPY (&value, var_args, &error);
1065       if (error)
1066         {
1067           g_warning ("%s: %s", G_STRLOC, error);
1068           g_free (error);
1069           
1070           /* we purposely leak the value here, it might not be
1071            * in a sane state if an error condition occoured
1072            */
1073           break;
1074         }
1075       
1076       g_value_unset (&value);
1077       
1078       name = va_arg (var_args, gchar*);
1079     }
1080   
1081   g_object_unref (object);
1082 }
1083
1084 void
1085 g_object_set (gpointer     _object,
1086               const gchar *first_property_name,
1087               ...)
1088 {
1089   GObject *object = _object;
1090   va_list var_args;
1091   
1092   g_return_if_fail (G_IS_OBJECT (object));
1093   
1094   va_start (var_args, first_property_name);
1095   g_object_set_valist (object, first_property_name, var_args);
1096   va_end (var_args);
1097 }
1098
1099 void
1100 g_object_get (gpointer     _object,
1101               const gchar *first_property_name,
1102               ...)
1103 {
1104   GObject *object = _object;
1105   va_list var_args;
1106   
1107   g_return_if_fail (G_IS_OBJECT (object));
1108   
1109   va_start (var_args, first_property_name);
1110   g_object_get_valist (object, first_property_name, var_args);
1111   va_end (var_args);
1112 }
1113
1114 void
1115 g_object_set_property (GObject      *object,
1116                        const gchar  *property_name,
1117                        const GValue *value)
1118 {
1119   NotifyQueue *nqueue;
1120   GParamSpec *pspec;
1121   const gchar *trailer;
1122   
1123   g_return_if_fail (G_IS_OBJECT (object));
1124   g_return_if_fail (property_name != NULL);
1125   g_return_if_fail (G_IS_VALUE (value));
1126   
1127   g_object_ref (object);
1128   nqueue = object_freeze_notifies (object);
1129   
1130   pspec = g_param_spec_pool_lookup (pspec_pool,
1131                                     property_name,
1132                                     G_OBJECT_TYPE (object),
1133                                     TRUE,
1134                                     &trailer);
1135   if (!pspec)
1136     g_warning ("%s: object class `%s' has no property named `%s'",
1137                G_STRLOC,
1138                G_OBJECT_TYPE_NAME (object),
1139                property_name);
1140   else
1141     {
1142       GValue tmp_value = { 0, };
1143       
1144       /* provide a copy to work from and convert if necessary */
1145       g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1146       
1147       if (!g_value_convert (value, &tmp_value) ||
1148           g_param_value_validate (pspec, &tmp_value))
1149         g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
1150                    G_STRLOC,
1151                    G_VALUE_TYPE_NAME (value),
1152                    pspec->name,
1153                    g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
1154       else
1155         object_set_property (object, &tmp_value, pspec, trailer, nqueue);
1156       
1157       g_value_unset (&tmp_value);
1158     }
1159   
1160   object_thaw_notifies (object, nqueue);
1161   g_object_unref (object);
1162 }
1163
1164 void
1165 g_object_get_property (GObject     *object,
1166                        const gchar *property_name,
1167                        GValue      *value)
1168 {
1169   GParamSpec *pspec;
1170   const gchar *trailer;
1171   
1172   g_return_if_fail (G_IS_OBJECT (object));
1173   g_return_if_fail (property_name != NULL);
1174   g_return_if_fail (G_IS_VALUE (value));
1175   
1176   g_object_ref (object);
1177   
1178   pspec = g_param_spec_pool_lookup (pspec_pool,
1179                                     property_name,
1180                                     G_OBJECT_TYPE (object),
1181                                     TRUE,
1182                                     &trailer);
1183   if (!pspec)
1184     g_warning ("%s: object class `%s' has no property named `%s'",
1185                G_STRLOC,
1186                G_OBJECT_TYPE_NAME (object),
1187                property_name);
1188   else
1189     {
1190       GValue tmp_value = { 0, };
1191       
1192       /* provide a copy to work from and later convert if necessary, so
1193        * _get_property() implementations need *not* care about freeing values
1194        * that might be already set in the property to get.
1195        * (though, at this point, GValue should exclusively be modified
1196        * through the accessor functions anyways)
1197        */
1198       g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1199       
1200       if (!g_value_types_exchangable (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
1201         g_warning ("%s: can't retrive property `%s' value of type `%s' as value of type `%s'",
1202                    G_STRLOC,
1203                    pspec->name,
1204                    g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1205                    G_VALUE_TYPE_NAME (value));
1206       else
1207         {
1208           object_get_property (object, &tmp_value, pspec, trailer);
1209           g_value_convert (&tmp_value, value);
1210           /* g_value_validate (value, pspec); */
1211         }
1212       
1213       g_value_unset (&tmp_value);
1214     }
1215   
1216   g_object_unref (object);
1217 }
1218
1219 gpointer
1220 g_object_ref (gpointer _object)
1221 {
1222   GObject *object = _object;
1223
1224   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1225   g_return_val_if_fail (object->ref_count > 0, NULL);
1226   
1227   object->ref_count += 1;
1228   
1229   return object;
1230 }
1231
1232 void
1233 g_object_unref (gpointer _object)
1234 {
1235   GObject *object = _object;
1236
1237   g_return_if_fail (G_IS_OBJECT (object));
1238   g_return_if_fail (object->ref_count > 0);
1239   
1240   if (object->ref_count > 1)
1241     object->ref_count -= 1;
1242   else
1243     g_object_last_unref (object);
1244 }
1245
1246 gpointer
1247 g_object_get_qdata (GObject *object,
1248                     GQuark   quark)
1249 {
1250   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1251   
1252   return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1253 }
1254
1255 void
1256 g_object_set_qdata (GObject *object,
1257                     GQuark   quark,
1258                     gpointer data)
1259 {
1260   g_return_if_fail (G_IS_OBJECT (object));
1261   g_return_if_fail (quark > 0);
1262   
1263   g_datalist_id_set_data (&object->qdata, quark, data);
1264 }
1265
1266 void
1267 g_object_set_qdata_full (GObject       *object,
1268                          GQuark         quark,
1269                          gpointer       data,
1270                          GDestroyNotify destroy)
1271 {
1272   g_return_if_fail (G_IS_OBJECT (object));
1273   g_return_if_fail (quark > 0);
1274   
1275   g_datalist_id_set_data_full (&object->qdata, quark, data, data ? destroy : NULL);
1276 }
1277
1278 gpointer
1279 g_object_steal_qdata (GObject *object,
1280                       GQuark   quark)
1281 {
1282   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1283   g_return_val_if_fail (quark > 0, NULL);
1284   
1285   return g_datalist_id_remove_no_notify (&object->qdata, quark);
1286 }
1287
1288 gpointer
1289 g_object_get_data (GObject     *object,
1290                    const gchar *key)
1291 {
1292   GQuark quark;
1293
1294   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1295   g_return_val_if_fail (key != NULL, NULL);
1296
1297   quark = g_quark_try_string (key);
1298
1299   return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1300 }
1301
1302 void
1303 g_object_set_data (GObject     *object,
1304                    const gchar *key,
1305                    gpointer     data)
1306 {
1307   g_return_if_fail (G_IS_OBJECT (object));
1308   g_return_if_fail (key != NULL);
1309
1310   g_datalist_id_set_data (&object->qdata, g_quark_from_string (key), data);
1311 }
1312
1313 void
1314 g_object_set_data_full (GObject       *object,
1315                         const gchar   *key,
1316                         gpointer       data,
1317                         GDestroyNotify destroy)
1318 {
1319   g_return_if_fail (G_IS_OBJECT (object));
1320   g_return_if_fail (key != NULL);
1321
1322   g_datalist_id_set_data_full (&object->qdata, g_quark_from_string (key), data, data ? destroy : NULL);
1323 }
1324
1325 gpointer
1326 g_object_steal_data (GObject     *object,
1327                      const gchar *key)
1328 {
1329   GQuark quark;
1330
1331   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1332   g_return_val_if_fail (key != NULL, NULL);
1333
1334   quark = g_quark_try_string (key);
1335
1336   return quark ? g_datalist_id_remove_no_notify (&object->qdata, quark) : NULL;
1337 }
1338
1339 static void
1340 g_value_object_init (GValue *value)
1341 {
1342   value->data[0].v_pointer = NULL;
1343 }
1344
1345 static void
1346 g_value_object_free_value (GValue *value)
1347 {
1348   if (value->data[0].v_pointer)
1349     g_object_unref (value->data[0].v_pointer);
1350 }
1351
1352 static void
1353 g_value_object_copy_value (const GValue *src_value,
1354                            GValue       *dest_value)
1355 {
1356   if (src_value->data[0].v_pointer)
1357     dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
1358   else
1359     dest_value->data[0].v_pointer = NULL;
1360 }
1361
1362 static gpointer
1363 g_value_object_peek_pointer (const GValue *value)
1364 {
1365   return value->data[0].v_pointer;
1366 }
1367
1368 static gchar*
1369 g_value_object_collect_value (GValue      *value,
1370                               guint        nth_value,
1371                               GType       *collect_type,
1372                               GTypeCValue *collect_value)
1373 {
1374   if (collect_value->v_pointer)
1375     {
1376       GObject *object = collect_value->v_pointer;
1377       
1378       if (object->g_type_instance.g_class == NULL)
1379         return g_strconcat ("invalid unclassed object pointer for value type `",
1380                             G_VALUE_TYPE_NAME (value),
1381                             "'",
1382                             NULL);
1383       else if (!g_type_is_a (G_OBJECT_TYPE (object), G_VALUE_TYPE (value)))
1384         return g_strconcat ("invalid object type `",
1385                             G_OBJECT_TYPE_NAME (object),
1386                             "' for value type `",
1387                             G_VALUE_TYPE_NAME (value),
1388                             "'",
1389                             NULL);
1390       value->data[0].v_pointer = g_object_ref (object);
1391     }
1392   else
1393     value->data[0].v_pointer = NULL;
1394   
1395   *collect_type = 0;
1396   return NULL;
1397 }
1398
1399 static gchar*
1400 g_value_object_lcopy_value (const GValue *value,
1401                             guint         nth_value,
1402                             GType        *collect_type,
1403                             GTypeCValue  *collect_value)
1404 {
1405   GObject **object_p = collect_value->v_pointer;
1406   
1407   if (!object_p)
1408     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
1409   
1410   *object_p = value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
1411   
1412   *collect_type = 0;
1413   return NULL;
1414 }
1415
1416 void
1417 g_value_set_object (GValue  *value,
1418                     GObject *v_object)
1419 {
1420   g_return_if_fail (G_IS_VALUE_OBJECT (value));
1421   
1422   if (value->data[0].v_pointer)
1423     {
1424       g_object_unref (value->data[0].v_pointer);
1425       value->data[0].v_pointer = NULL;
1426     }
1427
1428   if (v_object)
1429     {
1430       g_return_if_fail (G_IS_OBJECT (v_object));
1431       g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (v_object), G_VALUE_TYPE (value)));
1432
1433       value->data[0].v_pointer = v_object;
1434       g_object_ref (value->data[0].v_pointer);
1435     }
1436 }
1437
1438 GObject*
1439 g_value_get_object (const GValue *value)
1440 {
1441   g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
1442   
1443   return value->data[0].v_pointer;
1444 }
1445
1446 GObject*
1447 g_value_dup_object (const GValue *value)
1448 {
1449   g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
1450   
1451   return value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
1452 }
1453
1454 guint
1455 g_signal_connect_object (gpointer     instance,
1456                          const gchar *detailed_signal,
1457                          GCallback    c_handler,
1458                          gpointer     gobject,
1459                          gboolean     swapped,
1460                          gboolean     after)
1461 {
1462   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1463   g_return_val_if_fail (detailed_signal != NULL, 0);
1464   g_return_val_if_fail (c_handler != NULL, 0);
1465
1466   if (gobject)
1467     {
1468       GClosure *closure;
1469
1470       g_return_val_if_fail (G_IS_OBJECT (gobject), 0);
1471
1472       closure = (swapped ? g_cclosure_new_object_swap : g_cclosure_new_object) (c_handler, gobject);
1473
1474       return g_signal_connect_closure (instance, detailed_signal, closure, after);
1475     }
1476   else
1477     return g_signal_connect_data (instance, detailed_signal, c_handler, NULL, NULL, swapped, after);
1478 }
1479
1480 typedef struct {
1481   GObject  *object;
1482   guint     n_closures;
1483   GClosure *closures[1]; /* flexible array */
1484 } CArray;
1485
1486 static void
1487 object_remove_closure (gpointer  data,
1488                        GClosure *closure)
1489 {
1490   GObject *object = data;
1491   CArray *carray = g_object_get_qdata (object, quark_closure_array);
1492   guint i;
1493   
1494   for (i = 0; i < carray->n_closures; i++)
1495     if (carray->closures[i] == closure)
1496       {
1497         carray->n_closures--;
1498         if (i < carray->n_closures)
1499           carray->closures[i] = carray->closures[carray->n_closures];
1500         return;
1501       }
1502   g_assert_not_reached ();
1503 }
1504
1505 static void
1506 destroy_closure_array (gpointer data)
1507 {
1508   CArray *carray = data;
1509   GObject *object = carray->object;
1510   guint i, n = carray->n_closures;
1511   
1512   for (i = 0; i < n; i++)
1513     {
1514       GClosure *closure = carray->closures[i];
1515       
1516       /* removing object_remove_closure() upfront is probably faster than
1517        * letting it fiddle with quark_closure_array which is empty anyways
1518        */
1519       g_closure_remove_inotify (closure, object, object_remove_closure);
1520       g_closure_invalidate (closure);
1521     }
1522   g_free (carray);
1523 }
1524
1525 void
1526 g_object_watch_closure (GObject  *object,
1527                         GClosure *closure)
1528 {
1529   CArray *carray;
1530   
1531   g_return_if_fail (G_IS_OBJECT (object));
1532   g_return_if_fail (closure != NULL);
1533   g_return_if_fail (closure->is_invalid == FALSE);
1534   g_return_if_fail (closure->in_marshal == FALSE);
1535   g_return_if_fail (object->ref_count > 0);     /* this doesn't work on finalizing objects */
1536   
1537   g_closure_add_inotify (closure, object, object_remove_closure);
1538   g_closure_add_marshal_guards (closure,
1539                                 object, (GClosureNotify) g_object_ref,
1540                                 object, (GClosureNotify) g_object_unref);
1541   carray = g_object_steal_qdata (object, quark_closure_array);
1542   if (!carray)
1543     {
1544       carray = g_renew (CArray, NULL, 1);
1545       carray->object = object;
1546       carray->n_closures = 1;
1547       carray->closures[0] = closure;
1548       g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
1549     }
1550   else
1551     {
1552       guint i = carray->n_closures++;
1553       
1554       carray = g_realloc (carray, sizeof (*carray) + sizeof (carray->closures[0]) * i);
1555       carray->closures[i] = closure;
1556       g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
1557     }
1558 }
1559
1560 GClosure*
1561 g_closure_new_object (guint    sizeof_closure,
1562                       GObject *object)
1563 {
1564   GClosure *closure;
1565
1566   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1567   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
1568
1569   closure = g_closure_new_simple (sizeof_closure, object);
1570   g_object_watch_closure (object, closure);
1571
1572   return closure;
1573 }
1574
1575 GClosure*
1576 g_cclosure_new_object (GCallback callback_func,
1577                        gpointer  _object)
1578 {
1579   GObject *object = _object;
1580   GClosure *closure;
1581
1582   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1583   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
1584   g_return_val_if_fail (callback_func != NULL, NULL);
1585
1586   closure = g_cclosure_new (callback_func, object, NULL);
1587   g_object_watch_closure (object, closure);
1588
1589   return closure;
1590 }
1591
1592 GClosure*
1593 g_cclosure_new_object_swap (GCallback callback_func,
1594                             gpointer  _object)
1595 {
1596   GObject *object = _object;
1597   GClosure *closure;
1598
1599   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1600   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
1601   g_return_val_if_fail (callback_func != NULL, NULL);
1602
1603   closure = g_cclosure_new_swap (callback_func, object, NULL);
1604   g_object_watch_closure (object, closure);
1605
1606   return closure;
1607 }