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