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