turned all modifications to the first 32 integer bits in a closure into
[platform/upstream/glib.git] / gobject / gobject.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1998-1999, 2000-2001 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 #include        "gobjectalias.h"
21 #include        <glib/gdatasetprivate.h>
22
23 /*
24  * MT safe with regards to reference counting.
25  */
26
27 #include        "gvaluecollector.h"
28 #include        "gsignal.h"
29 #include        "gparamspecs.h"
30 #include        "gvaluetypes.h"
31 #include        "gobjectnotifyqueue.c"
32 #include        <string.h>
33 #include        <signal.h>
34
35
36 #define PREALLOC_CPARAMS        (8)
37
38
39 /* --- macros --- */
40 #define PARAM_SPEC_PARAM_ID(pspec)              ((pspec)->param_id)
41 #define PARAM_SPEC_SET_PARAM_ID(pspec, id)      ((pspec)->param_id = (id))
42
43 #define OBJECT_HAS_TOGGLE_REF_FLAG 0x1
44 #define OBJECT_HAS_TOGGLE_REF(object) \
45     ((G_DATALIST_GET_FLAGS(&(object)->qdata) & OBJECT_HAS_TOGGLE_REF_FLAG) != 0)
46
47
48 /* --- signals --- */
49 enum {
50   NOTIFY,
51   LAST_SIGNAL
52 };
53
54
55 /* --- properties --- */
56 enum {
57   PROP_NONE
58 };
59
60
61 /* --- prototypes --- */
62 static void     g_object_base_class_init                (GObjectClass   *class);
63 static void     g_object_base_class_finalize            (GObjectClass   *class);
64 static void     g_object_do_class_init                  (GObjectClass   *class);
65 static void     g_object_init                           (GObject        *object);
66 static GObject* g_object_constructor                    (GType                  type,
67                                                          guint                  n_construct_properties,
68                                                          GObjectConstructParam *construct_params);
69 static void     g_object_real_dispose                   (GObject        *object);
70 static void     g_object_finalize                       (GObject        *object);
71 static void     g_object_do_set_property                (GObject        *object,
72                                                          guint           property_id,
73                                                          const GValue   *value,
74                                                          GParamSpec     *pspec);
75 static void     g_object_do_get_property                (GObject        *object,
76                                                          guint           property_id,
77                                                          GValue         *value,
78                                                          GParamSpec     *pspec);
79 static void     g_value_object_init                     (GValue         *value);
80 static void     g_value_object_free_value               (GValue         *value);
81 static void     g_value_object_copy_value               (const GValue   *src_value,
82                                                          GValue         *dest_value);
83 static void     g_value_object_transform_value          (const GValue   *src_value,
84                                                          GValue         *dest_value);
85 static gpointer g_value_object_peek_pointer             (const GValue   *value);
86 static gchar*   g_value_object_collect_value            (GValue         *value,
87                                                          guint           n_collect_values,
88                                                          GTypeCValue    *collect_values,
89                                                          guint           collect_flags);
90 static gchar*   g_value_object_lcopy_value              (const GValue   *value,
91                                                          guint           n_collect_values,
92                                                          GTypeCValue    *collect_values,
93                                                          guint           collect_flags);
94 static void     g_object_dispatch_properties_changed    (GObject        *object,
95                                                          guint           n_pspecs,
96                                                          GParamSpec    **pspecs);
97 static inline void         object_get_property          (GObject        *object,
98                                                          GParamSpec     *pspec,
99                                                          GValue         *value);
100 static inline void         object_set_property          (GObject        *object,
101                                                          GParamSpec     *pspec,
102                                                          const GValue   *value,
103                                                          GObjectNotifyQueue *nqueue);
104
105 static void object_interface_check_properties           (gpointer        func_data,
106                                                          gpointer        g_iface);
107
108
109 /* --- variables --- */
110 static GQuark               quark_closure_array = 0;
111 static GQuark               quark_weak_refs = 0;
112 static GQuark               quark_toggle_refs = 0;
113 static GParamSpecPool      *pspec_pool = NULL;
114 static GObjectNotifyContext property_notify_context = { 0, };
115 static gulong               gobject_signals[LAST_SIGNAL] = { 0, };
116 G_LOCK_DEFINE_STATIC (construct_objects_lock);
117 static GSList *construct_objects = NULL;
118
119 /* --- functions --- */
120 #ifdef  G_ENABLE_DEBUG
121 #define IF_DEBUG(debug_type)    if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
122 G_LOCK_DEFINE_STATIC     (debug_objects);
123 static volatile GObject *g_trap_object_ref = NULL;
124 static guint             debug_objects_count = 0;
125 static GHashTable       *debug_objects_ht = NULL;
126 static void
127 debug_objects_foreach (gpointer key,
128                        gpointer value,
129                        gpointer user_data)
130 {
131   GObject *object = value;
132
133   g_message ("[%p] stale %s\tref_count=%u",
134              object,
135              G_OBJECT_TYPE_NAME (object),
136              object->ref_count);
137 }
138 static void
139 debug_objects_atexit (void)
140 {
141   IF_DEBUG (OBJECTS)
142     {
143       G_LOCK (debug_objects);
144       g_message ("stale GObjects: %u", debug_objects_count);
145       g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
146       G_UNLOCK (debug_objects);
147     }
148 }
149 #endif  /* G_ENABLE_DEBUG */
150
151 void
152 g_object_type_init (void)
153 {
154   static gboolean initialized = FALSE;
155   static const GTypeFundamentalInfo finfo = {
156     G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE,
157   };
158   static GTypeInfo info = {
159     sizeof (GObjectClass),
160     (GBaseInitFunc) g_object_base_class_init,
161     (GBaseFinalizeFunc) g_object_base_class_finalize,
162     (GClassInitFunc) g_object_do_class_init,
163     NULL        /* class_destroy */,
164     NULL        /* class_data */,
165     sizeof (GObject),
166     0           /* n_preallocs */,
167     (GInstanceInitFunc) g_object_init,
168     NULL,       /* value_table */
169   };
170   static const GTypeValueTable value_table = {
171     g_value_object_init,          /* value_init */
172     g_value_object_free_value,    /* value_free */
173     g_value_object_copy_value,    /* value_copy */
174     g_value_object_peek_pointer,  /* value_peek_pointer */
175     "p",                          /* collect_format */
176     g_value_object_collect_value, /* collect_value */
177     "p",                          /* lcopy_format */
178     g_value_object_lcopy_value,   /* lcopy_value */
179   };
180   GType type;
181   
182   g_return_if_fail (initialized == FALSE);
183   initialized = TRUE;
184   
185   /* G_TYPE_OBJECT
186    */
187   info.value_table = &value_table;
188   type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &info, &finfo, 0);
189   g_assert (type == G_TYPE_OBJECT);
190   g_value_register_transform_func (G_TYPE_OBJECT, G_TYPE_OBJECT, g_value_object_transform_value);
191   
192 #ifdef  G_ENABLE_DEBUG
193   IF_DEBUG (OBJECTS)
194     {
195       debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
196       g_atexit (debug_objects_atexit);
197     }
198 #endif  /* G_ENABLE_DEBUG */
199 }
200
201 static void
202 g_object_base_class_init (GObjectClass *class)
203 {
204   GObjectClass *pclass = g_type_class_peek_parent (class);
205
206   /* reset instance specific fields and methods that don't get inherited */
207   class->construct_properties = pclass ? g_slist_copy (pclass->construct_properties) : NULL;
208   class->get_property = NULL;
209   class->set_property = NULL;
210 }
211
212 static void
213 g_object_base_class_finalize (GObjectClass *class)
214 {
215   GList *list, *node;
216   
217   _g_signals_destroy (G_OBJECT_CLASS_TYPE (class));
218
219   g_slist_free (class->construct_properties);
220   class->construct_properties = NULL;
221   list = g_param_spec_pool_list_owned (pspec_pool, G_OBJECT_CLASS_TYPE (class));
222   for (node = list; node; node = node->next)
223     {
224       GParamSpec *pspec = node->data;
225       
226       g_param_spec_pool_remove (pspec_pool, pspec);
227       PARAM_SPEC_SET_PARAM_ID (pspec, 0);
228       g_param_spec_unref (pspec);
229     }
230   g_list_free (list);
231 }
232
233 static void
234 g_object_notify_dispatcher (GObject     *object,
235                             guint        n_pspecs,
236                             GParamSpec **pspecs)
237 {
238   G_OBJECT_GET_CLASS (object)->dispatch_properties_changed (object, n_pspecs, pspecs);
239 }
240
241 static void
242 g_object_do_class_init (GObjectClass *class)
243 {
244   /* read the comment about typedef struct CArray; on why not to change this quark */
245   quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
246
247   quark_weak_refs = g_quark_from_static_string ("GObject-weak-references");
248   quark_toggle_refs = g_quark_from_static_string ("GObject-toggle-references");
249   pspec_pool = g_param_spec_pool_new (TRUE);
250   property_notify_context.quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
251   property_notify_context.dispatcher = g_object_notify_dispatcher;
252   
253   class->constructor = g_object_constructor;
254   class->set_property = g_object_do_set_property;
255   class->get_property = g_object_do_get_property;
256   class->dispose = g_object_real_dispose;
257   class->finalize = g_object_finalize;
258   class->dispatch_properties_changed = g_object_dispatch_properties_changed;
259   class->notify = NULL;
260
261   gobject_signals[NOTIFY] =
262     g_signal_new ("notify",
263                   G_TYPE_FROM_CLASS (class),
264                   G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS | G_SIGNAL_ACTION,
265                   G_STRUCT_OFFSET (GObjectClass, notify),
266                   NULL, NULL,
267                   g_cclosure_marshal_VOID__PARAM,
268                   G_TYPE_NONE,
269                   1, G_TYPE_PARAM);
270
271   /* Install a check function that we'll use to verify that classes that
272    * implement an interface implement all properties for that interface
273    */
274   g_type_add_interface_check (NULL, object_interface_check_properties);
275 }
276
277 static void
278 install_property_internal (GType       g_type,
279                            guint       property_id,
280                            GParamSpec *pspec)
281 {
282   if (g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type, FALSE))
283     {
284       g_warning ("When installing property: type `%s' already has a property named `%s'",
285                  g_type_name (g_type),
286                  pspec->name);
287       return;
288     }
289
290   g_param_spec_ref (pspec);
291   g_param_spec_sink (pspec);
292   PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
293   g_param_spec_pool_insert (pspec_pool, pspec, g_type);
294 }
295
296 void
297 g_object_class_install_property (GObjectClass *class,
298                                  guint         property_id,
299                                  GParamSpec   *pspec)
300 {
301   g_return_if_fail (G_IS_OBJECT_CLASS (class));
302   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
303   if (pspec->flags & G_PARAM_WRITABLE)
304     g_return_if_fail (class->set_property != NULL);
305   if (pspec->flags & G_PARAM_READABLE)
306     g_return_if_fail (class->get_property != NULL);
307   g_return_if_fail (property_id > 0);
308   g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0);  /* paranoid */
309   if (pspec->flags & G_PARAM_CONSTRUCT)
310     g_return_if_fail ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
311   if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
312     g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
313
314   install_property_internal (G_OBJECT_CLASS_TYPE (class), property_id, pspec);
315
316   if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
317     class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
318
319   /* for property overrides of construct poperties, we have to get rid
320    * of the overidden inherited construct property
321    */
322   pspec = g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type_parent (G_OBJECT_CLASS_TYPE (class)), TRUE);
323   if (pspec && pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
324     class->construct_properties = g_slist_remove (class->construct_properties, pspec);
325 }
326
327 void
328 g_object_interface_install_property (gpointer      g_iface,
329                                      GParamSpec   *pspec)
330 {
331   GTypeInterface *iface_class = g_iface;
332         
333   g_return_if_fail (G_TYPE_IS_INTERFACE (iface_class->g_type));
334   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
335   g_return_if_fail (!G_IS_PARAM_SPEC_OVERRIDE (pspec)); /* paranoid */
336   g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0);  /* paranoid */
337                     
338   install_property_internal (iface_class->g_type, 0, pspec);
339 }
340
341 GParamSpec*
342 g_object_class_find_property (GObjectClass *class,
343                               const gchar  *property_name)
344 {
345   GParamSpec *pspec;
346   GParamSpec *redirect;
347         
348   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
349   g_return_val_if_fail (property_name != NULL, NULL);
350   
351   pspec = g_param_spec_pool_lookup (pspec_pool,
352                                     property_name,
353                                     G_OBJECT_CLASS_TYPE (class),
354                                     TRUE);
355   if (pspec)
356     {
357       redirect = g_param_spec_get_redirect_target (pspec);
358       if (redirect)
359         return redirect;
360       else
361         return pspec;
362     }
363   else
364     return NULL;
365 }
366
367 GParamSpec*
368 g_object_interface_find_property (gpointer      g_iface,
369                                   const gchar  *property_name)
370 {
371   GTypeInterface *iface_class = g_iface;
372         
373   g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface_class->g_type), NULL);
374   g_return_val_if_fail (property_name != NULL, NULL);
375   
376   return g_param_spec_pool_lookup (pspec_pool,
377                                    property_name,
378                                    iface_class->g_type,
379                                    FALSE);
380 }
381
382 void
383 g_object_class_override_property (GObjectClass *oclass,
384                                   guint         property_id,
385                                   const gchar  *name)
386 {
387   GParamSpec *overridden = NULL;
388   GParamSpec *new;
389   GType parent_type;
390   
391   g_return_if_fail (G_IS_OBJECT_CLASS (oclass));
392   g_return_if_fail (property_id > 0);
393   g_return_if_fail (name != NULL);
394
395   /* Find the overridden property; first check parent types
396    */
397   parent_type = g_type_parent (G_OBJECT_CLASS_TYPE (oclass));
398   if (parent_type != G_TYPE_NONE)
399     overridden = g_param_spec_pool_lookup (pspec_pool,
400                                            name,
401                                            parent_type,
402                                            TRUE);
403   if (!overridden)
404     {
405       GType *ifaces;
406       guint n_ifaces;
407       
408       /* Now check interfaces
409        */
410       ifaces = g_type_interfaces (G_OBJECT_CLASS_TYPE (oclass), &n_ifaces);
411       while (n_ifaces-- && !overridden)
412         {
413           overridden = g_param_spec_pool_lookup (pspec_pool,
414                                                  name,
415                                                  ifaces[n_ifaces],
416                                                  FALSE);
417         }
418       
419       g_free (ifaces);
420     }
421
422   if (!overridden)
423     {
424       g_warning ("%s: Can't find property to override for '%s::%s'",
425                  G_STRFUNC, G_OBJECT_CLASS_NAME (oclass), name);
426       return;
427     }
428
429   new = g_param_spec_override (name, overridden);
430   g_object_class_install_property (oclass, property_id, new);
431 }
432
433 GParamSpec** /* free result */
434 g_object_class_list_properties (GObjectClass *class,
435                                 guint        *n_properties_p)
436 {
437   GParamSpec **pspecs;
438   guint n;
439
440   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
441
442   pspecs = g_param_spec_pool_list (pspec_pool,
443                                    G_OBJECT_CLASS_TYPE (class),
444                                    &n);
445   if (n_properties_p)
446     *n_properties_p = n;
447
448   return pspecs;
449 }
450
451 GParamSpec** /* free result */
452 g_object_interface_list_properties (gpointer      g_iface,
453                                     guint        *n_properties_p)
454 {
455   GTypeInterface *iface_class = g_iface;
456   GParamSpec **pspecs;
457   guint n;
458
459   g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface_class->g_type), NULL);
460
461   pspecs = g_param_spec_pool_list (pspec_pool,
462                                    iface_class->g_type,
463                                    &n);
464   if (n_properties_p)
465     *n_properties_p = n;
466
467   return pspecs;
468 }
469
470 static void
471 g_object_init (GObject *object)
472 {
473   object->ref_count = 1;
474   g_datalist_init (&object->qdata);
475   
476   /* freeze object's notification queue, g_object_newv() preserves pairedness */
477   g_object_notify_queue_freeze (object, &property_notify_context);
478
479   /* allow construct-only properties to be set */
480   G_LOCK (construct_objects_lock);
481   construct_objects = g_slist_prepend (construct_objects, object);
482   G_UNLOCK (construct_objects_lock);
483   
484 #ifdef  G_ENABLE_DEBUG
485   IF_DEBUG (OBJECTS)
486     {
487       G_LOCK (debug_objects);
488       debug_objects_count++;
489       g_hash_table_insert (debug_objects_ht, object, object);
490       G_UNLOCK (debug_objects);
491     }
492 #endif  /* G_ENABLE_DEBUG */
493 }
494
495 static void
496 g_object_do_set_property (GObject      *object,
497                           guint         property_id,
498                           const GValue *value,
499                           GParamSpec   *pspec)
500 {
501   switch (property_id)
502     {
503     default:
504       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
505       break;
506     }
507 }
508
509 static void
510 g_object_do_get_property (GObject     *object,
511                           guint        property_id,
512                           GValue      *value,
513                           GParamSpec  *pspec)
514 {
515   switch (property_id)
516     {
517     default:
518       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
519       break;
520     }
521 }
522
523 static void
524 g_object_real_dispose (GObject *object)
525 {
526   g_signal_handlers_destroy (object);
527   g_datalist_id_set_data (&object->qdata, quark_closure_array, NULL);
528   g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL);
529 }
530
531 static void
532 g_object_finalize (GObject *object)
533 {
534   g_datalist_clear (&object->qdata);
535   
536 #ifdef  G_ENABLE_DEBUG
537   IF_DEBUG (OBJECTS)
538     {
539       G_LOCK (debug_objects);
540       g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
541       g_hash_table_remove (debug_objects_ht, object);
542       debug_objects_count--;
543       G_UNLOCK (debug_objects);
544     }
545 #endif  /* G_ENABLE_DEBUG */
546 }
547
548
549 static void
550 g_object_dispatch_properties_changed (GObject     *object,
551                                       guint        n_pspecs,
552                                       GParamSpec **pspecs)
553 {
554   guint i;
555
556   for (i = 0; i < n_pspecs; i++)
557     g_signal_emit (object, gobject_signals[NOTIFY], g_quark_from_string (pspecs[i]->name), pspecs[i]);
558 }
559
560 void
561 g_object_run_dispose (GObject *object)
562 {
563   g_return_if_fail (G_IS_OBJECT (object));
564   g_return_if_fail (object->ref_count > 0);
565
566   g_object_ref (object);
567   G_OBJECT_GET_CLASS (object)->dispose (object);
568   g_object_unref (object);
569 }
570
571 void
572 g_object_freeze_notify (GObject *object)
573 {
574   g_return_if_fail (G_IS_OBJECT (object));
575
576   if (g_atomic_int_get (&object->ref_count) == 0)
577     return;
578
579   g_object_ref (object);
580   g_object_notify_queue_freeze (object, &property_notify_context);
581   g_object_unref (object);
582 }
583
584 void
585 g_object_notify (GObject     *object,
586                  const gchar *property_name)
587 {
588   GParamSpec *pspec;
589   
590   g_return_if_fail (G_IS_OBJECT (object));
591   g_return_if_fail (property_name != NULL);
592   if (g_atomic_int_get (&object->ref_count) == 0)
593     return;
594   
595   g_object_ref (object);
596   /* We don't need to get the redirect target
597    * (by, e.g. calling g_object_class_find_property())
598    * because g_object_notify_queue_add() does that
599    */
600   pspec = g_param_spec_pool_lookup (pspec_pool,
601                                     property_name,
602                                     G_OBJECT_TYPE (object),
603                                     TRUE);
604
605   if (!pspec)
606     g_warning ("%s: object class `%s' has no property named `%s'",
607                G_STRFUNC,
608                G_OBJECT_TYPE_NAME (object),
609                property_name);
610   else
611     {
612       GObjectNotifyQueue *nqueue;
613       
614       nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
615       g_object_notify_queue_add (object, nqueue, pspec);
616       g_object_notify_queue_thaw (object, nqueue);
617     }
618   g_object_unref (object);
619 }
620
621 void
622 g_object_thaw_notify (GObject *object)
623 {
624   GObjectNotifyQueue *nqueue;
625   
626   g_return_if_fail (G_IS_OBJECT (object));
627   if (g_atomic_int_get (&object->ref_count) == 0)
628     return;
629   
630   g_object_ref (object);
631   nqueue = g_object_notify_queue_from_object (object, &property_notify_context);
632   if (!nqueue || !nqueue->freeze_count)
633     g_warning ("%s: property-changed notification for %s(%p) is not frozen",
634                G_STRFUNC, G_OBJECT_TYPE_NAME (object), object);
635   else
636     g_object_notify_queue_thaw (object, nqueue);
637   g_object_unref (object);
638 }
639
640 static inline void
641 object_get_property (GObject     *object,
642                      GParamSpec  *pspec,
643                      GValue      *value)
644 {
645   GObjectClass *class = g_type_class_peek (pspec->owner_type);
646   guint param_id = PARAM_SPEC_PARAM_ID (pspec);
647   GParamSpec *redirect;
648
649   redirect = g_param_spec_get_redirect_target (pspec);
650   if (redirect)
651     pspec = redirect;    
652   
653   class->get_property (object, param_id, value, pspec);
654 }
655
656 static inline void
657 object_set_property (GObject             *object,
658                      GParamSpec          *pspec,
659                      const GValue        *value,
660                      GObjectNotifyQueue  *nqueue)
661 {
662   GValue tmp_value = { 0, };
663   GObjectClass *class = g_type_class_peek (pspec->owner_type);
664   guint param_id = PARAM_SPEC_PARAM_ID (pspec);
665   GParamSpec *redirect;
666
667   redirect = g_param_spec_get_redirect_target (pspec);
668   if (redirect)
669     pspec = redirect;
670
671   /* provide a copy to work from, convert (if necessary) and validate */
672   g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
673   if (!g_value_transform (value, &tmp_value))
674     g_warning ("unable to set property `%s' of type `%s' from value of type `%s'",
675                pspec->name,
676                g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
677                G_VALUE_TYPE_NAME (value));
678   else if (g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION))
679     {
680       gchar *contents = g_strdup_value_contents (value);
681
682       g_warning ("value \"%s\" of type `%s' is invalid or out of range for property `%s' of type `%s'",
683                  contents,
684                  G_VALUE_TYPE_NAME (value),
685                  pspec->name,
686                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
687       g_free (contents);
688     }
689   else
690     {
691       class->set_property (object, param_id, &tmp_value, pspec);
692       g_object_notify_queue_add (object, nqueue, pspec);
693     }
694   g_value_unset (&tmp_value);
695 }
696
697 static void
698 object_interface_check_properties (gpointer func_data,
699                                    gpointer g_iface)
700 {
701   GTypeInterface *iface_class = g_iface;
702   GObjectClass *class = g_type_class_peek (iface_class->g_instance_type);
703   GType iface_type = iface_class->g_type;
704   GParamSpec **pspecs;
705   guint n;
706
707   if (!G_IS_OBJECT_CLASS (class))
708     return;
709
710   pspecs = g_param_spec_pool_list (pspec_pool, iface_type, &n);
711
712   while (n--)
713     {
714       GParamSpec *class_pspec = g_param_spec_pool_lookup (pspec_pool,
715                                                           pspecs[n]->name,
716                                                           G_OBJECT_CLASS_TYPE (class),
717                                                           TRUE);
718       
719       if (!class_pspec)
720         {
721           g_critical ("Object class %s doesn't implement property "
722                       "'%s' from interface '%s'",
723                       g_type_name (G_OBJECT_CLASS_TYPE (class)),
724                       pspecs[n]->name,
725                       g_type_name (iface_type));
726
727           continue;
728         }
729
730       /* The implementation paramspec must have a less restrictive
731        * type than the interface parameter spec for set() and a
732        * more restrictive type for get(). We just require equality,
733        * rather than doing something more complicated checking
734        * the READABLE and WRITABLE flags. We also simplify here
735        * by only checking the value type, not the G_PARAM_SPEC_TYPE.
736        */
737       if (class_pspec &&
738           !g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (pspecs[n]),
739                         G_PARAM_SPEC_VALUE_TYPE (class_pspec)))
740         {
741           g_critical ("Property '%s' on class '%s' has type '%s' "
742                       "which is different from the type '%s', "
743                       "of the property on interface '%s'\n",
744                       pspecs[n]->name,
745                       g_type_name (G_OBJECT_CLASS_TYPE (class)),
746                       g_type_name (G_PARAM_SPEC_VALUE_TYPE (class_pspec)),
747                       g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspecs[n])),
748                       g_type_name (iface_type));
749         }
750       
751 #define SUBSET(a,b,mask) (((a) & ~(b) & (mask)) == 0)
752       
753       /* CONSTRUCT and CONSTRUCT_ONLY add restrictions.
754        * READABLE and WRITABLE remove restrictions. The implementation
755        * paramspec must have less restrictive flags.
756        */
757       if (class_pspec &&
758           (!SUBSET (class_pspec->flags,
759                     pspecs[n]->flags,
760                     G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY) ||
761            !SUBSET (pspecs[n]->flags,
762                     class_pspec->flags,
763                     G_PARAM_READABLE | G_PARAM_WRITABLE)))
764         {
765           g_critical ("Flags for property '%s' on class '%s' "
766                       "are not compatible with the property on"
767                       "interface '%s'\n",
768                       pspecs[n]->name,
769                       g_type_name (G_OBJECT_CLASS_TYPE (class)),
770                       g_type_name (iface_type));
771         }
772 #undef SUBSET     
773     }
774   
775   g_free (pspecs);
776 }
777
778 gpointer
779 g_object_new (GType        object_type,
780               const gchar *first_property_name,
781               ...)
782 {
783   GObject *object;
784   va_list var_args;
785   
786   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
787   
788   va_start (var_args, first_property_name);
789   object = g_object_new_valist (object_type, first_property_name, var_args);
790   va_end (var_args);
791   
792   return object;
793 }
794
795 static gboolean
796 object_in_construction (GObject *object)
797 {
798   gboolean in_construction;
799   G_LOCK (construct_objects_lock);
800   in_construction = g_slist_find (construct_objects, object) != NULL;
801   G_UNLOCK (construct_objects_lock);
802   return in_construction;
803 }
804
805 gpointer
806 g_object_newv (GType       object_type,
807                guint       n_parameters,
808                GParameter *parameters)
809 {
810   GObjectConstructParam *cparams, *oparams;
811   GObjectNotifyQueue *nqueue;
812   GObject *object;
813   GObjectClass *class, *unref_class = NULL;
814   GSList *slist;
815   guint n_total_cparams = 0, n_cparams = 0, n_oparams = 0, n_cvalues;
816   GValue *cvalues;
817   GList *clist = NULL;
818   guint i;
819
820   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
821
822   class = g_type_class_peek_static (object_type);
823   if (!class)
824     class = unref_class = g_type_class_ref (object_type);
825   for (slist = class->construct_properties; slist; slist = slist->next)
826     {
827       clist = g_list_prepend (clist, slist->data);
828       n_total_cparams += 1;
829     }
830
831   /* collect parameters, sort into construction and normal ones */
832   oparams = g_new (GObjectConstructParam, n_parameters);
833   cparams = g_new (GObjectConstructParam, n_total_cparams);
834   for (i = 0; i < n_parameters; i++)
835     {
836       GValue *value = &parameters[i].value;
837       GParamSpec *pspec = g_param_spec_pool_lookup (pspec_pool,
838                                                     parameters[i].name,
839                                                     object_type,
840                                                     TRUE);
841       if (!pspec)
842         {
843           g_warning ("%s: object class `%s' has no property named `%s'",
844                      G_STRFUNC,
845                      g_type_name (object_type),
846                      parameters[i].name);
847           continue;
848         }
849       if (!(pspec->flags & G_PARAM_WRITABLE))
850         {
851           g_warning ("%s: property `%s' of object class `%s' is not writable",
852                      G_STRFUNC,
853                      pspec->name,
854                      g_type_name (object_type));
855           continue;
856         }
857       if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
858         {
859           GList *list = g_list_find (clist, pspec);
860
861           if (!list)
862             {
863               g_warning ("%s: construct property \"%s\" for object `%s' can't be set twice",
864                          G_STRFUNC, pspec->name, g_type_name (object_type));
865               continue;
866             }
867           cparams[n_cparams].pspec = pspec;
868           cparams[n_cparams].value = value;
869           n_cparams++;
870           if (!list->prev)
871             clist = list->next;
872           else
873             list->prev->next = list->next;
874           if (list->next)
875             list->next->prev = list->prev;
876           g_list_free_1 (list);
877         }
878       else
879         {
880           oparams[n_oparams].pspec = pspec;
881           oparams[n_oparams].value = value;
882           n_oparams++;
883         }
884     }
885
886   /* set remaining construction properties to default values */
887   n_cvalues = n_total_cparams - n_cparams;
888   cvalues = g_new (GValue, n_cvalues);
889   while (clist)
890     {
891       GList *tmp = clist->next;
892       GParamSpec *pspec = clist->data;
893       GValue *value = cvalues + n_total_cparams - n_cparams - 1;
894
895       value->g_type = 0;
896       g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
897       g_param_value_set_default (pspec, value);
898
899       cparams[n_cparams].pspec = pspec;
900       cparams[n_cparams].value = value;
901       n_cparams++;
902
903       g_list_free_1 (clist);
904       clist = tmp;
905     }
906
907   /* construct object from construction parameters */
908   object = class->constructor (object_type, n_total_cparams, cparams);
909   G_LOCK (construct_objects_lock);
910   construct_objects = g_slist_remove (construct_objects, object);
911   G_UNLOCK (construct_objects_lock);
912
913   /* free construction values */
914   g_free (cparams);
915   while (n_cvalues--)
916     g_value_unset (cvalues + n_cvalues);
917   g_free (cvalues);
918   
919   /* release g_object_init() notification queue freeze_count */
920   nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
921   g_object_notify_queue_thaw (object, nqueue);
922   
923   /* set remaining properties */
924   for (i = 0; i < n_oparams; i++)
925     object_set_property (object, oparams[i].pspec, oparams[i].value, nqueue);
926   g_free (oparams);
927
928   if (unref_class)
929     g_type_class_unref (unref_class);
930
931   /* release our own freeze count and handle notifications */
932   g_object_notify_queue_thaw (object, nqueue);
933   
934   return object;
935 }
936
937 GObject*
938 g_object_new_valist (GType        object_type,
939                      const gchar *first_property_name,
940                      va_list      var_args)
941 {
942   GObjectClass *class;
943   GParameter *params;
944   const gchar *name;
945   GObject *object;
946   guint n_params = 0, n_alloced_params = 16;
947   
948   g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
949
950   if (!first_property_name)
951     return g_object_newv (object_type, 0, NULL);
952
953   class = g_type_class_ref (object_type);
954
955   params = g_new (GParameter, n_alloced_params);
956   name = first_property_name;
957   while (name)
958     {
959       gchar *error = NULL;
960       GParamSpec *pspec = g_param_spec_pool_lookup (pspec_pool,
961                                                     name,
962                                                     object_type,
963                                                     TRUE);
964       if (!pspec)
965         {
966           g_warning ("%s: object class `%s' has no property named `%s'",
967                      G_STRFUNC,
968                      g_type_name (object_type),
969                      name);
970           break;
971         }
972       if (n_params >= n_alloced_params)
973         {
974           n_alloced_params += 16;
975           params = g_renew (GParameter, params, n_alloced_params);
976         }
977       params[n_params].name = name;
978       params[n_params].value.g_type = 0;
979       g_value_init (&params[n_params].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
980       G_VALUE_COLLECT (&params[n_params].value, var_args, 0, &error);
981       if (error)
982         {
983           g_warning ("%s: %s", G_STRFUNC, error);
984           g_free (error);
985           g_value_unset (&params[n_params].value);
986           break;
987         }
988       n_params++;
989       name = va_arg (var_args, gchar*);
990     }
991
992   object = g_object_newv (object_type, n_params, params);
993
994   while (n_params--)
995     g_value_unset (&params[n_params].value);
996   g_free (params);
997
998   g_type_class_unref (class);
999
1000   return object;
1001 }
1002
1003 static GObject*
1004 g_object_constructor (GType                  type,
1005                       guint                  n_construct_properties,
1006                       GObjectConstructParam *construct_params)
1007 {
1008   GObject *object;
1009
1010   /* create object */
1011   object = (GObject*) g_type_create_instance (type);
1012   
1013   /* set construction parameters */
1014   if (n_construct_properties)
1015     {
1016       GObjectNotifyQueue *nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
1017       
1018       /* set construct properties */
1019       while (n_construct_properties--)
1020         {
1021           GValue *value = construct_params->value;
1022           GParamSpec *pspec = construct_params->pspec;
1023
1024           construct_params++;
1025           object_set_property (object, pspec, value, nqueue);
1026         }
1027       g_object_notify_queue_thaw (object, nqueue);
1028       /* the notification queue is still frozen from g_object_init(), so
1029        * we don't need to handle it here, g_object_newv() takes
1030        * care of that
1031        */
1032     }
1033
1034   return object;
1035 }
1036
1037 void
1038 g_object_set_valist (GObject     *object,
1039                      const gchar *first_property_name,
1040                      va_list      var_args)
1041 {
1042   GObjectNotifyQueue *nqueue;
1043   const gchar *name;
1044   
1045   g_return_if_fail (G_IS_OBJECT (object));
1046   
1047   g_object_ref (object);
1048   nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
1049   
1050   name = first_property_name;
1051   while (name)
1052     {
1053       GValue value = { 0, };
1054       GParamSpec *pspec;
1055       gchar *error = NULL;
1056       
1057       pspec = g_param_spec_pool_lookup (pspec_pool,
1058                                         name,
1059                                         G_OBJECT_TYPE (object),
1060                                         TRUE);
1061       if (!pspec)
1062         {
1063           g_warning ("%s: object class `%s' has no property named `%s'",
1064                      G_STRFUNC,
1065                      G_OBJECT_TYPE_NAME (object),
1066                      name);
1067           break;
1068         }
1069       if (!(pspec->flags & G_PARAM_WRITABLE))
1070         {
1071           g_warning ("%s: property `%s' of object class `%s' is not writable",
1072                      G_STRFUNC,
1073                      pspec->name,
1074                      G_OBJECT_TYPE_NAME (object));
1075           break;
1076         }
1077       if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction (object))
1078         {
1079           g_warning ("%s: construct property \"%s\" for object `%s' can't be set after construction",
1080                      G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
1081           break;
1082         }
1083
1084       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1085       
1086       G_VALUE_COLLECT (&value, var_args, 0, &error);
1087       if (error)
1088         {
1089           g_warning ("%s: %s", G_STRFUNC, error);
1090           g_free (error);
1091           g_value_unset (&value);
1092           break;
1093         }
1094       
1095       object_set_property (object, pspec, &value, nqueue);
1096       g_value_unset (&value);
1097       
1098       name = va_arg (var_args, gchar*);
1099     }
1100
1101   g_object_notify_queue_thaw (object, nqueue);
1102   g_object_unref (object);
1103 }
1104
1105 void
1106 g_object_get_valist (GObject     *object,
1107                      const gchar *first_property_name,
1108                      va_list      var_args)
1109 {
1110   const gchar *name;
1111   
1112   g_return_if_fail (G_IS_OBJECT (object));
1113   
1114   g_object_ref (object);
1115   
1116   name = first_property_name;
1117   
1118   while (name)
1119     {
1120       GValue value = { 0, };
1121       GParamSpec *pspec;
1122       gchar *error;
1123       
1124       pspec = g_param_spec_pool_lookup (pspec_pool,
1125                                         name,
1126                                         G_OBJECT_TYPE (object),
1127                                         TRUE);
1128       if (!pspec)
1129         {
1130           g_warning ("%s: object class `%s' has no property named `%s'",
1131                      G_STRFUNC,
1132                      G_OBJECT_TYPE_NAME (object),
1133                      name);
1134           break;
1135         }
1136       if (!(pspec->flags & G_PARAM_READABLE))
1137         {
1138           g_warning ("%s: property `%s' of object class `%s' is not readable",
1139                      G_STRFUNC,
1140                      pspec->name,
1141                      G_OBJECT_TYPE_NAME (object));
1142           break;
1143         }
1144       
1145       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1146       
1147       object_get_property (object, pspec, &value);
1148       
1149       G_VALUE_LCOPY (&value, var_args, 0, &error);
1150       if (error)
1151         {
1152           g_warning ("%s: %s", G_STRFUNC, error);
1153           g_free (error);
1154           g_value_unset (&value);
1155           break;
1156         }
1157       
1158       g_value_unset (&value);
1159       
1160       name = va_arg (var_args, gchar*);
1161     }
1162   
1163   g_object_unref (object);
1164 }
1165
1166 void
1167 g_object_set (gpointer     _object,
1168               const gchar *first_property_name,
1169               ...)
1170 {
1171   GObject *object = _object;
1172   va_list var_args;
1173   
1174   g_return_if_fail (G_IS_OBJECT (object));
1175   
1176   va_start (var_args, first_property_name);
1177   g_object_set_valist (object, first_property_name, var_args);
1178   va_end (var_args);
1179 }
1180
1181 void
1182 g_object_get (gpointer     _object,
1183               const gchar *first_property_name,
1184               ...)
1185 {
1186   GObject *object = _object;
1187   va_list var_args;
1188   
1189   g_return_if_fail (G_IS_OBJECT (object));
1190   
1191   va_start (var_args, first_property_name);
1192   g_object_get_valist (object, first_property_name, var_args);
1193   va_end (var_args);
1194 }
1195
1196 void
1197 g_object_set_property (GObject      *object,
1198                        const gchar  *property_name,
1199                        const GValue *value)
1200 {
1201   GObjectNotifyQueue *nqueue;
1202   GParamSpec *pspec;
1203   
1204   g_return_if_fail (G_IS_OBJECT (object));
1205   g_return_if_fail (property_name != NULL);
1206   g_return_if_fail (G_IS_VALUE (value));
1207   
1208   g_object_ref (object);
1209   nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
1210   
1211   pspec = g_param_spec_pool_lookup (pspec_pool,
1212                                     property_name,
1213                                     G_OBJECT_TYPE (object),
1214                                     TRUE);
1215   if (!pspec)
1216     g_warning ("%s: object class `%s' has no property named `%s'",
1217                G_STRFUNC,
1218                G_OBJECT_TYPE_NAME (object),
1219                property_name);
1220   else if (!(pspec->flags & G_PARAM_WRITABLE))
1221     g_warning ("%s: property `%s' of object class `%s' is not writable",
1222                G_STRFUNC,
1223                pspec->name,
1224                G_OBJECT_TYPE_NAME (object));
1225   else if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction (object))
1226     g_warning ("%s: construct property \"%s\" for object `%s' can't be set after construction",
1227                G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
1228   else
1229     object_set_property (object, pspec, value, nqueue);
1230   
1231   g_object_notify_queue_thaw (object, nqueue);
1232   g_object_unref (object);
1233 }
1234
1235 void
1236 g_object_get_property (GObject     *object,
1237                        const gchar *property_name,
1238                        GValue      *value)
1239 {
1240   GParamSpec *pspec;
1241   
1242   g_return_if_fail (G_IS_OBJECT (object));
1243   g_return_if_fail (property_name != NULL);
1244   g_return_if_fail (G_IS_VALUE (value));
1245   
1246   g_object_ref (object);
1247   
1248   pspec = g_param_spec_pool_lookup (pspec_pool,
1249                                     property_name,
1250                                     G_OBJECT_TYPE (object),
1251                                     TRUE);
1252   if (!pspec)
1253     g_warning ("%s: object class `%s' has no property named `%s'",
1254                G_STRFUNC,
1255                G_OBJECT_TYPE_NAME (object),
1256                property_name);
1257   else if (!(pspec->flags & G_PARAM_READABLE))
1258     g_warning ("%s: property `%s' of object class `%s' is not readable",
1259                G_STRFUNC,
1260                pspec->name,
1261                G_OBJECT_TYPE_NAME (object));
1262   else
1263     {
1264       GValue *prop_value, tmp_value = { 0, };
1265       
1266       /* auto-conversion of the callers value type
1267        */
1268       if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
1269         {
1270           g_value_reset (value);
1271           prop_value = value;
1272         }
1273       else if (!g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
1274         {
1275           g_warning ("%s: can't retrieve property `%s' of type `%s' as value of type `%s'",
1276                      G_STRFUNC, pspec->name,
1277                      g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1278                      G_VALUE_TYPE_NAME (value));
1279           g_object_unref (object);
1280           return;
1281         }
1282       else
1283         {
1284           g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1285           prop_value = &tmp_value;
1286         }
1287       object_get_property (object, pspec, prop_value);
1288       if (prop_value != value)
1289         {
1290           g_value_transform (prop_value, value);
1291           g_value_unset (&tmp_value);
1292         }
1293     }
1294   
1295   g_object_unref (object);
1296 }
1297
1298 gpointer
1299 g_object_connect (gpointer     _object,
1300                   const gchar *signal_spec,
1301                   ...)
1302 {
1303   GObject *object = _object;
1304   va_list var_args;
1305
1306   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1307   g_return_val_if_fail (object->ref_count > 0, object);
1308
1309   va_start (var_args, signal_spec);
1310   while (signal_spec)
1311     {
1312       GCallback callback = va_arg (var_args, GCallback);
1313       gpointer data = va_arg (var_args, gpointer);
1314       gulong sid;
1315
1316       if (strncmp (signal_spec, "signal::", 8) == 0)
1317         sid = g_signal_connect_data (object, signal_spec + 8,
1318                                      callback, data, NULL,
1319                                      0);
1320       else if (strncmp (signal_spec, "object_signal::", 15) == 0 ||
1321                strncmp (signal_spec, "object-signal::", 15) == 0)
1322         sid = g_signal_connect_object (object, signal_spec + 15,
1323                                        callback, data,
1324                                        0);
1325       else if (strncmp (signal_spec, "swapped_signal::", 16) == 0 ||
1326                strncmp (signal_spec, "swapped-signal::", 16) == 0)
1327         sid = g_signal_connect_data (object, signal_spec + 16,
1328                                      callback, data, NULL,
1329                                      G_CONNECT_SWAPPED);
1330       else if (strncmp (signal_spec, "swapped_object_signal::", 23) == 0 ||
1331                strncmp (signal_spec, "swapped-object-signal::", 23) == 0)
1332         sid = g_signal_connect_object (object, signal_spec + 23,
1333                                        callback, data,
1334                                        G_CONNECT_SWAPPED);
1335       else if (strncmp (signal_spec, "signal_after::", 14) == 0 ||
1336                strncmp (signal_spec, "signal-after::", 14) == 0)
1337         sid = g_signal_connect_data (object, signal_spec + 14,
1338                                      callback, data, NULL,
1339                                      G_CONNECT_AFTER);
1340       else if (strncmp (signal_spec, "object_signal_after::", 21) == 0 ||
1341                strncmp (signal_spec, "object-signal-after::", 21) == 0)
1342         sid = g_signal_connect_object (object, signal_spec + 21,
1343                                        callback, data,
1344                                        G_CONNECT_AFTER);
1345       else if (strncmp (signal_spec, "swapped_signal_after::", 22) == 0 ||
1346                strncmp (signal_spec, "swapped-signal-after::", 22) == 0)
1347         sid = g_signal_connect_data (object, signal_spec + 22,
1348                                      callback, data, NULL,
1349                                      G_CONNECT_SWAPPED | G_CONNECT_AFTER);
1350       else if (strncmp (signal_spec, "swapped_object_signal_after::", 29) == 0 ||
1351                strncmp (signal_spec, "swapped-object-signal-after::", 29) == 0)
1352         sid = g_signal_connect_object (object, signal_spec + 29,
1353                                        callback, data,
1354                                        G_CONNECT_SWAPPED | G_CONNECT_AFTER);
1355       else
1356         {
1357           g_warning ("%s: invalid signal spec \"%s\"", G_STRFUNC, signal_spec);
1358           break;
1359         }
1360       signal_spec = va_arg (var_args, gchar*);
1361     }
1362   va_end (var_args);
1363
1364   return object;
1365 }
1366
1367 void
1368 g_object_disconnect (gpointer     _object,
1369                      const gchar *signal_spec,
1370                      ...)
1371 {
1372   GObject *object = _object;
1373   va_list var_args;
1374
1375   g_return_if_fail (G_IS_OBJECT (object));
1376   g_return_if_fail (object->ref_count > 0);
1377
1378   va_start (var_args, signal_spec);
1379   while (signal_spec)
1380     {
1381       GCallback callback = va_arg (var_args, GCallback);
1382       gpointer data = va_arg (var_args, gpointer);
1383       guint sid = 0, detail = 0, mask = 0;
1384
1385       if (strncmp (signal_spec, "any_signal::", 12) == 0 ||
1386           strncmp (signal_spec, "any-signal::", 12) == 0)
1387         {
1388           signal_spec += 12;
1389           mask = G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA;
1390         }
1391       else if (strcmp (signal_spec, "any_signal") == 0 ||
1392                strcmp (signal_spec, "any-signal") == 0)
1393         {
1394           signal_spec += 10;
1395           mask = G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA;
1396         }
1397       else
1398         {
1399           g_warning ("%s: invalid signal spec \"%s\"", G_STRFUNC, signal_spec);
1400           break;
1401         }
1402
1403       if ((mask & G_SIGNAL_MATCH_ID) &&
1404           !g_signal_parse_name (signal_spec, G_OBJECT_TYPE (object), &sid, &detail, FALSE))
1405         g_warning ("%s: invalid signal name \"%s\"", G_STRFUNC, signal_spec);
1406       else if (!g_signal_handlers_disconnect_matched (object, mask | (detail ? G_SIGNAL_MATCH_DETAIL : 0),
1407                                                       sid, detail,
1408                                                       NULL, (gpointer)callback, data))
1409         g_warning ("%s: signal handler %p(%p) is not connected", G_STRFUNC, callback, data);
1410       signal_spec = va_arg (var_args, gchar*);
1411     }
1412   va_end (var_args);
1413 }
1414
1415 typedef struct {
1416   GObject *object;
1417   guint n_weak_refs;
1418   struct {
1419     GWeakNotify notify;
1420     gpointer    data;
1421   } weak_refs[1];  /* flexible array */
1422 } WeakRefStack;
1423
1424 static void
1425 weak_refs_notify (gpointer data)
1426 {
1427   WeakRefStack *wstack = data;
1428   guint i;
1429
1430   for (i = 0; i < wstack->n_weak_refs; i++)
1431     wstack->weak_refs[i].notify (wstack->weak_refs[i].data, wstack->object);
1432   g_free (wstack);
1433 }
1434
1435 void
1436 g_object_weak_ref (GObject    *object,
1437                    GWeakNotify notify,
1438                    gpointer    data)
1439 {
1440   WeakRefStack *wstack;
1441   guint i;
1442   
1443   g_return_if_fail (G_IS_OBJECT (object));
1444   g_return_if_fail (notify != NULL);
1445   g_return_if_fail (object->ref_count >= 1);
1446
1447   wstack = g_datalist_id_remove_no_notify (&object->qdata, quark_weak_refs);
1448   if (wstack)
1449     {
1450       i = wstack->n_weak_refs++;
1451       wstack = g_realloc (wstack, sizeof (*wstack) + sizeof (wstack->weak_refs[0]) * i);
1452     }
1453   else
1454     {
1455       wstack = g_renew (WeakRefStack, NULL, 1);
1456       wstack->object = object;
1457       wstack->n_weak_refs = 1;
1458       i = 0;
1459     }
1460   wstack->weak_refs[i].notify = notify;
1461   wstack->weak_refs[i].data = data;
1462   g_datalist_id_set_data_full (&object->qdata, quark_weak_refs, wstack, weak_refs_notify);
1463 }
1464
1465 void
1466 g_object_weak_unref (GObject    *object,
1467                      GWeakNotify notify,
1468                      gpointer    data)
1469 {
1470   WeakRefStack *wstack;
1471   gboolean found_one = FALSE;
1472
1473   g_return_if_fail (G_IS_OBJECT (object));
1474   g_return_if_fail (notify != NULL);
1475
1476   wstack = g_datalist_id_get_data (&object->qdata, quark_weak_refs);
1477   if (wstack)
1478     {
1479       guint i;
1480
1481       for (i = 0; i < wstack->n_weak_refs; i++)
1482         if (wstack->weak_refs[i].notify == notify &&
1483             wstack->weak_refs[i].data == data)
1484           {
1485             found_one = TRUE;
1486             wstack->n_weak_refs -= 1;
1487             if (i != wstack->n_weak_refs)
1488               wstack->weak_refs[i] = wstack->weak_refs[wstack->n_weak_refs];
1489
1490             break;
1491           }
1492     }
1493   if (!found_one)
1494     g_warning ("%s: couldn't find weak ref %p(%p)", G_STRFUNC, notify, data);
1495 }
1496
1497 void
1498 g_object_add_weak_pointer (GObject  *object, 
1499                            gpointer *weak_pointer_location)
1500 {
1501   g_return_if_fail (G_IS_OBJECT (object));
1502   g_return_if_fail (weak_pointer_location != NULL);
1503
1504   g_object_weak_ref (object, 
1505                      (GWeakNotify) g_nullify_pointer, 
1506                      weak_pointer_location);
1507 }
1508
1509 void
1510 g_object_remove_weak_pointer (GObject  *object, 
1511                               gpointer *weak_pointer_location)
1512 {
1513   g_return_if_fail (G_IS_OBJECT (object));
1514   g_return_if_fail (weak_pointer_location != NULL);
1515
1516   g_object_weak_unref (object, 
1517                        (GWeakNotify) g_nullify_pointer, 
1518                        weak_pointer_location);
1519 }
1520
1521 typedef struct {
1522   GObject *object;
1523   guint n_toggle_refs;
1524   struct {
1525     GToggleNotify notify;
1526     gpointer    data;
1527   } toggle_refs[1];  /* flexible array */
1528 } ToggleRefStack;
1529
1530 static void
1531 toggle_refs_notify (GObject *object,
1532                     gboolean is_last_ref)
1533 {
1534   ToggleRefStack *tstack = g_datalist_id_get_data (&object->qdata, quark_toggle_refs);
1535
1536   /* Reentrancy here is not as tricky as it seems, because a toggle reference
1537    * will only be notified when there is exactly one of them.
1538    */
1539   g_assert (tstack->n_toggle_refs == 1);
1540   tstack->toggle_refs[0].notify (tstack->toggle_refs[0].data, tstack->object, is_last_ref);
1541 }
1542
1543 void
1544 g_object_add_toggle_ref (GObject       *object,
1545                          GToggleNotify  notify,
1546                          gpointer       data)
1547 {
1548   ToggleRefStack *tstack;
1549   guint i;
1550   
1551   g_return_if_fail (G_IS_OBJECT (object));
1552   g_return_if_fail (notify != NULL);
1553   g_return_if_fail (object->ref_count >= 1);
1554
1555   g_object_ref (object);
1556
1557   tstack = g_datalist_id_remove_no_notify (&object->qdata, quark_toggle_refs);
1558   if (tstack)
1559     {
1560       i = tstack->n_toggle_refs++;
1561       /* allocate i = tstate->n_toggle_refs - 1 positions beyond the 1 declared
1562        * in tstate->toggle_refs */
1563       tstack = g_realloc (tstack, sizeof (*tstack) + sizeof (tstack->toggle_refs[0]) * i);
1564     }
1565   else
1566     {
1567       tstack = g_renew (ToggleRefStack, NULL, 1);
1568       tstack->object = object;
1569       tstack->n_toggle_refs = 1;
1570       i = 0;
1571     }
1572
1573   /* Set a flag for fast lookup after adding the first toggle reference */
1574   if (tstack->n_toggle_refs == 1)
1575     g_datalist_set_flags (&object->qdata, OBJECT_HAS_TOGGLE_REF_FLAG);
1576   
1577   tstack->toggle_refs[i].notify = notify;
1578   tstack->toggle_refs[i].data = data;
1579   g_datalist_id_set_data_full (&object->qdata, quark_toggle_refs, tstack,
1580                                (GDestroyNotify)g_free);
1581 }
1582  
1583 void
1584 g_object_remove_toggle_ref (GObject       *object,
1585                             GToggleNotify  notify,
1586                             gpointer       data)
1587 {
1588   ToggleRefStack *tstack;
1589   gboolean found_one = FALSE;
1590
1591   g_return_if_fail (G_IS_OBJECT (object));
1592   g_return_if_fail (notify != NULL);
1593
1594   tstack = g_datalist_id_get_data (&object->qdata, quark_toggle_refs);
1595   if (tstack)
1596     {
1597       guint i;
1598
1599       for (i = 0; i < tstack->n_toggle_refs; i++)
1600         if (tstack->toggle_refs[i].notify == notify &&
1601             tstack->toggle_refs[i].data == data)
1602           {
1603             found_one = TRUE;
1604             tstack->n_toggle_refs -= 1;
1605             if (i != tstack->n_toggle_refs)
1606               tstack->toggle_refs[i] = tstack->toggle_refs[tstack->n_toggle_refs];
1607
1608             if (tstack->n_toggle_refs == 0)
1609               g_datalist_unset_flags (&object->qdata, OBJECT_HAS_TOGGLE_REF_FLAG);
1610
1611             g_object_unref (object);
1612             
1613             break;
1614           }
1615     }
1616   
1617   if (!found_one)
1618     g_warning ("%s: couldn't find toggle ref %p(%p)", G_STRFUNC, notify, data);
1619 }
1620
1621 gpointer
1622 g_object_ref (gpointer _object)
1623 {
1624   GObject *object = _object;
1625   gint old_val;
1626
1627   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1628   g_return_val_if_fail (object->ref_count > 0, NULL);
1629   
1630 #ifdef  G_ENABLE_DEBUG
1631   if (g_trap_object_ref == object)
1632     G_BREAKPOINT ();
1633 #endif  /* G_ENABLE_DEBUG */
1634
1635
1636   old_val = g_atomic_int_exchange_and_add (&object->ref_count, 1);
1637
1638   if (old_val == 1 && OBJECT_HAS_TOGGLE_REF (object))
1639     toggle_refs_notify (object, FALSE);
1640   
1641   return object;
1642 }
1643
1644 void
1645 g_object_unref (gpointer _object)
1646 {
1647   GObject *object = _object;
1648   gint old_ref;
1649   gboolean is_zero;
1650   
1651   g_return_if_fail (G_IS_OBJECT (object));
1652   g_return_if_fail (object->ref_count > 0);
1653   
1654 #ifdef  G_ENABLE_DEBUG
1655   if (g_trap_object_ref == object)
1656     G_BREAKPOINT ();
1657 #endif  /* G_ENABLE_DEBUG */
1658
1659   /* here we want to atomically do: if (ref_count>1) { ref_count--; return; } */
1660  retry_atomic_decrement1:
1661   old_ref = g_atomic_int_get (&object->ref_count);
1662   if (old_ref > 1)
1663     {
1664       if (!g_atomic_int_compare_and_exchange (&object->ref_count, old_ref, old_ref - 1))
1665         goto retry_atomic_decrement1;
1666
1667       /* if we went from 2->1 we need to notify toggle refs if any */
1668       if (old_ref == 2 && OBJECT_HAS_TOGGLE_REF (object))
1669         toggle_refs_notify (object, TRUE);
1670     }
1671   else
1672     {
1673       /* we are about tp remove the last reference */
1674       G_OBJECT_GET_CLASS (object)->dispose (object);
1675
1676       /* may have been re-referenced meanwhile */
1677     retry_atomic_decrement2:
1678       old_ref = g_atomic_int_get (&object->ref_count);
1679       if (old_ref > 1)
1680         {
1681           if (!g_atomic_int_compare_and_exchange (&object->ref_count, old_ref, old_ref - 1))
1682             goto retry_atomic_decrement2;
1683
1684           /* if we went from 2->1 we need to notify toggle refs if any */
1685           if (old_ref == 2 && OBJECT_HAS_TOGGLE_REF (object))
1686             toggle_refs_notify (object, TRUE);
1687           
1688           return;
1689         }
1690       
1691       /* we are still in the process of taking away the last ref */
1692       g_datalist_id_set_data (&object->qdata, quark_closure_array, NULL);
1693       g_signal_handlers_destroy (object);
1694       g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL);
1695       
1696       /* decrement the last reference */
1697       is_zero = g_atomic_int_dec_and_test (&object->ref_count);
1698       
1699       /* may have been re-referenced meanwhile */
1700       if (G_LIKELY (is_zero)) 
1701         {
1702           G_OBJECT_GET_CLASS (object)->finalize (object);
1703 #ifdef  G_ENABLE_DEBUG
1704           IF_DEBUG (OBJECTS)
1705             {
1706               /* catch objects not chaining finalize handlers */
1707               G_LOCK (debug_objects);
1708               g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
1709               G_UNLOCK (debug_objects);
1710             }
1711 #endif  /* G_ENABLE_DEBUG */
1712           g_type_free_instance ((GTypeInstance*) object);
1713         }
1714     }
1715 }
1716
1717 gpointer
1718 g_object_get_qdata (GObject *object,
1719                     GQuark   quark)
1720 {
1721   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1722   
1723   return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1724 }
1725
1726 void
1727 g_object_set_qdata (GObject *object,
1728                     GQuark   quark,
1729                     gpointer data)
1730 {
1731   g_return_if_fail (G_IS_OBJECT (object));
1732   g_return_if_fail (quark > 0);
1733   
1734   g_datalist_id_set_data (&object->qdata, quark, data);
1735 }
1736
1737 void
1738 g_object_set_qdata_full (GObject       *object,
1739                          GQuark         quark,
1740                          gpointer       data,
1741                          GDestroyNotify destroy)
1742 {
1743   g_return_if_fail (G_IS_OBJECT (object));
1744   g_return_if_fail (quark > 0);
1745   
1746   g_datalist_id_set_data_full (&object->qdata, quark, data,
1747                                data ? destroy : (GDestroyNotify) NULL);
1748 }
1749
1750 gpointer
1751 g_object_steal_qdata (GObject *object,
1752                       GQuark   quark)
1753 {
1754   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1755   g_return_val_if_fail (quark > 0, NULL);
1756   
1757   return g_datalist_id_remove_no_notify (&object->qdata, quark);
1758 }
1759
1760 gpointer
1761 g_object_get_data (GObject     *object,
1762                    const gchar *key)
1763 {
1764   GQuark quark;
1765
1766   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1767   g_return_val_if_fail (key != NULL, NULL);
1768
1769   quark = g_quark_try_string (key);
1770
1771   return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1772 }
1773
1774 void
1775 g_object_set_data (GObject     *object,
1776                    const gchar *key,
1777                    gpointer     data)
1778 {
1779   g_return_if_fail (G_IS_OBJECT (object));
1780   g_return_if_fail (key != NULL);
1781
1782   g_datalist_id_set_data (&object->qdata, g_quark_from_string (key), data);
1783 }
1784
1785 void
1786 g_object_set_data_full (GObject       *object,
1787                         const gchar   *key,
1788                         gpointer       data,
1789                         GDestroyNotify destroy)
1790 {
1791   g_return_if_fail (G_IS_OBJECT (object));
1792   g_return_if_fail (key != NULL);
1793
1794   g_datalist_id_set_data_full (&object->qdata, g_quark_from_string (key), data,
1795                                data ? destroy : (GDestroyNotify) NULL);
1796 }
1797
1798 gpointer
1799 g_object_steal_data (GObject     *object,
1800                      const gchar *key)
1801 {
1802   GQuark quark;
1803
1804   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1805   g_return_val_if_fail (key != NULL, NULL);
1806
1807   quark = g_quark_try_string (key);
1808
1809   return quark ? g_datalist_id_remove_no_notify (&object->qdata, quark) : NULL;
1810 }
1811
1812 static void
1813 g_value_object_init (GValue *value)
1814 {
1815   value->data[0].v_pointer = NULL;
1816 }
1817
1818 static void
1819 g_value_object_free_value (GValue *value)
1820 {
1821   if (value->data[0].v_pointer)
1822     g_object_unref (value->data[0].v_pointer);
1823 }
1824
1825 static void
1826 g_value_object_copy_value (const GValue *src_value,
1827                            GValue       *dest_value)
1828 {
1829   if (src_value->data[0].v_pointer)
1830     dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
1831   else
1832     dest_value->data[0].v_pointer = NULL;
1833 }
1834
1835 static void
1836 g_value_object_transform_value (const GValue *src_value,
1837                                 GValue       *dest_value)
1838 {
1839   if (src_value->data[0].v_pointer && g_type_is_a (G_OBJECT_TYPE (src_value->data[0].v_pointer), G_VALUE_TYPE (dest_value)))
1840     dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
1841   else
1842     dest_value->data[0].v_pointer = NULL;
1843 }
1844
1845 static gpointer
1846 g_value_object_peek_pointer (const GValue *value)
1847 {
1848   return value->data[0].v_pointer;
1849 }
1850
1851 static gchar*
1852 g_value_object_collect_value (GValue      *value,
1853                               guint        n_collect_values,
1854                               GTypeCValue *collect_values,
1855                               guint        collect_flags)
1856 {
1857   if (collect_values[0].v_pointer)
1858     {
1859       GObject *object = collect_values[0].v_pointer;
1860       
1861       if (object->g_type_instance.g_class == NULL)
1862         return g_strconcat ("invalid unclassed object pointer for value type `",
1863                             G_VALUE_TYPE_NAME (value),
1864                             "'",
1865                             NULL);
1866       else if (!g_value_type_compatible (G_OBJECT_TYPE (object), G_VALUE_TYPE (value)))
1867         return g_strconcat ("invalid object type `",
1868                             G_OBJECT_TYPE_NAME (object),
1869                             "' for value type `",
1870                             G_VALUE_TYPE_NAME (value),
1871                             "'",
1872                             NULL);
1873       /* never honour G_VALUE_NOCOPY_CONTENTS for ref-counted types */
1874       value->data[0].v_pointer = g_object_ref (object);
1875     }
1876   else
1877     value->data[0].v_pointer = NULL;
1878   
1879   return NULL;
1880 }
1881
1882 static gchar*
1883 g_value_object_lcopy_value (const GValue *value,
1884                             guint        n_collect_values,
1885                             GTypeCValue *collect_values,
1886                             guint        collect_flags)
1887 {
1888   GObject **object_p = collect_values[0].v_pointer;
1889   
1890   if (!object_p)
1891     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
1892
1893   if (!value->data[0].v_pointer)
1894     *object_p = NULL;
1895   else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
1896     *object_p = value->data[0].v_pointer;
1897   else
1898     *object_p = g_object_ref (value->data[0].v_pointer);
1899   
1900   return NULL;
1901 }
1902
1903 void
1904 g_value_set_object (GValue   *value,
1905                     gpointer  v_object)
1906 {
1907   GObject *old;
1908         
1909   g_return_if_fail (G_VALUE_HOLDS_OBJECT (value));
1910
1911   old = value->data[0].v_pointer;
1912   
1913   if (v_object)
1914     {
1915       g_return_if_fail (G_IS_OBJECT (v_object));
1916       g_return_if_fail (g_value_type_compatible (G_OBJECT_TYPE (v_object), G_VALUE_TYPE (value)));
1917
1918       value->data[0].v_pointer = v_object;
1919       g_object_ref (value->data[0].v_pointer);
1920     }
1921   else
1922     value->data[0].v_pointer = NULL;
1923   
1924   if (old)
1925     g_object_unref (old);
1926 }
1927
1928 void
1929 g_value_set_object_take_ownership (GValue  *value,
1930                                    gpointer v_object)
1931 {
1932   g_value_take_object (value, v_object);
1933 }
1934
1935 void
1936 g_value_take_object (GValue  *value,
1937                      gpointer v_object)
1938 {
1939   g_return_if_fail (G_VALUE_HOLDS_OBJECT (value));
1940
1941   if (value->data[0].v_pointer)
1942     {
1943       g_object_unref (value->data[0].v_pointer);
1944       value->data[0].v_pointer = NULL;
1945     }
1946
1947   if (v_object)
1948     {
1949       g_return_if_fail (G_IS_OBJECT (v_object));
1950       g_return_if_fail (g_value_type_compatible (G_OBJECT_TYPE (v_object), G_VALUE_TYPE (value)));
1951
1952       value->data[0].v_pointer = v_object; /* we take over the reference count */
1953     }
1954 }
1955
1956 gpointer
1957 g_value_get_object (const GValue *value)
1958 {
1959   g_return_val_if_fail (G_VALUE_HOLDS_OBJECT (value), NULL);
1960   
1961   return value->data[0].v_pointer;
1962 }
1963
1964 GObject*
1965 g_value_dup_object (const GValue *value)
1966 {
1967   g_return_val_if_fail (G_VALUE_HOLDS_OBJECT (value), NULL);
1968   
1969   return value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
1970 }
1971
1972 gulong
1973 g_signal_connect_object (gpointer      instance,
1974                          const gchar  *detailed_signal,
1975                          GCallback     c_handler,
1976                          gpointer      gobject,
1977                          GConnectFlags connect_flags)
1978 {
1979   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1980   g_return_val_if_fail (detailed_signal != NULL, 0);
1981   g_return_val_if_fail (c_handler != NULL, 0);
1982
1983   if (gobject)
1984     {
1985       GClosure *closure;
1986
1987       g_return_val_if_fail (G_IS_OBJECT (gobject), 0);
1988
1989       closure = ((connect_flags & G_CONNECT_SWAPPED) ? g_cclosure_new_object_swap : g_cclosure_new_object) (c_handler, gobject);
1990
1991       return g_signal_connect_closure (instance, detailed_signal, closure, connect_flags & G_CONNECT_AFTER);
1992     }
1993   else
1994     return g_signal_connect_data (instance, detailed_signal, c_handler, NULL, NULL, connect_flags);
1995 }
1996
1997 typedef struct {
1998   GObject  *object;
1999   guint     n_closures;
2000   GClosure *closures[1]; /* flexible array */
2001 } CArray;
2002 /* don't change this structure without supplying an accessor for
2003  * watched closures, e.g.:
2004  * GSList* g_object_list_watched_closures (GObject *object)
2005  * {
2006  *   CArray *carray;
2007  *   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
2008  *   carray = g_object_get_data (object, "GObject-closure-array");
2009  *   if (carray)
2010  *     {
2011  *       GSList *slist = NULL;
2012  *       guint i;
2013  *       for (i = 0; i < carray->n_closures; i++)
2014  *         slist = g_slist_prepend (slist, carray->closures[i]);
2015  *       return slist;
2016  *     }
2017  *   return NULL;
2018  * }
2019  */
2020
2021 static void
2022 object_remove_closure (gpointer  data,
2023                        GClosure *closure)
2024 {
2025   GObject *object = data;
2026   CArray *carray = g_object_get_qdata (object, quark_closure_array);
2027   guint i;
2028   
2029   for (i = 0; i < carray->n_closures; i++)
2030     if (carray->closures[i] == closure)
2031       {
2032         carray->n_closures--;
2033         if (i < carray->n_closures)
2034           carray->closures[i] = carray->closures[carray->n_closures];
2035         return;
2036       }
2037   g_assert_not_reached ();
2038 }
2039
2040 static void
2041 destroy_closure_array (gpointer data)
2042 {
2043   CArray *carray = data;
2044   GObject *object = carray->object;
2045   guint i, n = carray->n_closures;
2046   
2047   for (i = 0; i < n; i++)
2048     {
2049       GClosure *closure = carray->closures[i];
2050       
2051       /* removing object_remove_closure() upfront is probably faster than
2052        * letting it fiddle with quark_closure_array which is empty anyways
2053        */
2054       g_closure_remove_invalidate_notifier (closure, object, object_remove_closure);
2055       g_closure_invalidate (closure);
2056     }
2057   g_free (carray);
2058 }
2059
2060 void
2061 g_object_watch_closure (GObject  *object,
2062                         GClosure *closure)
2063 {
2064   CArray *carray;
2065   guint i;
2066   
2067   g_return_if_fail (G_IS_OBJECT (object));
2068   g_return_if_fail (closure != NULL);
2069   g_return_if_fail (closure->is_invalid == FALSE);
2070   g_return_if_fail (closure->in_marshal == FALSE);
2071   g_return_if_fail (object->ref_count > 0);     /* this doesn't work on finalizing objects */
2072   
2073   g_closure_add_invalidate_notifier (closure, object, object_remove_closure);
2074   g_closure_add_marshal_guards (closure,
2075                                 object, (GClosureNotify) g_object_ref,
2076                                 object, (GClosureNotify) g_object_unref);
2077   carray = g_datalist_id_remove_no_notify (&object->qdata, quark_closure_array);
2078   if (!carray)
2079     {
2080       carray = g_renew (CArray, NULL, 1);
2081       carray->object = object;
2082       carray->n_closures = 1;
2083       i = 0;
2084     }
2085   else
2086     {
2087       i = carray->n_closures++;
2088       carray = g_realloc (carray, sizeof (*carray) + sizeof (carray->closures[0]) * i);
2089     }
2090   carray->closures[i] = closure;
2091   g_datalist_id_set_data_full (&object->qdata, quark_closure_array, carray, destroy_closure_array);
2092 }
2093
2094 GClosure*
2095 g_closure_new_object (guint    sizeof_closure,
2096                       GObject *object)
2097 {
2098   GClosure *closure;
2099
2100   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
2101   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
2102
2103   closure = g_closure_new_simple (sizeof_closure, object);
2104   g_object_watch_closure (object, closure);
2105
2106   return closure;
2107 }
2108
2109 GClosure*
2110 g_cclosure_new_object (GCallback callback_func,
2111                        GObject  *object)
2112 {
2113   GClosure *closure;
2114
2115   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
2116   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
2117   g_return_val_if_fail (callback_func != NULL, NULL);
2118
2119   closure = g_cclosure_new (callback_func, object, NULL);
2120   g_object_watch_closure (object, closure);
2121
2122   return closure;
2123 }
2124
2125 GClosure*
2126 g_cclosure_new_object_swap (GCallback callback_func,
2127                             GObject  *object)
2128 {
2129   GClosure *closure;
2130
2131   g_return_val_if_fail (G_IS_OBJECT (object), NULL);
2132   g_return_val_if_fail (object->ref_count > 0, NULL);     /* this doesn't work on finalizing objects */
2133   g_return_val_if_fail (callback_func != NULL, NULL);
2134
2135   closure = g_cclosure_new_swap (callback_func, object, NULL);
2136   g_object_watch_closure (object, closure);
2137
2138   return closure;
2139 }
2140
2141 #define __G_OBJECT_C__
2142 #include "gobjectaliasdef.c"