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