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