implemented G_TYPE_GTPYE. applied patch from matthias which implements
authorTim Janik <timj@imendio.com>
Thu, 22 Dec 2005 15:07:03 +0000 (15:07 +0000)
committerTim Janik <timj@src.gnome.org>
Thu, 22 Dec 2005 15:07:03 +0000 (15:07 +0000)
Thu Dec 22 14:59:24 2005  Tim Janik  <timj@imendio.com>

        * gvaluetypes.[hc]: implemented G_TYPE_GTPYE. applied patch
        from matthias which implements GType accessors for GValue.

        * gparamspecs.[hc]: applied patch from matthias which
        implements G_TYPE_PARAM_GTYPE.

        * gobject.[hc]:
        GUnowned: introduced a new object type that has an initially
        floating reference.
        g_object_compat_control(): allow setting of a floating flag handler.

gobject/ChangeLog
gobject/gobject.c
gobject/gobject.h
gobject/gobject.symbols
gobject/gparamspecs.c
gobject/gparamspecs.h
gobject/gvaluetypes.c
gobject/gvaluetypes.h

index ece8c6b..9572467 100644 (file)
@@ -1,3 +1,16 @@
+Thu Dec 22 14:59:24 2005  Tim Janik  <timj@imendio.com>
+
+       * gvaluetypes.[hc]: implemented G_TYPE_GTPYE. applied patch
+       from matthias which implements GType accessors for GValue.
+
+       * gparamspecs.[hc]: applied patch from matthias which 
+       implements G_TYPE_PARAM_GTYPE.
+
+       * gobject.[hc]:
+       GUnowned: introduced a new object type that has an initially
+       floating reference.
+       g_object_compat_control(): allow setting of a floating flag handler.
+
 2005-12-09  Matthias Clasen  <mclasen@redhat.com>
 
        * === Released 2.9.1 ===
index 85ed73d..91d39a8 100644 (file)
@@ -102,6 +102,8 @@ static inline void     object_set_property          (GObject        *object,
                                                         GParamSpec     *pspec,
                                                         const GValue   *value,
                                                         GObjectNotifyQueue *nqueue);
+static guint               object_floating_flag_handler (GObject        *object,
+                                                         gint            job);
 
 static void object_interface_check_properties           (gpointer        func_data,
                                                         gpointer        g_iface);
@@ -116,6 +118,7 @@ static GObjectNotifyContext property_notify_context = { 0, };
 static gulong              gobject_signals[LAST_SIGNAL] = { 0, };
 G_LOCK_DEFINE_STATIC (construct_objects_lock);
 static GSList *construct_objects = NULL;
+static guint (*floating_flag_handler) (GObject*, gint) = object_floating_flag_handler;
 
 /* --- functions --- */
 #ifdef G_ENABLE_DEBUG
@@ -473,7 +476,6 @@ g_object_init (GObject *object)
 {
   object->ref_count = 1;
   g_datalist_init (&object->qdata);
-  g_object_force_floating (object);
   
   /* freeze object's notification queue, g_object_newv() preserves pairedness */
   g_object_notify_queue_freeze (object, &property_notify_context);
@@ -1520,29 +1522,48 @@ g_object_remove_weak_pointer (GObject  *object,
                        weak_pointer_location);
 }
 
+static guint
+object_floating_flag_handler (GObject        *object,
+                              gint            job)
+{
+  switch (job)
+    {
+      gpointer oldvalue;
+    case +1:    /* force floating if possible */
+      do
+        oldvalue = g_atomic_pointer_get (&object->qdata);
+      while (!g_atomic_pointer_compare_and_exchange ((void**) &object->qdata, oldvalue,
+                                                     (gpointer) ((gsize) oldvalue | OBJECT_FLOATING_FLAG)));
+      return (gsize) oldvalue & OBJECT_FLOATING_FLAG;
+    case -1:    /* sink if possible */
+      do
+        oldvalue = g_atomic_pointer_get (&object->qdata);
+      while (!g_atomic_pointer_compare_and_exchange ((void**) &object->qdata, oldvalue,
+                                                     (gpointer) ((gsize) oldvalue & ~(gsize) OBJECT_FLOATING_FLAG)));
+      return (gsize) oldvalue & OBJECT_FLOATING_FLAG;
+    default:    /* check floating */
+      return 0 != ((gsize) g_atomic_pointer_get (&object->qdata) & OBJECT_FLOATING_FLAG);
+    }
+}
+
 gboolean
 g_object_is_floating (gpointer _object)
 {
   GObject *object = _object;
   g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-  return ((gsize) g_atomic_pointer_get (&object->qdata) & OBJECT_FLOATING_FLAG) != 0;
+  return floating_flag_handler (object, 0);
 }
 
 gpointer
 g_object_ref_sink (gpointer _object)
 {
   GObject *object = _object;
-  gpointer oldvalue;
+  gboolean was_floating;
   g_return_val_if_fail (G_IS_OBJECT (object), object);
   g_return_val_if_fail (object->ref_count >= 1, object);
   g_object_ref (object);
-  do
-    {
-      oldvalue = g_atomic_pointer_get (&object->qdata);
-    }
-  while (!g_atomic_pointer_compare_and_exchange ((void**) &object->qdata, oldvalue,
-                                                 (gpointer) ((gsize) oldvalue & ~(gsize) OBJECT_FLOATING_FLAG)));
-  if ((gsize) oldvalue & OBJECT_FLOATING_FLAG)
+  was_floating = floating_flag_handler (object, -1);
+  if (was_floating)
     g_object_unref (object);
   return object;
 }
