1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 1998, 1999, 2000 Tim Janik and Red Hat, Inc.
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.
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.
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.
27 #include "gvaluecollector.h"
29 #include "gparamspecs.h"
30 #include "gvaluetypes.h"
34 #define PREALLOC_CPARAMS (8)
38 #define PARAM_SPEC_PARAM_ID(pspec) (GPOINTER_TO_UINT (g_param_spec_get_qdata ((pspec), quark_property_id)))
49 /* --- properties --- */
56 PROP_SWAPPED_SIGNAL_AFTER
60 /* --- typedefs --- */
61 typedef struct _NotifyQueue NotifyQueue;
64 /* --- prototypes --- */
65 static void g_object_base_class_init (GObjectClass *class);
66 static void g_object_base_class_finalize (GObjectClass *class);
67 static void g_object_do_class_init (GObjectClass *class);
68 static void g_object_init (GObject *object);
69 static GObject* g_object_constructor (GType type,
70 guint n_construct_properties,
71 GObjectConstructParam *construct_params);
72 static void g_object_last_unref (GObject *object);
73 static void g_object_shutdown (GObject *object);
74 static void g_object_finalize (GObject *object);
75 static void g_object_do_set_property (GObject *object,
79 const gchar *trailer);
80 static void g_object_do_get_property (GObject *object,
84 const gchar *trailer);
85 static void g_value_object_init (GValue *value);
86 static void g_value_object_free_value (GValue *value);
87 static void g_value_object_copy_value (const GValue *src_value,
89 static gpointer g_value_object_peek_pointer (const GValue *value);
90 static gchar* g_value_object_collect_value (GValue *value,
93 GTypeCValue *collect_value);
94 static gchar* g_value_object_lcopy_value (const GValue *value,
97 GTypeCValue *collect_value);
98 static void g_object_dispatch_properties_changed (GObject *object,
100 GParamSpec **pspecs);
101 static void g_object_properties_changed (GObject *object,
103 GParamSpec **pspecs);
104 static void g_object_notify_property_changed (GObject *object,
106 static inline NotifyQueue* object_freeze_notifies (GObject *object);
107 static inline void object_queue_property (GObject *object,
109 NotifyQueue *nqueue);
110 static inline void object_thaw_notifies (GObject *object,
111 NotifyQueue *nqueue);
112 static inline void object_get_property (GObject *object,
115 const gchar *trailer);
116 static inline void object_set_property (GObject *object,
119 const gchar *trailer,
120 NotifyQueue *nqueue);
123 /* --- structures --- */
132 /* --- variables --- */
133 static GQuark quark_notify_queue = 0;
134 static GQuark quark_property_id = 0;
135 static GQuark quark_closure_array = 0;
136 static GParamSpecPool *pspec_pool = NULL;
137 static gulong gobject_signals[LAST_SIGNAL] = { 0, };
140 /* --- functions --- */
141 /* We need an actual method for handling debug keys in GLib.
142 * For now, we'll simply use, as a method
143 * 'extern gboolean glib_debug_objects'
145 gboolean glib_debug_objects = FALSE;
147 #ifdef G_ENABLE_DEBUG
148 G_LOCK_DEFINE_STATIC (debug_objects);
149 static volatile GObject *glib_trap_object_ref = NULL;
150 static guint debug_objects_count = 0;
151 static GHashTable *debug_objects_ht = NULL;
153 debug_objects_foreach (gpointer key,
157 GObject *object = value;
159 g_message ("[%p] stale %s\tref_count=%u",
161 G_OBJECT_TYPE_NAME (object),
165 debug_objects_atexit (void)
167 G_LOCK (debug_objects);
168 if (glib_debug_objects)
170 if (debug_objects_ht)
172 g_message ("stale GObjects: %u", debug_objects_count);
173 g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
176 G_UNLOCK (debug_objects);
178 #endif /* G_ENABLE_DEBUG */
181 g_object_type_init (void) /* sync with gtype.c */
183 static gboolean initialized = FALSE;
184 static const GTypeFundamentalInfo finfo = {
185 G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE,
187 static GTypeInfo info = {
188 sizeof (GObjectClass),
189 (GBaseInitFunc) g_object_base_class_init,
190 (GBaseFinalizeFunc) g_object_base_class_finalize,
191 (GClassInitFunc) g_object_do_class_init,
192 NULL /* class_destroy */,
193 NULL /* class_data */,
196 (GInstanceInitFunc) g_object_init,
197 NULL, /* value_table */
199 static const GTypeValueTable value_table = {
200 g_value_object_init, /* value_init */
201 g_value_object_free_value, /* value_free */
202 g_value_object_copy_value, /* value_copy */
203 g_value_object_peek_pointer, /* value_peek_pointer */
204 G_VALUE_COLLECT_POINTER, /* collect_type */
205 g_value_object_collect_value, /* collect_value */
206 G_VALUE_COLLECT_POINTER, /* lcopy_type */
207 g_value_object_lcopy_value, /* lcopy_value */
211 g_return_if_fail (initialized == FALSE);
216 info.value_table = &value_table;
217 type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &info, &finfo, 0);
218 g_assert (type == G_TYPE_OBJECT);
220 #ifdef G_ENABLE_DEBUG
221 g_atexit (debug_objects_atexit);
222 #endif /* G_ENABLE_DEBUG */
226 g_object_base_class_init (GObjectClass *class)
228 GObjectClass *pclass = g_type_class_peek_parent (class);
230 /* reset instance specific fields and methods that don't get inherited */
231 class->n_property_specs = 0;
232 class->property_specs = NULL;
233 class->construct_properties = pclass ? g_slist_copy (pclass->construct_properties) : NULL;
234 class->get_property = NULL;
235 class->set_property = NULL;
239 g_object_base_class_finalize (GObjectClass *class)
243 g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
245 _g_signals_destroy (G_OBJECT_CLASS_TYPE (class));
247 g_slist_free (class->construct_properties);
248 class->construct_properties = NULL;
249 for (i = 0; i < class->n_property_specs; i++)
251 GParamSpec *pspec = class->property_specs[i];
253 g_param_spec_pool_remove (pspec_pool, pspec);
254 g_param_spec_set_qdata (pspec, quark_property_id, NULL);
255 g_param_spec_unref (pspec);
257 class->n_property_specs = 0;
258 g_free (class->property_specs);
259 class->property_specs = NULL;
263 g_object_do_class_init (GObjectClass *class)
265 quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
266 quark_property_id = g_quark_from_static_string ("GObject-property-id");
267 quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
268 pspec_pool = g_param_spec_pool_new (TRUE);
270 class->constructor = g_object_constructor;
271 class->set_property = g_object_do_set_property;
272 class->get_property = g_object_do_get_property;
273 class->shutdown = g_object_shutdown;
274 class->finalize = g_object_finalize;
275 class->dispatch_properties_changed = g_object_dispatch_properties_changed;
276 class->properties_changed = g_object_properties_changed;
277 class->notify = g_object_notify_property_changed;
279 g_object_class_install_property (class,
281 g_param_spec_pointer ("data", "Named Data",
282 "Named anonymous pointers",
283 G_PARAM_READABLE | G_PARAM_WRITABLE));
284 g_object_class_install_property (class,
286 g_param_spec_ccallback ("signal", "Signal Connection",
287 "Signal connection consisting of a callback function "
288 "and a data pointer",
290 g_object_class_install_property (class,
292 g_param_spec_ccallback ("swapped_signal", "Swapped Signal Connection",
293 "Signal connection consisting of a callback function "
294 "and a data pointer",
296 g_object_class_install_property (class,
298 g_param_spec_ccallback ("signal_after", "Signal After Connection",
299 "Signal connection consisting of a callback function "
300 "and a data pointer",
302 g_object_class_install_property (class,
303 PROP_SWAPPED_SIGNAL_AFTER,
304 g_param_spec_ccallback ("swapped_signal_after", "Swapped Signal After Connection",
305 "Signal connection consisting of a callback function "
306 "and a data pointer",
308 gobject_signals[PROPERTIES_CHANGED] =
309 g_signal_newc ("properties_changed",
310 G_TYPE_FROM_CLASS (class),
311 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
312 G_STRUCT_OFFSET (GObjectClass, properties_changed),
313 NULL, /* accumulator */
314 g_cclosure_marshal_VOID__UINT_POINTER,
316 2, G_TYPE_UINT, G_TYPE_POINTER);
317 gobject_signals[NOTIFY] =
318 g_signal_newc ("notify",
319 G_TYPE_FROM_CLASS (class),
320 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
321 G_STRUCT_OFFSET (GObjectClass, notify),
322 NULL, /* accumulator */
323 g_cclosure_marshal_VOID__PARAM,
329 g_object_class_install_property (GObjectClass *class,
335 g_return_if_fail (G_IS_OBJECT_CLASS (class));
336 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
337 if (pspec->flags & G_PARAM_WRITABLE)
338 g_return_if_fail (class->set_property != NULL);
339 if (pspec->flags & G_PARAM_READABLE)
340 g_return_if_fail (class->get_property != NULL);
341 g_return_if_fail (property_id > 0);
342 g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
343 if (pspec->flags & G_PARAM_CONSTRUCT)
344 g_return_if_fail ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
345 if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
346 g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
348 /* expensive paranoia checks ;( */
349 for (i = 0; i < class->n_property_specs; i++)
350 if (PARAM_SPEC_PARAM_ID (class->property_specs[i]) == property_id)
352 g_warning (G_STRLOC ": class `%s' already contains a property `%s' with id %u, "
353 "cannot install property `%s'",
354 G_OBJECT_CLASS_NAME (class),
355 class->property_specs[i]->name,
360 if (g_param_spec_pool_lookup (pspec_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE, NULL))
362 g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
363 G_OBJECT_CLASS_NAME (class),
368 g_param_spec_ref (pspec);
369 g_param_spec_sink (pspec);
370 g_param_spec_set_qdata (pspec, quark_property_id, GUINT_TO_POINTER (property_id));
371 g_param_spec_pool_insert (pspec_pool, pspec, G_OBJECT_CLASS_TYPE (class));
372 i = class->n_property_specs++;
373 class->property_specs = g_renew (GParamSpec*, class->property_specs, class->n_property_specs);
374 class->property_specs[i] = pspec;
375 if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
376 class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
378 /* for property overrides of construct poperties, we have to get rid
379 * of the overidden inherited construct property
381 pspec = g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type_parent (G_OBJECT_CLASS_TYPE (class)), TRUE, NULL);
382 if (pspec && pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
383 class->construct_properties = g_slist_remove (class->construct_properties, pspec);
387 g_object_class_find_property (GObjectClass *class,
388 const gchar *property_name)
390 g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
391 g_return_val_if_fail (property_name != NULL, NULL);
393 return g_param_spec_pool_lookup (pspec_pool,
395 G_OBJECT_CLASS_TYPE (class),
400 free_notify_queue (gpointer data)
402 NotifyQueue *nqueue = data;
404 g_slist_free (nqueue->pspecs);
408 static inline NotifyQueue*
409 object_freeze_notifies (GObject *object)
413 nqueue = g_object_get_qdata (object, quark_notify_queue);
416 nqueue = g_new0 (NotifyQueue, 1);
417 g_object_set_qdata_full (object, quark_notify_queue, nqueue, free_notify_queue);
419 nqueue->freeze_count++;
425 object_queue_property (GObject *object,
429 /* we will dedup later */
430 nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
435 g_object_init (GObject *object)
437 object->ref_count = 1;
438 g_datalist_init (&object->qdata);
440 /* freeze object's notification queue, g_object_new_valist() takes care of that */
441 object_freeze_notifies (object);
443 #ifdef G_ENABLE_DEBUG
444 G_LOCK (debug_objects);
445 if (glib_debug_objects)
447 if (!debug_objects_ht)
448 debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
449 debug_objects_count++;
450 g_hash_table_insert (debug_objects_ht, object, object);
452 G_UNLOCK (debug_objects);
453 #endif /* G_ENABLE_DEBUG */
457 g_object_do_set_property (GObject *object,
461 const gchar *trailer)
467 gboolean swapped, after;
468 gpointer callback, data;
470 g_return_if_fail (trailer != NULL);
472 g_object_set_data (object, trailer, g_value_get_pointer (value));
474 case PROP_SWAPPED_SIGNAL_AFTER:
476 case PROP_SIGNAL_AFTER:
478 case PROP_SWAPPED_SIGNAL:
483 g_return_if_fail (trailer != NULL);
485 g_value_get_ccallback (value, &callback, &data);
486 g_signal_connect_data (object, trailer,
487 callback, data, NULL,
491 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
497 g_object_do_get_property (GObject *object,
501 const gchar *trailer)
506 g_return_if_fail (trailer != NULL);
508 g_value_set_pointer (value, g_object_get_data (object, trailer));
511 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
517 g_object_last_unref (GObject *object)
519 g_return_if_fail (object->ref_count > 0);
521 if (object->ref_count == 1) /* may have been re-referenced meanwhile */
522 G_OBJECT_GET_CLASS (object)->shutdown (object);
524 #ifdef G_ENABLE_DEBUG
525 if (glib_trap_object_ref == object)
527 #endif /* G_ENABLE_DEBUG */
529 object->ref_count -= 1;
531 if (object->ref_count == 0) /* may have been re-referenced meanwhile */
533 G_OBJECT_GET_CLASS (object)->finalize (object);
534 #ifdef G_ENABLE_DEBUG
535 G_LOCK (debug_objects);
536 if (glib_debug_objects && debug_objects_ht)
537 g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
538 G_UNLOCK (debug_objects);
539 #endif /* G_ENABLE_DEBUG */
540 g_type_free_instance ((GTypeInstance*) object);
545 g_object_shutdown (GObject *object)
547 /* this function needs to be always present for unconditional
548 * chaining, we also might add some code here later.
549 * beware though, subclasses may invoke shutdown() arbitrarily.
554 g_object_finalize (GObject *object)
556 g_signal_handlers_destroy (object);
557 g_datalist_clear (&object->qdata);
559 #ifdef G_ENABLE_DEBUG
560 G_LOCK (debug_objects);
561 if (glib_debug_objects)
563 g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
565 g_hash_table_remove (debug_objects_ht, object);
566 debug_objects_count--;
568 G_UNLOCK (debug_objects);
569 #endif /* G_ENABLE_DEBUG */
573 object_thaw_notifies (GObject *object,
580 nqueue->freeze_count--;
581 if (nqueue->freeze_count)
583 g_return_if_fail (object->ref_count > 0);
585 pspecs = g_new (GParamSpec*, nqueue->n_pspecs);
586 for (slist = nqueue->pspecs; slist; slist = slist->next)
588 GParamSpec *pspec = slist->data;
591 /* dedup, make pspecs in the list unique */
593 if (pspecs[i] == pspec)
596 goto redo_dedup_check;
598 pspecs[n_pspecs++] = pspec;
600 g_object_set_qdata (object, quark_notify_queue, NULL);
603 G_OBJECT_GET_CLASS (object)->dispatch_properties_changed (object, n_pspecs, pspecs);
609 g_object_dispatch_properties_changed (GObject *object,
613 g_signal_emit (object, gobject_signals[PROPERTIES_CHANGED], 0, n_pspecs, pspecs);
617 g_object_properties_changed (GObject *object,
623 for (i = 0; i < n_pspecs; i++)
624 g_signal_emit (object, gobject_signals[NOTIFY], g_quark_from_string (pspecs[i]->name), pspecs[i]);
628 g_object_notify_property_changed (GObject *object,
632 g_message ("NOTIFICATION: property `%s' changed on object `%s'",
634 G_OBJECT_TYPE_NAME (object));
638 g_object_freeze_notify (GObject *object)
640 g_return_if_fail (G_IS_OBJECT (object));
641 if (!object->ref_count)
644 g_object_ref (object);
645 object_freeze_notifies (object);
646 g_object_unref (object);
650 g_object_notify (GObject *object,
651 const gchar *property_name)
655 g_return_if_fail (G_IS_OBJECT (object));
656 g_return_if_fail (property_name != NULL);
657 if (!object->ref_count)
660 g_object_ref (object);
661 pspec = g_param_spec_pool_lookup (pspec_pool,
663 G_OBJECT_TYPE (object),
666 g_warning ("%s: object class `%s' has no property named `%s'",
668 G_OBJECT_TYPE_NAME (object),
672 NotifyQueue *nqueue = object_freeze_notifies (object);
674 object_queue_property (object, pspec, nqueue);
675 object_thaw_notifies (object, nqueue);
677 g_object_unref (object);
681 g_object_thaw_notify (GObject *object)
685 g_return_if_fail (G_IS_OBJECT (object));
686 if (!object->ref_count)
689 g_object_ref (object);
690 nqueue = g_object_get_qdata (object, quark_notify_queue);
691 if (!nqueue || !nqueue->freeze_count)
692 g_warning (G_STRLOC ": property-changed notification for %s(%p) is not frozen",
693 G_OBJECT_TYPE_NAME (object), object);
695 object_thaw_notifies (object, nqueue);
696 g_object_unref (object);
700 object_get_property (GObject *object,
703 const gchar *trailer)
707 g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type)); /* paranoid */
709 class = g_type_class_peek (pspec->owner_type);
711 class->get_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
715 object_set_property (GObject *object,
718 const gchar *trailer,
723 g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type)); /* paranoid */
725 class = g_type_class_peek (pspec->owner_type);
727 class->set_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
728 object_queue_property (object, pspec, nqueue);
732 g_object_new (GType object_type,
733 const gchar *first_property_name,
739 g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
741 va_start (var_args, first_property_name);
742 object = g_object_new_valist (object_type, first_property_name, var_args);
749 g_object_new_valist (GType object_type,
750 const gchar *first_property_name,
757 GObjectConstructParam *cparams = NULL, *nparams = NULL;
758 guint n_cparams = 0, n_nparams = 0;
761 g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
763 class = g_type_class_ref (object_type);
764 clist = g_slist_copy (class->construct_properties);
766 /* collect parameters, sort into construction and normal ones */
767 name = first_property_name;
770 const gchar *trailer = NULL;
775 pspec = g_param_spec_pool_lookup (pspec_pool,
782 g_warning ("%s: object class `%s' has no property named `%s'",
784 g_type_name (object_type),
788 if (!(pspec->flags & G_PARAM_WRITABLE))
790 g_warning ("%s: property `%s' of object class `%s' is not writable",
793 g_type_name (object_type));
797 value = g_new (GValue, 1);
799 g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
800 G_VALUE_COLLECT (value, var_args, &error);
803 g_warning ("%s: %s", G_STRLOC, error);
806 /* we purposely leak the value here, it might not be
807 * in a sane state if an error condition occoured
811 if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
815 if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
816 cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
817 cparams[n_cparams].pspec = pspec;
818 cparams[n_cparams].value = value;
819 cparams[n_cparams].trailer = trailer;
820 for (i = 0; i < n_cparams; i++) /* picky, aren't we? ;) */
821 if (cparams[i].pspec == pspec)
822 g_warning (G_STRLOC ": construct property \"%s\" for object `%s' is being set twice",
823 pspec->name, g_type_name (object_type));
825 clist = g_slist_remove (clist, pspec); /* FIXME: unique */
829 if (!n_nparams || n_nparams >= PREALLOC_CPARAMS)
830 nparams = g_renew (GObjectConstructParam, nparams, MAX (n_nparams + 1, PREALLOC_CPARAMS));
831 nparams[n_nparams].pspec = pspec;
832 nparams[n_nparams].value = value;
833 nparams[n_nparams].trailer = trailer;
837 name = va_arg (var_args, gchar*);
840 /* construct object from construction parameters */
843 GSList *tmp = clist->next;
844 GParamSpec *pspec = clist->data;
845 GValue *value = g_new (GValue, 1);
848 g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
849 g_param_value_set_default (pspec, value);
851 if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
852 cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
853 cparams[n_cparams].pspec = pspec;
854 cparams[n_cparams].value = value;
855 cparams[n_cparams].trailer = NULL;
858 g_slist_free_1 (clist);
861 object = class->constructor (object_type, n_cparams, cparams);
863 /* free construction values */
866 g_value_unset (cparams[n_cparams].value);
867 g_free (cparams[n_cparams].value);
871 /* release g_object_init() notification queue freeze_count */
872 nqueue = object_freeze_notifies (object);
873 nqueue->freeze_count--;
875 /* set remaining properties */
879 GValue *value = nparams->value;
880 GParamSpec *pspec = nparams->pspec;
881 const gchar *trailer = nparams++->trailer;
883 /* convert if necessary */
884 if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
886 GValue tmp_value = { 0, };
888 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
889 if (!g_value_convert (value, &tmp_value) ||
890 g_param_value_validate (pspec, &tmp_value))
891 g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
893 G_VALUE_TYPE_NAME (value),
895 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
897 object_set_property (object, &tmp_value, pspec, trailer, nqueue);
898 g_value_unset (&tmp_value);
901 object_set_property (object, value, pspec, trailer, nqueue);
903 g_value_unset (value);
908 g_type_class_unref (class);
910 /* release our own freeze count and handle notifications */
911 object_thaw_notifies (object, nqueue);
917 g_object_constructor (GType type,
918 guint n_construct_properties,
919 GObjectConstructParam *construct_params)
924 object = (GObject*) g_type_create_instance (type);
926 /* set construction parameters */
927 if (n_construct_properties)
929 NotifyQueue *nqueue = object_freeze_notifies (object);
931 /* set construct properties */
932 while (n_construct_properties--)
934 GValue *value = construct_params->value;
935 GParamSpec *pspec = construct_params->pspec;
936 const gchar *trailer = construct_params++->trailer;
938 /* convert if necessary */
939 if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
941 GValue tmp_value = { 0, };
943 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
944 if (!g_value_convert (value, &tmp_value) ||
945 g_param_value_validate (pspec, &tmp_value))
946 g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
948 G_VALUE_TYPE_NAME (value),
950 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
952 object_set_property (object, &tmp_value, pspec, trailer, nqueue);
953 g_value_unset (&tmp_value);
956 object_set_property (object, value, pspec, trailer, nqueue);
958 nqueue->freeze_count--;
959 /* the notification queue is still frozen from g_object_init(), so
960 * we don't need to handle it here, g_object_new_valist() takes
969 g_object_set_valist (GObject *object,
970 const gchar *first_property_name,
976 g_return_if_fail (G_IS_OBJECT (object));
978 g_object_ref (object);
979 nqueue = object_freeze_notifies (object);
981 name = first_property_name;
984 const gchar *trailer = NULL;
985 GValue value = { 0, };
989 pspec = g_param_spec_pool_lookup (pspec_pool,
991 G_OBJECT_TYPE (object),
996 g_warning ("%s: object class `%s' has no property named `%s'",
998 G_OBJECT_TYPE_NAME (object),
1002 if (!(pspec->flags & G_PARAM_WRITABLE))
1004 g_warning ("%s: property `%s' of object class `%s' is not writable",
1007 G_OBJECT_TYPE_NAME (object));
1011 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1013 G_VALUE_COLLECT (&value, var_args, &error);
1016 g_warning ("%s: %s", G_STRLOC, error);
1019 /* we purposely leak the value here, it might not be
1020 * in a sane state if an error condition occoured
1025 object_set_property (object, &value, pspec, trailer, nqueue);
1027 g_value_unset (&value);
1029 name = va_arg (var_args, gchar*);
1032 object_thaw_notifies (object, nqueue);
1033 g_object_unref (object);
1037 g_object_get_valist (GObject *object,
1038 const gchar *first_property_name,
1043 g_return_if_fail (G_IS_OBJECT (object));
1045 g_object_ref (object);
1047 name = first_property_name;
1051 const gchar *trailer = NULL;
1052 GValue value = { 0, };
1056 pspec = g_param_spec_pool_lookup (pspec_pool,
1058 G_OBJECT_TYPE (object),
1063 g_warning ("%s: object class `%s' has no property named `%s'",
1065 G_OBJECT_TYPE_NAME (object),
1069 if (!(pspec->flags & G_PARAM_READABLE))
1071 g_warning ("%s: property `%s' of object class `%s' is not readable",
1074 G_OBJECT_TYPE_NAME (object));
1078 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1080 object_get_property (object, &value, pspec, trailer);
1082 G_VALUE_LCOPY (&value, var_args, &error);
1085 g_warning ("%s: %s", G_STRLOC, error);
1088 /* we purposely leak the value here, it might not be
1089 * in a sane state if an error condition occoured
1094 g_value_unset (&value);
1096 name = va_arg (var_args, gchar*);
1099 g_object_unref (object);
1103 g_object_set (gpointer _object,
1104 const gchar *first_property_name,
1107 GObject *object = _object;
1110 g_return_if_fail (G_IS_OBJECT (object));
1112 va_start (var_args, first_property_name);
1113 g_object_set_valist (object, first_property_name, var_args);
1118 g_object_get (gpointer _object,
1119 const gchar *first_property_name,
1122 GObject *object = _object;
1125 g_return_if_fail (G_IS_OBJECT (object));
1127 va_start (var_args, first_property_name);
1128 g_object_get_valist (object, first_property_name, var_args);
1133 g_object_set_property (GObject *object,
1134 const gchar *property_name,
1135 const GValue *value)
1137 NotifyQueue *nqueue;
1139 const gchar *trailer;
1141 g_return_if_fail (G_IS_OBJECT (object));
1142 g_return_if_fail (property_name != NULL);
1143 g_return_if_fail (G_IS_VALUE (value));
1145 g_object_ref (object);
1146 nqueue = object_freeze_notifies (object);
1148 pspec = g_param_spec_pool_lookup (pspec_pool,
1150 G_OBJECT_TYPE (object),
1154 g_warning ("%s: object class `%s' has no property named `%s'",
1156 G_OBJECT_TYPE_NAME (object),
1160 GValue tmp_value = { 0, };
1162 /* provide a copy to work from and convert if necessary */
1163 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1165 if (!g_value_convert (value, &tmp_value) ||
1166 g_param_value_validate (pspec, &tmp_value))
1167 g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
1169 G_VALUE_TYPE_NAME (value),
1171 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
1173 object_set_property (object, &tmp_value, pspec, trailer, nqueue);
1175 g_value_unset (&tmp_value);
1178 object_thaw_notifies (object, nqueue);
1179 g_object_unref (object);
1183 g_object_get_property (GObject *object,
1184 const gchar *property_name,
1188 const gchar *trailer;
1190 g_return_if_fail (G_IS_OBJECT (object));
1191 g_return_if_fail (property_name != NULL);
1192 g_return_if_fail (G_IS_VALUE (value));
1194 g_object_ref (object);
1196 pspec = g_param_spec_pool_lookup (pspec_pool,
1198 G_OBJECT_TYPE (object),
1202 g_warning ("%s: object class `%s' has no property named `%s'",
1204 G_OBJECT_TYPE_NAME (object),
1208 GValue tmp_value = { 0, };
1210 /* provide a copy to work from and later convert if necessary, so
1211 * _get_property() implementations need *not* care about freeing values
1212 * that might be already set in the property to get.
1213 * (though, at this point, GValue should exclusively be modified
1214 * through the accessor functions anyways)
1216 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1218 if (!g_value_types_exchangable (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
1219 g_warning ("%s: can't retrive property `%s' value of type `%s' as value of type `%s'",
1222 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1223 G_VALUE_TYPE_NAME (value));
1226 object_get_property (object, &tmp_value, pspec, trailer);
1227 g_value_convert (&tmp_value, value);
1228 /* g_value_validate (value, pspec); */
1231 g_value_unset (&tmp_value);
1234 g_object_unref (object);
1238 g_object_ref (gpointer _object)
1240 GObject *object = _object;
1242 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1243 g_return_val_if_fail (object->ref_count > 0, NULL);
1245 #ifdef G_ENABLE_DEBUG
1246 if (glib_trap_object_ref == object)
1248 #endif /* G_ENABLE_DEBUG */
1250 object->ref_count += 1;
1256 g_object_unref (gpointer _object)
1258 GObject *object = _object;
1260 g_return_if_fail (G_IS_OBJECT (object));
1261 g_return_if_fail (object->ref_count > 0);
1263 #ifdef G_ENABLE_DEBUG
1264 if (glib_trap_object_ref == object)
1266 #endif /* G_ENABLE_DEBUG */
1268 if (object->ref_count > 1)
1269 object->ref_count -= 1;
1271 g_object_last_unref (object);
1275 g_object_get_qdata (GObject *object,
1278 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1280 return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1284 g_object_set_qdata (GObject *object,
1288 g_return_if_fail (G_IS_OBJECT (object));
1289 g_return_if_fail (quark > 0);
1291 g_datalist_id_set_data (&object->qdata, quark, data);
1295 g_object_set_qdata_full (GObject *object,
1298 GDestroyNotify destroy)
1300 g_return_if_fail (G_IS_OBJECT (object));
1301 g_return_if_fail (quark > 0);
1303 g_datalist_id_set_data_full (&object->qdata, quark, data, data ? destroy : NULL);
1307 g_object_steal_qdata (GObject *object,
1310 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1311 g_return_val_if_fail (quark > 0, NULL);
1313 return g_datalist_id_remove_no_notify (&object->qdata, quark);
1317 g_object_get_data (GObject *object,
1322 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1323 g_return_val_if_fail (key != NULL, NULL);
1325 quark = g_quark_try_string (key);
1327 return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1331 g_object_set_data (GObject *object,
1335 g_return_if_fail (G_IS_OBJECT (object));
1336 g_return_if_fail (key != NULL);
1338 g_datalist_id_set_data (&object->qdata, g_quark_from_string (key), data);
1342 g_object_set_data_full (GObject *object,
1345 GDestroyNotify destroy)
1347 g_return_if_fail (G_IS_OBJECT (object));
1348 g_return_if_fail (key != NULL);
1350 g_datalist_id_set_data_full (&object->qdata, g_quark_from_string (key), data, data ? destroy : NULL);
1354 g_object_steal_data (GObject *object,
1359 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1360 g_return_val_if_fail (key != NULL, NULL);
1362 quark = g_quark_try_string (key);
1364 return quark ? g_datalist_id_remove_no_notify (&object->qdata, quark) : NULL;
1368 g_value_object_init (GValue *value)
1370 value->data[0].v_pointer = NULL;
1374 g_value_object_free_value (GValue *value)
1376 if (value->data[0].v_pointer)
1377 g_object_unref (value->data[0].v_pointer);
1381 g_value_object_copy_value (const GValue *src_value,
1384 if (src_value->data[0].v_pointer)
1385 dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
1387 dest_value->data[0].v_pointer = NULL;
1391 g_value_object_peek_pointer (const GValue *value)
1393 return value->data[0].v_pointer;
1397 g_value_object_collect_value (GValue *value,
1399 GType *collect_type,
1400 GTypeCValue *collect_value)
1402 if (collect_value->v_pointer)
1404 GObject *object = collect_value->v_pointer;
1406 if (object->g_type_instance.g_class == NULL)
1407 return g_strconcat ("invalid unclassed object pointer for value type `",
1408 G_VALUE_TYPE_NAME (value),
1411 else if (!g_type_is_a (G_OBJECT_TYPE (object), G_VALUE_TYPE (value)))
1412 return g_strconcat ("invalid object type `",
1413 G_OBJECT_TYPE_NAME (object),
1414 "' for value type `",
1415 G_VALUE_TYPE_NAME (value),
1418 value->data[0].v_pointer = g_object_ref (object);
1421 value->data[0].v_pointer = NULL;
1428 g_value_object_lcopy_value (const GValue *value,
1430 GType *collect_type,
1431 GTypeCValue *collect_value)
1433 GObject **object_p = collect_value->v_pointer;
1436 return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
1438 *object_p = value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
1445 g_value_set_object (GValue *value,
1448 g_return_if_fail (G_IS_VALUE_OBJECT (value));
1450 if (value->data[0].v_pointer)
1452 g_object_unref (value->data[0].v_pointer);
1453 value->data[0].v_pointer = NULL;
1458 g_return_if_fail (G_IS_OBJECT (v_object));
1459 g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (v_object), G_VALUE_TYPE (value)));
1461 value->data[0].v_pointer = v_object;
1462 g_object_ref (value->data[0].v_pointer);
1467 g_value_get_object (const GValue *value)
1469 g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
1471 return value->data[0].v_pointer;
1475 g_value_dup_object (const GValue *value)
1477 g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
1479 return value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
1483 g_signal_connect_object (gpointer instance,
1484 const gchar *detailed_signal,
1485 GCallback c_handler,
1490 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1491 g_return_val_if_fail (detailed_signal != NULL, 0);
1492 g_return_val_if_fail (c_handler != NULL, 0);
1498 g_return_val_if_fail (G_IS_OBJECT (gobject), 0);
1500 closure = (swapped ? g_cclosure_new_object_swap : g_cclosure_new_object) (c_handler, gobject);
1502 return g_signal_connect_closure (instance, detailed_signal, closure, after);
1505 return g_signal_connect_data (instance, detailed_signal, c_handler, NULL, NULL, swapped, after);
1511 GClosure *closures[1]; /* flexible array */
1515 object_remove_closure (gpointer data,
1518 GObject *object = data;
1519 CArray *carray = g_object_get_qdata (object, quark_closure_array);
1522 for (i = 0; i < carray->n_closures; i++)
1523 if (carray->closures[i] == closure)
1525 carray->n_closures--;
1526 if (i < carray->n_closures)
1527 carray->closures[i] = carray->closures[carray->n_closures];
1530 g_assert_not_reached ();
1534 destroy_closure_array (gpointer data)
1536 CArray *carray = data;
1537 GObject *object = carray->object;
1538 guint i, n = carray->n_closures;
1540 for (i = 0; i < n; i++)
1542 GClosure *closure = carray->closures[i];
1544 /* removing object_remove_closure() upfront is probably faster than
1545 * letting it fiddle with quark_closure_array which is empty anyways
1547 g_closure_remove_inotify (closure, object, object_remove_closure);
1548 g_closure_invalidate (closure);
1554 g_object_watch_closure (GObject *object,
1559 g_return_if_fail (G_IS_OBJECT (object));
1560 g_return_if_fail (closure != NULL);
1561 g_return_if_fail (closure->is_invalid == FALSE);
1562 g_return_if_fail (closure->in_marshal == FALSE);
1563 g_return_if_fail (object->ref_count > 0); /* this doesn't work on finalizing objects */
1565 g_closure_add_inotify (closure, object, object_remove_closure);
1566 g_closure_add_marshal_guards (closure,
1567 object, (GClosureNotify) g_object_ref,
1568 object, (GClosureNotify) g_object_unref);
1569 carray = g_object_steal_qdata (object, quark_closure_array);
1572 carray = g_renew (CArray, NULL, 1);
1573 carray->object = object;
1574 carray->n_closures = 1;
1575 carray->closures[0] = closure;
1576 g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
1580 guint i = carray->n_closures++;
1582 carray = g_realloc (carray, sizeof (*carray) + sizeof (carray->closures[0]) * i);
1583 carray->closures[i] = closure;
1584 g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
1589 g_closure_new_object (guint sizeof_closure,
1594 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1595 g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
1597 closure = g_closure_new_simple (sizeof_closure, object);
1598 g_object_watch_closure (object, closure);
1604 g_cclosure_new_object (GCallback callback_func,
1607 GObject *object = _object;
1610 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1611 g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
1612 g_return_val_if_fail (callback_func != NULL, NULL);
1614 closure = g_cclosure_new (callback_func, object, NULL);
1615 g_object_watch_closure (object, closure);
1621 g_cclosure_new_object_swap (GCallback callback_func,
1624 GObject *object = _object;
1627 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1628 g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
1629 g_return_val_if_fail (callback_func != NULL, NULL);
1631 closure = g_cclosure_new_swap (callback_func, object, NULL);
1632 g_object_watch_closure (object, closure);