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