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