source: trunk/third/glib2/gobject/gobject.c @ 20721

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