mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-09-28 01:57:14 +02:00
GParamSpec: add g_param_spec_get_default_value()
The way of getting the default value out of a GParamSpec is to allocate a GValue, initialise it, then call g_param_spec_set_default() to set the default value into that GValue. This is exactly how we handle setting the default value for all of the construct properties that were not explicitly passed to g_object_new(). Instead of doing the alloc/init/store on all construct properties on every call to g_object_new(), we can cache those GValues in the private data of the GParamSpec itself and reuse them. This patch does not actually make that change to g_object_new() yet, but it adds the API to GParamSpec so that a future patch to GObject can make the change. https://bugzilla.gnome.org/show_bug.cgi?id=698056
This commit is contained in:
@@ -480,6 +480,7 @@ g_param_spec_ref
|
|||||||
g_param_spec_unref
|
g_param_spec_unref
|
||||||
g_param_spec_sink
|
g_param_spec_sink
|
||||||
g_param_spec_ref_sink
|
g_param_spec_ref_sink
|
||||||
|
g_param_spec_get_default_value
|
||||||
g_param_value_set_default
|
g_param_value_set_default
|
||||||
g_param_value_defaults
|
g_param_value_defaults
|
||||||
g_param_value_validate
|
g_param_value_validate
|
||||||
|
@@ -80,6 +80,13 @@ static gchar* value_param_lcopy_value (const GValue *value,
|
|||||||
GTypeCValue *collect_values,
|
GTypeCValue *collect_values,
|
||||||
guint collect_flags);
|
guint collect_flags);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GValue default_value;
|
||||||
|
} GParamSpecPrivate;
|
||||||
|
|
||||||
|
static gint g_param_private_offset;
|
||||||
|
#define PRIV(inst) (&G_STRUCT_MEMBER(GParamSpecPrivate, (inst), g_param_private_offset))
|
||||||
|
|
||||||
/* --- functions --- */
|
/* --- functions --- */
|
||||||
void
|
void
|
||||||
@@ -147,6 +154,9 @@ g_param_spec_class_init (GParamSpecClass *class,
|
|||||||
class->value_set_default = NULL;
|
class->value_set_default = NULL;
|
||||||
class->value_validate = NULL;
|
class->value_validate = NULL;
|
||||||
class->values_cmp = NULL;
|
class->values_cmp = NULL;
|
||||||
|
|
||||||
|
g_type_class_add_private (class, sizeof (GParamSpecPrivate));
|
||||||
|
g_param_private_offset = g_type_class_get_instance_private_offset (class);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -168,6 +178,11 @@ g_param_spec_init (GParamSpec *pspec,
|
|||||||
static void
|
static void
|
||||||
g_param_spec_finalize (GParamSpec *pspec)
|
g_param_spec_finalize (GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
|
GParamSpecPrivate *priv = PRIV (pspec);
|
||||||
|
|
||||||
|
if (priv->default_value.g_type)
|
||||||
|
g_value_reset (&priv->default_value);
|
||||||
|
|
||||||
g_datalist_clear (&pspec->qdata);
|
g_datalist_clear (&pspec->qdata);
|
||||||
|
|
||||||
if (!(pspec->flags & G_PARAM_STATIC_NICK))
|
if (!(pspec->flags & G_PARAM_STATIC_NICK))
|
||||||
@@ -1506,3 +1521,50 @@ g_value_dup_param (const GValue *value)
|
|||||||
|
|
||||||
return value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
|
return value->data[0].v_pointer ? g_param_spec_ref (value->data[0].v_pointer) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_param_get_default_value:
|
||||||
|
* @param: a #GParamSpec
|
||||||
|
*
|
||||||
|
* Gets the default value of @param as a pointer to a #GValue.
|
||||||
|
*
|
||||||
|
* The #GValue will remain value for the life of @param.
|
||||||
|
*
|
||||||
|
* Returns: a pointer to a #GValue which must not be modified
|
||||||
|
*
|
||||||
|
* Since: 2.38
|
||||||
|
**/
|
||||||
|
const GValue *
|
||||||
|
g_param_spec_get_default_value (GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GParamSpecPrivate *priv = PRIV (pspec);
|
||||||
|
|
||||||
|
/* We use the type field of the GValue as the key for the once because
|
||||||
|
* it will be zero before it is initialised and non-zero after. We
|
||||||
|
* have to take care that we don't write a non-zero value to the type
|
||||||
|
* field before we are completely done, however, because then another
|
||||||
|
* thread could come along and find the value partially-initialised.
|
||||||
|
*
|
||||||
|
* In order to accomplish this we store the default value in a
|
||||||
|
* stack-allocated GValue. We then set the type field in that value
|
||||||
|
* to zero and copy the contents into place. We then end by storing
|
||||||
|
* the type as the last step in order to ensure that we're completely
|
||||||
|
* done before a g_once_init_enter() could take the fast path in
|
||||||
|
* another thread.
|
||||||
|
*/
|
||||||
|
if (g_once_init_enter (&priv->default_value.g_type))
|
||||||
|
{
|
||||||
|
GValue default_value = G_VALUE_INIT;
|
||||||
|
|
||||||
|
g_value_init (&default_value, pspec->value_type);
|
||||||
|
g_param_value_set_default (pspec, &default_value);
|
||||||
|
|
||||||
|
/* store all but the type */
|
||||||
|
default_value.g_type = 0;
|
||||||
|
priv->default_value = default_value;
|
||||||
|
|
||||||
|
g_once_init_leave (&priv->default_value.g_type, pspec->value_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &priv->default_value;
|
||||||
|
}
|
||||||
|
@@ -336,6 +336,8 @@ void g_value_take_param (GValue *value,
|
|||||||
GLIB_DEPRECATED_FOR(g_value_take_param)
|
GLIB_DEPRECATED_FOR(g_value_take_param)
|
||||||
void g_value_set_param_take_ownership (GValue *value,
|
void g_value_set_param_take_ownership (GValue *value,
|
||||||
GParamSpec *param);
|
GParamSpec *param);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
const GValue * g_param_spec_get_default_value (GParamSpec *param);
|
||||||
|
|
||||||
/* --- convenience functions --- */
|
/* --- convenience functions --- */
|
||||||
typedef struct _GParamSpecTypeInfo GParamSpecTypeInfo;
|
typedef struct _GParamSpecTypeInfo GParamSpecTypeInfo;
|
||||||
@@ -421,7 +423,6 @@ GParamSpec** g_param_spec_pool_list (GParamSpecPool *pool,
|
|||||||
guint *n_pspecs_p);
|
guint *n_pspecs_p);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* contracts:
|
/* contracts:
|
||||||
*
|
*
|
||||||
* gboolean value_validate (GParamSpec *pspec,
|
* gboolean value_validate (GParamSpec *pspec,
|
||||||
|
@@ -786,6 +786,21 @@ test_param_implement (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_param_default (void)
|
||||||
|
{
|
||||||
|
GParamSpec *param;
|
||||||
|
const GValue *def;
|
||||||
|
|
||||||
|
param = g_param_spec_int ("my-int", "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
|
||||||
|
def = g_param_spec_get_default_value (param);
|
||||||
|
|
||||||
|
g_assert (G_VALUE_HOLDS (def, G_TYPE_INT));
|
||||||
|
g_assert_cmpint (g_value_get_int (def), ==, 10);
|
||||||
|
|
||||||
|
g_param_spec_unref (param);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -798,6 +813,7 @@ main (int argc, char *argv[])
|
|||||||
g_test_add_func ("/param/convert", test_param_convert);
|
g_test_add_func ("/param/convert", test_param_convert);
|
||||||
g_test_add_func ("/param/implement", test_param_implement);
|
g_test_add_func ("/param/implement", test_param_implement);
|
||||||
g_test_add_func ("/value/transform", test_value_transform);
|
g_test_add_func ("/value/transform", test_value_transform);
|
||||||
|
g_test_add_func ("/param/default", test_param_default);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user