@@ -1550,15 +1571,11 @@ g_object_ref_sink (gpointer _object)
 void
 g_object_force_floating (GObject *object)
 {
-  gpointer oldvalue;
+  gboolean was_floating;
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (object->ref_count >= 1);
-  do
-    {
-      oldvalue = g_atomic_pointer_get (&object->qdata);
-    }
-  while (!g_atomic_pointer_compare_and_exchange ((void**) &object->qdata, oldvalue,
-                                                 (gpointer) ((gsize) oldvalue | OBJECT_FLOATING_FLAG)));
+
+  was_floating = floating_flag_handler (object, +1);
 }
 
 typedef struct {
@@ -2181,5 +2198,34 @@ g_cclosure_new_object_swap (GCallback callback_func,
   return closure;
 }
 
+gsize
+g_object_compat_control (gsize           what,
+                         gpointer        data)
+{
+  switch (what)
+    {
+    case 1:     /* floating base type */
+      return G_TYPE_UNOWNED;
+    case 2:     /* FIXME: remove this once GLib/Gtk+ break ABI again */
+      floating_flag_handler = (guint(*)(GObject*,gint)) data;
+      return 1;
+    default:
+      return 0;
+    }
+}
+
+G_DEFINE_TYPE (GUnowned, g_unowned, G_TYPE_OBJECT);
+
+static void
+g_unowned_init (GUnowned *object)
+{
+  g_object_force_floating (object);
+}
+
+static void
+g_unowned_class_init (GUnownedClass *klass)
+{
+}
+
 #define __G_OBJECT_C__
 #include "gobjectaliasdef.c"
index bb684f4..71ba6d5 100644 (file)
@@ -44,10 +44,21 @@ G_BEGIN_DECLS
 #define G_OBJECT_CLASS_NAME(class)  (g_type_name (G_OBJECT_CLASS_TYPE (class)))
 #define G_VALUE_HOLDS_OBJECT(value) (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_OBJECT))
 
+/* --- type macros --- */
+#define G_TYPE_UNOWNED             (g_unowned_get_type())
+#define G_UNOWNED(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_UNOWNED, GUnowned))
+#define G_UNOWNED_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_UNOWNED, GUnownedClass))
+#define G_IS_UNOWNED(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_UNOWNED))
+#define G_IS_UNOWNED_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), G_TYPE_UNOWNED))
+#define G_UNOWNED_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), G_TYPE_UNOWNED, GUnownedClass))
+/* GUnowned ia a GObject with initially floating reference count */
+
 
 /* --- typedefs & structures --- */
 typedef struct _GObject                  GObject;
 typedef struct _GObjectClass             GObjectClass;
+typedef struct _GObject                  GUnowned;
+typedef struct _GObjectClass             GUnownedClass;
 typedef struct _GObjectConstructParam    GObjectConstructParam;
 typedef void (*GObjectGetPropertyFunc)  (GObject      *object,
                                          guint         property_id,
@@ -111,6 +122,7 @@ struct _GObjectConstructParam
 
 
 /* --- prototypes --- */
+GType       g_unowned_get_type                (void);
 void        g_object_class_install_property   (GObjectClass   *oclass,
                                               guint           property_id,
                                               GParamSpec     *pspec);
@@ -232,7 +244,6 @@ gulong          g_signal_connect_object           (gpointer        instance,
                                               gpointer        gobject,
                                               GConnectFlags   connect_flags);
 
-
 /*< protected >*/
 void        g_object_force_floating           (GObject        *object);
 void        g_object_run_dispose             (GObject        *object);
@@ -243,6 +254,8 @@ void        g_value_take_object               (GValue         *value,
 #ifndef G_DISABLE_DEPRECATED
 void        g_value_set_object_take_ownership (GValue         *value,
                                               gpointer        v_object);
+gsize      g_object_compat_control           (gsize           what,
+                                              gpointer        data);
 #endif
 
 /* --- implementation macros --- */
index bf23e6f..79f12b4 100644 (file)
@@ -160,6 +160,7 @@ g_value_dup_object
 g_value_take_object
 #ifndef G_DISABLE_DEPRECATED
 g_value_set_object_take_ownership
+g_object_compat_control
 #endif
 g_signal_connect_object
 #endif
index f970074..953bb8d 100644 (file)
@@ -1016,13 +1016,55 @@ param_override_values_cmp (GParamSpec   *pspec,
   return g_param_values_cmp (ospec->overridden, value1, value2);
 }
 
+static void
+param_gtype_init (GParamSpec *pspec)
+{
+}
+
+static void
+param_gtype_set_default (GParamSpec *pspec,
+                        GValue     *value)
+{
+  value->data[0].v_long = G_TYPE_NONE;
+}
+
+static gboolean
+param_gtype_validate (GParamSpec *pspec,
+                     GValue     *value)
+{
+  GParamSpecGType *tspec = G_PARAM_SPEC_GTYPE (pspec);
+  GType gtype = value->data[0].v_long;
+  guint changed = 0;
+  
+  if (tspec->is_a_type != G_TYPE_NONE && !g_type_is_a (gtype, tspec->is_a_type))
+    {
+      value->data[0].v_long = G_TYPE_NONE;
+      changed++;
+    }
+  
+  return changed;
+}
+
+static gint
+param_gtype_values_cmp (GParamSpec   *pspec,
+                       const GValue *value1,
+                       const GValue *value2)
+{
+  GType p1 = value1->data[0].v_long;
+  GType p2 = value2->data[0].v_long;
+
+  /* not much to compare here, try to at least provide stable lesser/greater result */
+
+  return p1 < p2 ? -1 : p1 > p2;
+}
+
 /* --- type initialization --- */
 GType *g_param_spec_types = NULL;
 
 void
 g_param_spec_types_init (void) 
 {
-  const guint n_types = 21;
+  const guint n_types = 22;
   GType type, *spec_types, *spec_types_bound;
 
   g_param_spec_types = g_new0 (GType, n_types);
@@ -1408,6 +1450,24 @@ g_param_spec_types_init (void)
     g_assert (type == G_TYPE_PARAM_OVERRIDE);
   }
 
+  /* G_TYPE_PARAM_GTYPE
+   */
+  {
+    GParamSpecTypeInfo pspec_info = {
+      sizeof (GParamSpecGType),        /* instance_size */
+      0,                       /* n_preallocs */
+      param_gtype_init,                /* instance_init */
+      G_TYPE_GTYPE,            /* value_type */
+      NULL,                    /* finalize */
+      param_gtype_set_default, /* value_set_default */
+      param_gtype_validate,    /* value_validate */
+      param_gtype_values_cmp,  /* values_cmp */
+    };
+    type = g_param_type_register_static (g_intern_static_string ("GParamGType"), &pspec_info);
+    *spec_types++ = type;
+    g_assert (type == G_TYPE_PARAM_GTYPE);
+  }
+
   g_assert (spec_types == spec_types_bound);
 }
 
@@ -1853,6 +1913,26 @@ g_param_spec_pointer (const gchar *name,
 }
 
 GParamSpec*
+g_param_spec_gtype (const gchar *name,
+                   const gchar *nick,
+                   const gchar *blurb,
+                   GType        is_a_type,
+                   GParamFlags  flags)
+{
+  GParamSpecGType *tspec;
+  
+  tspec = g_param_spec_internal (G_TYPE_PARAM_GTYPE,
+                                name,
+                                nick,
+                                blurb,
+                                flags);
+
+  tspec->is_a_type = is_a_type;
+
+  return G_PARAM_SPEC (tspec);
+}
+
+GParamSpec*
 g_param_spec_value_array (const gchar *name,
                          const gchar *nick,
                          const gchar *blurb,
index 137e1d0..b6add1c 100644 (file)
@@ -96,6 +96,9 @@ G_BEGIN_DECLS
 #define        G_TYPE_PARAM_OVERRIDE              (g_param_spec_types[20])
 #define G_IS_PARAM_SPEC_OVERRIDE(pspec)    (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_OVERRIDE))
 #define G_PARAM_SPEC_OVERRIDE(pspec)       (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_OVERRIDE, GParamSpecOverride))
+#define        G_TYPE_PARAM_GTYPE                 (g_param_spec_types[21])
+#define G_IS_PARAM_SPEC_GTYPE(pspec)       (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_GTYPE))
+#define G_PARAM_SPEC_GTYPE(pspec)          (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_GTYPE, GParamSpecGType))
 
 
 /* --- typedefs & structures --- */
@@ -120,6 +123,7 @@ typedef struct _GParamSpecPointer    GParamSpecPointer;
 typedef struct _GParamSpecValueArray GParamSpecValueArray;
 typedef struct _GParamSpecObject     GParamSpecObject;
 typedef struct _GParamSpecOverride   GParamSpecOverride;
+typedef struct _GParamSpecGType      GParamSpecGType;
 
 struct _GParamSpecChar
 {
@@ -268,6 +272,11 @@ struct _GParamSpecOverride
   GParamSpec    parent_instance;
   GParamSpec   *overridden;
 };
+struct _GParamSpecGType
+{
+  GParamSpec    parent_instance;
+  GType         is_a_type;
+};
 
 /* --- GParamSpec prototypes --- */
 GParamSpec*    g_param_spec_char        (const gchar    *name,
@@ -391,9 +400,13 @@ GParamSpec*        g_param_spec_object      (const gchar    *name,
                                          const gchar    *blurb,
                                          GType           object_type,
                                          GParamFlags     flags);
-
 GParamSpec*     g_param_spec_override    (const gchar    *name,
                                          GParamSpec     *overridden);
+GParamSpec*    g_param_spec_gtype       (const gchar    *name,
+                                         const gchar    *nick,
+                                         const gchar    *blurb,
+                                         GType           is_a_type,
+                                         GParamFlags     flags);
 
 /* --- internal --- */
 /* We prefix variable declarations so they can
index cb3de7e..7bfc9f6 100644 (file)
@@ -818,6 +818,35 @@ g_value_get_pointer (const GValue *value)
   return value->data[0].v_pointer;
 }
 
+GType
+g_gtype_get_type (void)
+{
+  static const GTypeInfo type_info = { 0, };
+  static GType type;
+  if (!type)
+    type = g_type_register_static (G_TYPE_POINTER, g_intern_static_string ("GType"), &type_info, 0);
+  return type;
+}
+
+void 
+g_value_set_gtype (GValue *value,
+                  GType   v_gtype)
+{
+  g_return_if_fail (G_VALUE_HOLDS_GTYPE (value));
+
+  value->data[0].v_long = v_gtype;
+  
+}
+
+GType                
+g_value_get_gtype (const GValue *value)
+{
+  g_return_val_if_fail (G_VALUE_HOLDS_GTYPE (value), 0);
+
+  return value->data[0].v_long;
+}
+
+
 /* need extra includes for g_strdup_value_contents() ;( */
 #include "gobject.h"
 #include "gparam.h"
index dfe9ce3..2931cda 100644 (file)
@@ -43,6 +43,8 @@ G_BEGIN_DECLS
 #define G_VALUE_HOLDS_DOUBLE(value)     (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_DOUBLE))
 #define G_VALUE_HOLDS_STRING(value)     (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_STRING))
 #define G_VALUE_HOLDS_POINTER(value)    (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_POINTER))
+#define        G_TYPE_GTYPE                     (g_gtype_get_type())
+#define G_VALUE_HOLDS_GTYPE(value)      (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_GTYPE))
 
 
 /* --- prototypes --- */
@@ -88,6 +90,10 @@ gchar*                     g_value_dup_string        (const GValue *value);
 void                 g_value_set_pointer       (GValue       *value,
                                                 gpointer      v_pointer);
 gpointer             g_value_get_pointer       (const GValue *value);
+GType                g_gtype_get_type          (void);
+void                 g_value_set_gtype         (GValue       *value,
+                                                GType         v_gtype);
+GType                g_value_get_gtype         (const GValue *value);
 
 
 /* Convenience for registering new pointer types */