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,
91 guint n_collect_values,
92 GTypeCValue *collect_values,
94 static gchar* g_value_object_lcopy_value (const GValue *value,
95 guint n_collect_values,
96 GTypeCValue *collect_values,
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 #ifdef G_ENABLE_DEBUG
142 #define IF_DEBUG(debug_type) if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
143 G_LOCK_DEFINE_STATIC (debug_objects);
144 static volatile GObject *g_trap_object_ref = NULL;
145 static guint debug_objects_count = 0;
146 static GHashTable *debug_objects_ht = NULL;
148 debug_objects_foreach (gpointer key,
152 GObject *object = value;
154 g_message ("[%p] stale %s\tref_count=%u",
156 G_OBJECT_TYPE_NAME (object),
160 debug_objects_atexit (void)
164 G_LOCK (debug_objects);
165 if (debug_objects_ht)
167 g_message ("stale GObjects: %u", debug_objects_count);
168 g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
170 G_UNLOCK (debug_objects);
173 #endif /* G_ENABLE_DEBUG */
176 g_object_type_init (void) /* sync with gtype.c */
178 static gboolean initialized = FALSE;
179 static const GTypeFundamentalInfo finfo = {
180 G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE,
182 static GTypeInfo info = {
183 sizeof (GObjectClass),
184 (GBaseInitFunc) g_object_base_class_init,
185 (GBaseFinalizeFunc) g_object_base_class_finalize,
186 (GClassInitFunc) g_object_do_class_init,
187 NULL /* class_destroy */,
188 NULL /* class_data */,
191 (GInstanceInitFunc) g_object_init,
192 NULL, /* value_table */
194 static const GTypeValueTable value_table = {
195 g_value_object_init, /* value_init */
196 g_value_object_free_value, /* value_free */
197 g_value_object_copy_value, /* value_copy */
198 g_value_object_peek_pointer, /* value_peek_pointer */
199 "p", /* collect_format */
200 g_value_object_collect_value, /* collect_value */
201 "p", /* lcopy_format */
202 g_value_object_lcopy_value, /* lcopy_value */
206 g_return_if_fail (initialized == FALSE);
211 info.value_table = &value_table;
212 type = g_type_register_fundamental (G_TYPE_OBJECT, "GObject", &info, &finfo, 0);
213 g_assert (type == G_TYPE_OBJECT);
215 #ifdef G_ENABLE_DEBUG
217 g_atexit (debug_objects_atexit);
218 #endif /* G_ENABLE_DEBUG */
222 g_object_base_class_init (GObjectClass *class)
224 GObjectClass *pclass = g_type_class_peek_parent (class);
226 /* reset instance specific fields and methods that don't get inherited */
227 class->n_property_specs = 0;
228 class->property_specs = NULL;
229 class->construct_properties = pclass ? g_slist_copy (pclass->construct_properties) : NULL;
230 class->get_property = NULL;
231 class->set_property = NULL;
235 g_object_base_class_finalize (GObjectClass *class)
239 g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
241 _g_signals_destroy (G_OBJECT_CLASS_TYPE (class));
243 g_slist_free (class->construct_properties);
244 class->construct_properties = NULL;
245 for (i = 0; i < class->n_property_specs; i++)
247 GParamSpec *pspec = class->property_specs[i];
249 g_param_spec_pool_remove (pspec_pool, pspec);
250 g_param_spec_set_qdata (pspec, quark_property_id, NULL);
251 g_param_spec_unref (pspec);
253 class->n_property_specs = 0;
254 g_free (class->property_specs);
255 class->property_specs = NULL;
259 g_object_do_class_init (GObjectClass *class)
261 quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
262 quark_property_id = g_quark_from_static_string ("GObject-property-id");
263 quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
264 pspec_pool = g_param_spec_pool_new (TRUE);
266 class->constructor = g_object_constructor;
267 class->set_property = g_object_do_set_property;
268 class->get_property = g_object_do_get_property;
269 class->shutdown = g_object_shutdown;
270 class->finalize = g_object_finalize;
271 class->dispatch_properties_changed = g_object_dispatch_properties_changed;
272 class->properties_changed = g_object_properties_changed;
273 class->notify = g_object_notify_property_changed;
275 g_object_class_install_property (class,
277 g_param_spec_pointer ("data", "Named Data",
278 "Named anonymous pointers",
279 G_PARAM_READABLE | G_PARAM_WRITABLE));
280 g_object_class_install_property (class,
282 g_param_spec_ccallback ("signal", "Signal Connection",
283 "Signal connection consisting of a callback function "
284 "and a data pointer",
286 g_object_class_install_property (class,
288 g_param_spec_ccallback ("swapped_signal", "Swapped Signal Connection",
289 "Signal connection consisting of a callback function "
290 "and a data pointer",
292 g_object_class_install_property (class,
294 g_param_spec_ccallback ("signal_after", "Signal After Connection",
295 "Signal connection consisting of a callback function "
296 "and a data pointer",
298 g_object_class_install_property (class,
299 PROP_SWAPPED_SIGNAL_AFTER,
300 g_param_spec_ccallback ("swapped_signal_after", "Swapped Signal After Connection",
301 "Signal connection consisting of a callback function "
302 "and a data pointer",
304 gobject_signals[PROPERTIES_CHANGED] =
305 g_signal_newc ("properties_changed",
306 G_TYPE_FROM_CLASS (class),
307 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
308 G_STRUCT_OFFSET (GObjectClass, properties_changed),
309 NULL, /* accumulator */
310 g_cclosure_marshal_VOID__UINT_POINTER,
312 2, G_TYPE_UINT, G_TYPE_POINTER);
313 gobject_signals[NOTIFY] =
314 g_signal_newc ("notify",
315 G_TYPE_FROM_CLASS (class),
316 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
317 G_STRUCT_OFFSET (GObjectClass, notify),
318 NULL, /* accumulator */
319 g_cclosure_marshal_VOID__PARAM,
325 g_object_class_install_property (GObjectClass *class,
331 g_return_if_fail (G_IS_OBJECT_CLASS (class));
332 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
333 if (pspec->flags & G_PARAM_WRITABLE)
334 g_return_if_fail (class->set_property != NULL);
335 if (pspec->flags & G_PARAM_READABLE)
336 g_return_if_fail (class->get_property != NULL);
337 g_return_if_fail (property_id > 0);
338 g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
339 if (pspec->flags & G_PARAM_CONSTRUCT)
340 g_return_if_fail ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
341 if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
342 g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
344 /* expensive paranoia checks ;( */
345 for (i = 0; i < class->n_property_specs; i++)
346 if (PARAM_SPEC_PARAM_ID (class->property_specs[i]) == property_id)
348 g_warning (G_STRLOC ": class `%s' already contains a property `%s' with id %u, "
349 "cannot install property `%s'",
350 G_OBJECT_CLASS_NAME (class),
351 class->property_specs[i]->name,
356 if (g_param_spec_pool_lookup (pspec_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE, NULL))
358 g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
359 G_OBJECT_CLASS_NAME (class),
364 g_param_spec_ref (pspec);
365 g_param_spec_sink (pspec);
366 g_param_spec_set_qdata (pspec, quark_property_id, GUINT_TO_POINTER (property_id));
367 g_param_spec_pool_insert (pspec_pool, pspec, G_OBJECT_CLASS_TYPE (class));
368 i = class->n_property_specs++;
369 class->property_specs = g_renew (GParamSpec*, class->property_specs, class->n_property_specs);
370 class->property_specs[i] = pspec;
371 if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
372 class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
374 /* for property overrides of construct poperties, we have to get rid
375 * of the overidden inherited construct property
377 pspec = g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type_parent (G_OBJECT_CLASS_TYPE (class)), TRUE, NULL);
378 if (pspec && pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
379 class->construct_properties = g_slist_remove (class->construct_properties, pspec);
383 g_object_class_find_property (GObjectClass *class,
384 const gchar *property_name)
386 g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
387 g_return_val_if_fail (property_name != NULL, NULL);
389 return g_param_spec_pool_lookup (pspec_pool,
391 G_OBJECT_CLASS_TYPE (class),
396 free_notify_queue (gpointer data)
398 NotifyQueue *nqueue = data;
400 g_slist_free (nqueue->pspecs);
404 static inline NotifyQueue*
405 object_freeze_notifies (GObject *object)
409 nqueue = g_object_get_qdata (object, quark_notify_queue);
412 nqueue = g_new0 (NotifyQueue, 1);
413 g_object_set_qdata_full (object, quark_notify_queue, nqueue, free_notify_queue);
415 nqueue->freeze_count++;
421 object_queue_property (GObject *object,
425 /* we will dedup later */
426 nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
431 g_object_init (GObject *object)
433 object->ref_count = 1;
434 g_datalist_init (&object->qdata);
436 /* freeze object's notification queue, g_object_new_valist() takes care of that */
437 object_freeze_notifies (object);
439 #ifdef G_ENABLE_DEBUG
442 G_LOCK (debug_objects);
443 if (!debug_objects_ht)
444 debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
445 debug_objects_count++;
446 g_hash_table_insert (debug_objects_ht, object, object);
447 G_UNLOCK (debug_objects);
449 #endif /* G_ENABLE_DEBUG */
453 g_object_do_set_property (GObject *object,
457 const gchar *trailer)
463 gboolean swapped, after;
464 gpointer callback, data;
466 g_return_if_fail (trailer != NULL);
468 g_object_set_data (object, trailer, g_value_get_pointer (value));
470 case PROP_SWAPPED_SIGNAL_AFTER:
472 case PROP_SIGNAL_AFTER:
474 case PROP_SWAPPED_SIGNAL:
479 g_return_if_fail (trailer != NULL);
481 g_value_get_ccallback (value, &callback, &data);
482 g_signal_connect_data (object, trailer,
483 callback, data, NULL,
487 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
493 g_object_do_get_property (GObject *object,
497 const gchar *trailer)
502 g_return_if_fail (trailer != NULL);
504 g_value_set_pointer (value, g_object_get_data (object, trailer));
507 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
513 g_object_last_unref (GObject *object)
515 g_return_if_fail (object->ref_count > 0);
517 if (object->ref_count == 1) /* may have been re-referenced meanwhile */
518 G_OBJECT_GET_CLASS (object)->shutdown (object);
520 #ifdef G_ENABLE_DEBUG
521 if (g_trap_object_ref == object)
523 #endif /* G_ENABLE_DEBUG */
525 object->ref_count -= 1;
527 if (object->ref_count == 0) /* may have been re-referenced meanwhile */
529 G_OBJECT_GET_CLASS (object)->finalize (object);
530 #ifdef G_ENABLE_DEBUG
533 G_LOCK (debug_objects);
534 if (debug_objects_ht)
535 g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
536 G_UNLOCK (debug_objects);
538 #endif /* G_ENABLE_DEBUG */
539 g_type_free_instance ((GTypeInstance*) object);
544 g_object_shutdown (GObject *object)
546 /* this function needs to be always present for unconditional
547 * chaining, we also might add some code here later.
548 * beware though, subclasses may invoke shutdown() arbitrarily.
553 g_object_finalize (GObject *object)
555 g_signal_handlers_destroy (object);
556 g_datalist_clear (&object->qdata);
558 #ifdef G_ENABLE_DEBUG
561 G_LOCK (debug_objects);
562 g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
563 g_hash_table_remove (debug_objects_ht, object);
564 debug_objects_count--;
565 G_UNLOCK (debug_objects);
567 #endif /* G_ENABLE_DEBUG */
571 object_thaw_notifies (GObject *object,
578 nqueue->freeze_count--;
579 if (nqueue->freeze_count)
581 g_return_if_fail (object->ref_count > 0);
583 pspecs = g_new (GParamSpec*, nqueue->n_pspecs);
584 for (slist = nqueue->pspecs; slist; slist = slist->next)
586 GParamSpec *pspec = slist->data;
589 /* dedup, make pspecs in the list unique */
591 if (pspecs[i] == pspec)
594 goto redo_dedup_check;
596 pspecs[n_pspecs++] = pspec;
598 g_object_set_qdata (object, quark_notify_queue, NULL);
601 G_OBJECT_GET_CLASS (object)->dispatch_properties_changed (object, n_pspecs, pspecs);
607 g_object_dispatch_properties_changed (GObject *object,
611 g_signal_emit (object, gobject_signals[PROPERTIES_CHANGED], 0, n_pspecs, pspecs);
615 g_object_properties_changed (GObject *object,
621 for (i = 0; i < n_pspecs; i++)
622 g_signal_emit (object, gobject_signals[NOTIFY], g_quark_from_string (pspecs[i]->name), pspecs[i]);
626 g_object_notify_property_changed (GObject *object,
630 g_message ("NOTIFICATION: property `%s' changed on object `%s'",
632 G_OBJECT_TYPE_NAME (object));
636 g_object_freeze_notify (GObject *object)
638 g_return_if_fail (G_IS_OBJECT (object));
639 if (!object->ref_count)
642 g_object_ref (object);
643 object_freeze_notifies (object);
644 g_object_unref (object);
648 g_object_notify (GObject *object,
649 const gchar *property_name)
653 g_return_if_fail (G_IS_OBJECT (object));
654 g_return_if_fail (property_name != NULL);
655 if (!object->ref_count)
658 g_object_ref (object);
659 pspec = g_param_spec_pool_lookup (pspec_pool,
661 G_OBJECT_TYPE (object),
664 g_warning ("%s: object class `%s' has no property named `%s'",
666 G_OBJECT_TYPE_NAME (object),
670 NotifyQueue *nqueue = object_freeze_notifies (object);
672 object_queue_property (object, pspec, nqueue);
673 object_thaw_notifies (object, nqueue);
675 g_object_unref (object);
679 g_object_thaw_notify (GObject *object)
683 g_return_if_fail (G_IS_OBJECT (object));
684 if (!object->ref_count)
687 g_object_ref (object);
688 nqueue = g_object_get_qdata (object, quark_notify_queue);
689 if (!nqueue || !nqueue->freeze_count)
690 g_warning (G_STRLOC ": property-changed notification for %s(%p) is not frozen",
691 G_OBJECT_TYPE_NAME (object), object);
693 object_thaw_notifies (object, nqueue);
694 g_object_unref (object);
698 object_get_property (GObject *object,
701 const gchar *trailer)
705 g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type)); /* paranoid */
707 class = g_type_class_peek (pspec->owner_type);
709 class->get_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
713 object_set_property (GObject *object,
716 const gchar *trailer,
721 g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), pspec->owner_type)); /* paranoid */
723 class = g_type_class_peek (pspec->owner_type);
725 class->set_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec, trailer);
726 object_queue_property (object, pspec, nqueue);
730 g_object_new (GType object_type,
731 const gchar *first_property_name,
737 g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
739 va_start (var_args, first_property_name);
740 object = g_object_new_valist (object_type, first_property_name, var_args);
747 g_object_new_valist (GType object_type,
748 const gchar *first_property_name,
755 GObjectConstructParam *cparams = NULL, *nparams = NULL;
756 guint n_cparams = 0, n_nparams = 0;
759 g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
761 class = g_type_class_ref (object_type);
762 clist = g_slist_copy (class->construct_properties);
764 /* collect parameters, sort into construction and normal ones */
765 name = first_property_name;
768 const gchar *trailer = NULL;
773 pspec = g_param_spec_pool_lookup (pspec_pool,
780 g_warning ("%s: object class `%s' has no property named `%s'",
782 g_type_name (object_type),
786 if (!(pspec->flags & G_PARAM_WRITABLE))
788 g_warning ("%s: property `%s' of object class `%s' is not writable",
791 g_type_name (object_type));
795 value = g_new (GValue, 1);
797 g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
798 G_VALUE_COLLECT (value, var_args, 0, &error);
801 g_warning ("%s: %s", G_STRLOC, error);
804 /* we purposely leak the value here, it might not be
805 * in a sane state if an error condition occoured
809 if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
813 if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
814 cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
815 cparams[n_cparams].pspec = pspec;
816 cparams[n_cparams].value = value;
817 cparams[n_cparams].trailer = trailer;
818 for (i = 0; i < n_cparams; i++) /* picky, aren't we? ;) */
819 if (cparams[i].pspec == pspec)
820 g_warning (G_STRLOC ": construct property \"%s\" for object `%s' is being set twice",
821 pspec->name, g_type_name (object_type));
823 clist = g_slist_remove (clist, pspec); /* FIXME: unique */
827 if (!n_nparams || n_nparams >= PREALLOC_CPARAMS)
828 nparams = g_renew (GObjectConstructParam, nparams, MAX (n_nparams + 1, PREALLOC_CPARAMS));
829 nparams[n_nparams].pspec = pspec;
830 nparams[n_nparams].value = value;
831 nparams[n_nparams].trailer = trailer;
835 name = va_arg (var_args, gchar*);
838 /* construct object from construction parameters */
841 GSList *tmp = clist->next;
842 GParamSpec *pspec = clist->data;
843 GValue *value = g_new (GValue, 1);
846 g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
847 g_param_value_set_default (pspec, value);
849 if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
850 cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
851 cparams[n_cparams].pspec = pspec;
852 cparams[n_cparams].value = value;
853 cparams[n_cparams].trailer = NULL;
856 g_slist_free_1 (clist);
859 object = class->constructor (object_type, n_cparams, cparams);
861 /* free construction values */
864 g_value_unset (cparams[n_cparams].value);
865 g_free (cparams[n_cparams].value);
869 /* release g_object_init() notification queue freeze_count */
870 nqueue = object_freeze_notifies (object);
871 nqueue->freeze_count--;
873 /* set remaining properties */
877 GValue *value = nparams->value;
878 GParamSpec *pspec = nparams->pspec;
879 const gchar *trailer = nparams++->trailer;
881 /* convert if necessary */
882 if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
884 GValue tmp_value = { 0, };
886 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
887 if (!g_value_convert (value, &tmp_value) ||
888 g_param_value_validate (pspec, &tmp_value))
889 g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
891 G_VALUE_TYPE_NAME (value),
893 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
895 object_set_property (object, &tmp_value, pspec, trailer, nqueue);
896 g_value_unset (&tmp_value);
899 object_set_property (object, value, pspec, trailer, nqueue);
901 g_value_unset (value);
906 g_type_class_unref (class);
908 /* release our own freeze count and handle notifications */
909 object_thaw_notifies (object, nqueue);
915 g_object_constructor (GType type,
916 guint n_construct_properties,
917 GObjectConstructParam *construct_params)
922 object = (GObject*) g_type_create_instance (type);
924 /* set construction parameters */
925 if (n_construct_properties)
927 NotifyQueue *nqueue = object_freeze_notifies (object);
929 /* set construct properties */
930 while (n_construct_properties--)
932 GValue *value = construct_params->value;
933 GParamSpec *pspec = construct_params->pspec;
934 const gchar *trailer = construct_params++->trailer;
936 /* convert if necessary */
937 if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
939 GValue tmp_value = { 0, };
941 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
942 if (!g_value_convert (value, &tmp_value) ||
943 g_param_value_validate (pspec, &tmp_value))
944 g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
946 G_VALUE_TYPE_NAME (value),
948 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
950 object_set_property (object, &tmp_value, pspec, trailer, nqueue);
951 g_value_unset (&tmp_value);
954 object_set_property (object, value, pspec, trailer, nqueue);
956 nqueue->freeze_count--;
957 /* the notification queue is still frozen from g_object_init(), so
958 * we don't need to handle it here, g_object_new_valist() takes
967 g_object_set_valist (GObject *object,
968 const gchar *first_property_name,
974 g_return_if_fail (G_IS_OBJECT (object));
976 g_object_ref (object);
977 nqueue = object_freeze_notifies (object);
979 name = first_property_name;
982 const gchar *trailer = NULL;
983 GValue value = { 0, };
987 pspec = g_param_spec_pool_lookup (pspec_pool,
989 G_OBJECT_TYPE (object),
994 g_warning ("%s: object class `%s' has no property named `%s'",
996 G_OBJECT_TYPE_NAME (object),
1000 if (!(pspec->flags & G_PARAM_WRITABLE))
1002 g_warning ("%s: property `%s' of object class `%s' is not writable",
1005 G_OBJECT_TYPE_NAME (object));
1009 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1011 G_VALUE_COLLECT (&value, var_args, 0, &error);
1014 g_warning ("%s: %s", G_STRLOC, error);
1017 /* we purposely leak the value here, it might not be
1018 * in a sane state if an error condition occoured
1023 object_set_property (object, &value, pspec, trailer, nqueue);
1025 g_value_unset (&value);
1027 name = va_arg (var_args, gchar*);
1030 object_thaw_notifies (object, nqueue);
1031 g_object_unref (object);
1035 g_object_get_valist (GObject *object,
1036 const gchar *first_property_name,
1041 g_return_if_fail (G_IS_OBJECT (object));
1043 g_object_ref (object);
1045 name = first_property_name;
1049 const gchar *trailer = NULL;
1050 GValue value = { 0, };
1054 pspec = g_param_spec_pool_lookup (pspec_pool,
1056 G_OBJECT_TYPE (object),
1061 g_warning ("%s: object class `%s' has no property named `%s'",
1063 G_OBJECT_TYPE_NAME (object),
1067 if (!(pspec->flags & G_PARAM_READABLE))
1069 g_warning ("%s: property `%s' of object class `%s' is not readable",
1072 G_OBJECT_TYPE_NAME (object));
1076 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1078 object_get_property (object, &value, pspec, trailer);
1080 G_VALUE_LCOPY (&value, var_args, 0, &error);
1083 g_warning ("%s: %s", G_STRLOC, error);
1086 /* we purposely leak the value here, it might not be
1087 * in a sane state if an error condition occoured
1092 g_value_unset (&value);
1094 name = va_arg (var_args, gchar*);
1097 g_object_unref (object);
1101 g_object_set (gpointer _object,
1102 const gchar *first_property_name,
1105 GObject *object = _object;
1108 g_return_if_fail (G_IS_OBJECT (object));
1110 va_start (var_args, first_property_name);
1111 g_object_set_valist (object, first_property_name, var_args);
1116 g_object_get (gpointer _object,
1117 const gchar *first_property_name,
1120 GObject *object = _object;
1123 g_return_if_fail (G_IS_OBJECT (object));
1125 va_start (var_args, first_property_name);
1126 g_object_get_valist (object, first_property_name, var_args);
1131 g_object_set_property (GObject *object,
1132 const gchar *property_name,
1133 const GValue *value)
1135 NotifyQueue *nqueue;
1137 const gchar *trailer;
1139 g_return_if_fail (G_IS_OBJECT (object));
1140 g_return_if_fail (property_name != NULL);
1141 g_return_if_fail (G_IS_VALUE (value));
1143 g_object_ref (object);
1144 nqueue = object_freeze_notifies (object);
1146 pspec = g_param_spec_pool_lookup (pspec_pool,
1148 G_OBJECT_TYPE (object),
1152 g_warning ("%s: object class `%s' has no property named `%s'",
1154 G_OBJECT_TYPE_NAME (object),
1158 GValue tmp_value = { 0, };
1160 /* provide a copy to work from and convert if necessary */
1161 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1163 if (!g_value_convert (value, &tmp_value) ||
1164 g_param_value_validate (pspec, &tmp_value))
1165 g_warning ("%s: cannot convert `%s' value to property `%s' value of type `%s'",
1167 G_VALUE_TYPE_NAME (value),
1169 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
1171 object_set_property (object, &tmp_value, pspec, trailer, nqueue);
1173 g_value_unset (&tmp_value);
1176 object_thaw_notifies (object, nqueue);
1177 g_object_unref (object);
1181 g_object_get_property (GObject *object,
1182 const gchar *property_name,
1186 const gchar *trailer;
1188 g_return_if_fail (G_IS_OBJECT (object));
1189 g_return_if_fail (property_name != NULL);
1190 g_return_if_fail (G_IS_VALUE (value));
1192 g_object_ref (object);
1194 pspec = g_param_spec_pool_lookup (pspec_pool,
1196 G_OBJECT_TYPE (object),
1200 g_warning ("%s: object class `%s' has no property named `%s'",
1202 G_OBJECT_TYPE_NAME (object),
1206 GValue tmp_value = { 0, };
1208 /* provide a copy to work from and later convert if necessary, so
1209 * _get_property() implementations need *not* care about freeing values
1210 * that might be already set in the property to get.
1211 * (though, at this point, GValue should exclusively be modified
1212 * through the accessor functions anyways)
1214 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1216 if (!g_value_types_exchangable (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
1217 g_warning ("%s: can't retrive property `%s' value of type `%s' as value of type `%s'",
1220 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1221 G_VALUE_TYPE_NAME (value));
1224 object_get_property (object, &tmp_value, pspec, trailer);
1225 g_value_convert (&tmp_value, value);
1226 /* g_value_validate (value, pspec); */
1229 g_value_unset (&tmp_value);
1232 g_object_unref (object);
1236 g_object_ref (gpointer _object)
1238 GObject *object = _object;
1240 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1241 g_return_val_if_fail (object->ref_count > 0, NULL);
1243 #ifdef G_ENABLE_DEBUG
1244 if (g_trap_object_ref == object)
1246 #endif /* G_ENABLE_DEBUG */
1248 object->ref_count += 1;
1254 g_object_unref (gpointer _object)
1256 GObject *object = _object;
1258 g_return_if_fail (G_IS_OBJECT (object));
1259 g_return_if_fail (object->ref_count > 0);
1261 #ifdef G_ENABLE_DEBUG
1262 if (g_trap_object_ref == object)
1264 #endif /* G_ENABLE_DEBUG */
1266 if (object->ref_count > 1)
1267 object->ref_count -= 1;
1269 g_object_last_unref (object);
1273 g_object_get_qdata (GObject *object,
1276 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1278 return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1282 g_object_set_qdata (GObject *object,
1286 g_return_if_fail (G_IS_OBJECT (object));
1287 g_return_if_fail (quark > 0);
1289 g_datalist_id_set_data (&object->qdata, quark, data);
1293 g_object_set_qdata_full (GObject *object,
1296 GDestroyNotify destroy)
1298 g_return_if_fail (G_IS_OBJECT (object));
1299 g_return_if_fail (quark > 0);
1301 g_datalist_id_set_data_full (&object->qdata, quark, data, data ? destroy : NULL);
1305 g_object_steal_qdata (GObject *object,
1308 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1309 g_return_val_if_fail (quark > 0, NULL);
1311 return g_datalist_id_remove_no_notify (&object->qdata, quark);
1315 g_object_get_data (GObject *object,
1320 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1321 g_return_val_if_fail (key != NULL, NULL);
1323 quark = g_quark_try_string (key);
1325 return quark ? g_datalist_id_get_data (&object->qdata, quark) : NULL;
1329 g_object_set_data (GObject *object,
1333 g_return_if_fail (G_IS_OBJECT (object));
1334 g_return_if_fail (key != NULL);
1336 g_datalist_id_set_data (&object->qdata, g_quark_from_string (key), data);
1340 g_object_set_data_full (GObject *object,
1343 GDestroyNotify destroy)
1345 g_return_if_fail (G_IS_OBJECT (object));
1346 g_return_if_fail (key != NULL);
1348 g_datalist_id_set_data_full (&object->qdata, g_quark_from_string (key), data, data ? destroy : NULL);
1352 g_object_steal_data (GObject *object,
1357 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1358 g_return_val_if_fail (key != NULL, NULL);
1360 quark = g_quark_try_string (key);
1362 return quark ? g_datalist_id_remove_no_notify (&object->qdata, quark) : NULL;
1366 g_value_object_init (GValue *value)
1368 value->data[0].v_pointer = NULL;
1372 g_value_object_free_value (GValue *value)
1374 if (value->data[0].v_pointer)
1375 g_object_unref (value->data[0].v_pointer);
1379 g_value_object_copy_value (const GValue *src_value,
1382 if (src_value->data[0].v_pointer)
1383 dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
1385 dest_value->data[0].v_pointer = NULL;
1389 g_value_object_peek_pointer (const GValue *value)
1391 return value->data[0].v_pointer;
1395 g_value_object_collect_value (GValue *value,
1396 guint n_collect_values,
1397 GTypeCValue *collect_values,
1398 guint collect_flags)
1400 if (collect_values[0].v_pointer)
1402 GObject *object = collect_values[0].v_pointer;
1404 if (object->g_type_instance.g_class == NULL)
1405 return g_strconcat ("invalid unclassed object pointer for value type `",
1406 G_VALUE_TYPE_NAME (value),
1409 else if (!g_type_is_a (G_OBJECT_TYPE (object), G_VALUE_TYPE (value)))
1410 return g_strconcat ("invalid object type `",
1411 G_OBJECT_TYPE_NAME (object),
1412 "' for value type `",
1413 G_VALUE_TYPE_NAME (value),
1416 value->data[0].v_pointer = g_object_ref (object);
1419 value->data[0].v_pointer = NULL;
1425 g_value_object_lcopy_value (const GValue *value,
1426 guint n_collect_values,
1427 GTypeCValue *collect_values,
1428 guint collect_flags)
1430 GObject **object_p = collect_values[0].v_pointer;
1433 return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
1435 if (!value->data[0].v_pointer)
1437 else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
1438 *object_p = value->data[0].v_pointer;
1440 *object_p = g_object_ref (value->data[0].v_pointer);
1446 g_value_set_object (GValue *value,
1449 g_return_if_fail (G_IS_VALUE_OBJECT (value));
1451 if (value->data[0].v_pointer)
1453 g_object_unref (value->data[0].v_pointer);
1454 value->data[0].v_pointer = NULL;
1459 g_return_if_fail (G_IS_OBJECT (v_object));
1460 g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (v_object), G_VALUE_TYPE (value)));
1462 value->data[0].v_pointer = v_object;
1463 g_object_ref (value->data[0].v_pointer);
1468 g_value_get_object (const GValue *value)
1470 g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
1472 return value->data[0].v_pointer;
1476 g_value_dup_object (const GValue *value)
1478 g_return_val_if_fail (G_IS_VALUE_OBJECT (value), NULL);
1480 return value->data[0].v_pointer ? g_object_ref (value->data[0].v_pointer) : NULL;
1484 g_signal_connect_object (gpointer instance,
1485 const gchar *detailed_signal,
1486 GCallback c_handler,
1491 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1492 g_return_val_if_fail (detailed_signal != NULL, 0);
1493 g_return_val_if_fail (c_handler != NULL, 0);
1499 g_return_val_if_fail (G_IS_OBJECT (gobject), 0);
1501 closure = (swapped ? g_cclosure_new_object_swap : g_cclosure_new_object) (c_handler, gobject);
1503 return g_signal_connect_closure (instance, detailed_signal, closure, after);
1506 return g_signal_connect_data (instance, detailed_signal, c_handler, NULL, NULL, swapped, after);
1512 GClosure *closures[1]; /* flexible array */
1516 object_remove_closure (gpointer data,
1519 GObject *object = data;
1520 CArray *carray = g_object_get_qdata (object, quark_closure_array);
1523 for (i = 0; i < carray->n_closures; i++)
1524 if (carray->closures[i] == closure)
1526 carray->n_closures--;
1527 if (i < carray->n_closures)
1528 carray->closures[i] = carray->closures[carray->n_closures];
1531 g_assert_not_reached ();
1535 destroy_closure_array (gpointer data)
1537 CArray *carray = data;
1538 GObject *object = carray->object;
1539 guint i, n = carray->n_closures;
1541 for (i = 0; i < n; i++)
1543 GClosure *closure = carray->closures[i];
1545 /* removing object_remove_closure() upfront is probably faster than
1546 * letting it fiddle with quark_closure_array which is empty anyways
1548 g_closure_remove_inotify (closure, object, object_remove_closure);
1549 g_closure_invalidate (closure);
1555 g_object_watch_closure (GObject *object,
1560 g_return_if_fail (G_IS_OBJECT (object));
1561 g_return_if_fail (closure != NULL);
1562 g_return_if_fail (closure->is_invalid == FALSE);
1563 g_return_if_fail (closure->in_marshal == FALSE);
1564 g_return_if_fail (object->ref_count > 0); /* this doesn't work on finalizing objects */
1566 g_closure_add_inotify (closure, object, object_remove_closure);
1567 g_closure_add_marshal_guards (closure,
1568 object, (GClosureNotify) g_object_ref,
1569 object, (GClosureNotify) g_object_unref);
1570 carray = g_object_steal_qdata (object, quark_closure_array);
1573 carray = g_renew (CArray, NULL, 1);
1574 carray->object = object;
1575 carray->n_closures = 1;
1576 carray->closures[0] = closure;
1577 g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
1581 guint i = carray->n_closures++;
1583 carray = g_realloc (carray, sizeof (*carray) + sizeof (carray->closures[0]) * i);
1584 carray->closures[i] = closure;
1585 g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
1590 g_closure_new_object (guint sizeof_closure,
1595 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1596 g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
1598 closure = g_closure_new_simple (sizeof_closure, object);
1599 g_object_watch_closure (object, closure);
1605 g_cclosure_new_object (GCallback callback_func,
1608 GObject *object = _object;
1611 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1612 g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
1613 g_return_val_if_fail (callback_func != NULL, NULL);
1615 closure = g_cclosure_new (callback_func, object, NULL);
1616 g_object_watch_closure (object, closure);
1622 g_cclosure_new_object_swap (GCallback callback_func,
1625 GObject *object = _object;
1628 g_return_val_if_fail (G_IS_OBJECT (object), NULL);
1629 g_return_val_if_fail (object->ref_count > 0, NULL); /* this doesn't work on finalizing objects */
1630 g_return_val_if_fail (callback_func != NULL, NULL);
1632 closure = g_cclosure_new_swap (callback_func, object, NULL);
1633 g_object_watch_closure (object, closure);