mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-24 03:02:10 +01:00
This is mostly a WIP/proof of concept patch on top of GProperty. the numbers from the performance test case say that we don't gain much, if at all, by checking if the property maps to a direct field offset, and we get the pointer to the struct member.
1500 lines
38 KiB
C
1500 lines
38 KiB
C
/* GObject - GLib Type, Object, Parameter and Signal Library
|
|
* Copyright (C) 2009 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General
|
|
* Public License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include <glib-object.h>
|
|
#include "testcommon.h"
|
|
|
|
#define WARM_UP_N_RUNS 50
|
|
#define ESTIMATE_ROUND_TIME_N_RUNS 5
|
|
#define DEFAULT_TEST_TIME 15 /* seconds */
|
|
/* The time we want each round to take, in seconds, this should
|
|
* be large enough compared to the timer resolution, but small
|
|
* enought that the risk of any random slowness will miss the
|
|
* running window */
|
|
#define TARGET_ROUND_TIME 0.004
|
|
|
|
static gboolean verbose = FALSE;
|
|
static int test_length = DEFAULT_TEST_TIME;
|
|
|
|
static GOptionEntry cmd_entries[] = {
|
|
{"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
|
|
"Print extra information", NULL},
|
|
{"seconds", 's', 0, G_OPTION_ARG_INT, &test_length,
|
|
"Time to run each test in seconds", NULL},
|
|
{NULL}
|
|
};
|
|
|
|
typedef struct _PerformanceTest PerformanceTest;
|
|
struct _PerformanceTest {
|
|
const char *name;
|
|
gpointer extra_data;
|
|
|
|
gpointer (*setup) (PerformanceTest *test);
|
|
void (*init) (PerformanceTest *test,
|
|
gpointer data,
|
|
double factor);
|
|
void (*run) (PerformanceTest *test,
|
|
gpointer data);
|
|
void (*finish) (PerformanceTest *test,
|
|
gpointer data);
|
|
void (*teardown) (PerformanceTest *test,
|
|
gpointer data);
|
|
void (*print_result) (PerformanceTest *test,
|
|
gpointer data,
|
|
double time);
|
|
};
|
|
|
|
static void
|
|
run_test (PerformanceTest *test)
|
|
{
|
|
gpointer data = NULL;
|
|
guint64 i, num_rounds;
|
|
double elapsed, min_elapsed, factor;
|
|
GTimer *timer;
|
|
|
|
g_print ("Running test %s\n", test->name);
|
|
|
|
/* Set up test */
|
|
timer = g_timer_new ();
|
|
data = test->setup (test);
|
|
|
|
if (verbose)
|
|
g_print ("Warming up\n");
|
|
|
|
/* Warm up the test by doing a few runs */
|
|
for (i = 0; i < WARM_UP_N_RUNS; i++)
|
|
{
|
|
test->init (test, data, 1.0);
|
|
test->run (test, data);
|
|
test->finish (test, data);
|
|
}
|
|
|
|
if (verbose)
|
|
g_print ("Estimating round time\n");
|
|
|
|
/* Estimate time for one run by doing a few test rounds */
|
|
min_elapsed = 0;
|
|
for (i = 0; i < ESTIMATE_ROUND_TIME_N_RUNS; i++)
|
|
{
|
|
test->init (test, data, 1.0);
|
|
g_timer_start (timer);
|
|
test->run (test, data);
|
|
g_timer_stop (timer);
|
|
test->finish (test, data);
|
|
|
|
elapsed = g_timer_elapsed (timer, NULL);
|
|
if (i == 0)
|
|
min_elapsed = elapsed;
|
|
else
|
|
min_elapsed = MIN (min_elapsed, elapsed);
|
|
}
|
|
|
|
factor = TARGET_ROUND_TIME / min_elapsed;
|
|
|
|
if (verbose)
|
|
g_print ("Uncorrected round time: %f.4 secs, correction factor %f.2\n", min_elapsed, factor);
|
|
|
|
/* Calculate number of rounds needed */
|
|
num_rounds = (test_length / TARGET_ROUND_TIME) + 1;
|
|
|
|
if (verbose)
|
|
g_print ("Running %"G_GINT64_MODIFIER"d rounds\n", num_rounds);
|
|
|
|
/* Run the test */
|
|
for (i = 0; i < num_rounds; i++)
|
|
{
|
|
test->init (test, data, factor);
|
|
g_timer_start (timer);
|
|
test->run (test, data);
|
|
g_timer_stop (timer);
|
|
test->finish (test, data);
|
|
elapsed = g_timer_elapsed (timer, NULL);
|
|
|
|
if (i == 0)
|
|
min_elapsed = elapsed;
|
|
else
|
|
min_elapsed = MIN (min_elapsed, elapsed);
|
|
}
|
|
|
|
if (verbose)
|
|
g_print ("Minimum corrected round time: %f secs\n", min_elapsed);
|
|
|
|
/* Print the results */
|
|
test->print_result (test, data, min_elapsed);
|
|
|
|
/* Tear down */
|
|
test->teardown (test, data);
|
|
g_timer_destroy (timer);
|
|
}
|
|
|
|
/*************************************************************
|
|
* Simple object is a very simple small GObject subclass
|
|
* with no properties, no signals, implementing no interfaces
|
|
*************************************************************/
|
|
|
|
static GType simple_object_get_type (void);
|
|
#define SIMPLE_TYPE_OBJECT (simple_object_get_type ())
|
|
typedef struct _SimpleObject SimpleObject;
|
|
typedef struct _SimpleObjectClass SimpleObjectClass;
|
|
|
|
struct _SimpleObject
|
|
{
|
|
GObject parent_instance;
|
|
int val;
|
|
};
|
|
|
|
struct _SimpleObjectClass
|
|
{
|
|
GObjectClass parent_class;
|
|
};
|
|
|
|
G_DEFINE_TYPE (SimpleObject, simple_object, G_TYPE_OBJECT);
|
|
|
|
static void
|
|
simple_object_finalize (GObject *object)
|
|
{
|
|
G_OBJECT_CLASS (simple_object_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
simple_object_class_init (SimpleObjectClass *class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
|
|
object_class->finalize = simple_object_finalize;
|
|
}
|
|
|
|
static void
|
|
simple_object_init (SimpleObject *simple_object)
|
|
{
|
|
simple_object->val = 42;
|
|
}
|
|
|
|
typedef struct _TestIfaceClass TestIfaceClass;
|
|
typedef struct _TestIfaceClass TestIface1Class;
|
|
typedef struct _TestIfaceClass TestIface2Class;
|
|
typedef struct _TestIfaceClass TestIface3Class;
|
|
typedef struct _TestIfaceClass TestIface4Class;
|
|
typedef struct _TestIfaceClass TestIface5Class;
|
|
typedef struct _TestIface TestIface;
|
|
|
|
struct _TestIfaceClass
|
|
{
|
|
GTypeInterface base_iface;
|
|
void (*method) (TestIface *obj);
|
|
};
|
|
|
|
static GType test_iface1_get_type (void);
|
|
static GType test_iface2_get_type (void);
|
|
static GType test_iface3_get_type (void);
|
|
static GType test_iface4_get_type (void);
|
|
static GType test_iface5_get_type (void);
|
|
|
|
#define TEST_TYPE_IFACE1 (test_iface1_get_type ())
|
|
#define TEST_TYPE_IFACE2 (test_iface2_get_type ())
|
|
#define TEST_TYPE_IFACE3 (test_iface3_get_type ())
|
|
#define TEST_TYPE_IFACE4 (test_iface4_get_type ())
|
|
#define TEST_TYPE_IFACE5 (test_iface5_get_type ())
|
|
|
|
static DEFINE_IFACE (TestIface1, test_iface1, NULL, NULL)
|
|
static DEFINE_IFACE (TestIface2, test_iface2, NULL, NULL)
|
|
static DEFINE_IFACE (TestIface3, test_iface3, NULL, NULL)
|
|
static DEFINE_IFACE (TestIface4, test_iface4, NULL, NULL)
|
|
static DEFINE_IFACE (TestIface5, test_iface5, NULL, NULL)
|
|
|
|
/*************************************************************
|
|
* Complex object is a GObject subclass with a properties,
|
|
* construct properties, signals and implementing an interface.
|
|
*************************************************************/
|
|
|
|
static GType complex_object_get_type (void);
|
|
#define COMPLEX_TYPE_OBJECT (complex_object_get_type ())
|
|
typedef struct _ComplexObject ComplexObject;
|
|
typedef struct _ComplexObjectClass ComplexObjectClass;
|
|
|
|
struct _ComplexObject
|
|
{
|
|
GObject parent_instance;
|
|
int val1;
|
|
int val2;
|
|
};
|
|
|
|
struct _ComplexObjectClass
|
|
{
|
|
GObjectClass parent_class;
|
|
|
|
void (*signal) (ComplexObject *obj);
|
|
void (*signal_empty) (ComplexObject *obj);
|
|
};
|
|
|
|
static void complex_test_iface_init (gpointer g_iface,
|
|
gpointer iface_data);
|
|
|
|
G_DEFINE_TYPE_EXTENDED (ComplexObject, complex_object,
|
|
G_TYPE_OBJECT, 0,
|
|
G_IMPLEMENT_INTERFACE (TEST_TYPE_IFACE1,
|
|
complex_test_iface_init)
|
|
G_IMPLEMENT_INTERFACE (TEST_TYPE_IFACE2,
|
|
complex_test_iface_init)
|
|
G_IMPLEMENT_INTERFACE (TEST_TYPE_IFACE3,
|
|
complex_test_iface_init)
|
|
G_IMPLEMENT_INTERFACE (TEST_TYPE_IFACE4,
|
|
complex_test_iface_init)
|
|
G_IMPLEMENT_INTERFACE (TEST_TYPE_IFACE5,
|
|
complex_test_iface_init)
|
|
);
|
|
|
|
#define COMPLEX_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), COMPLEX_TYPE_OBJECT, ComplexObject))
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_VAL1,
|
|
PROP_VAL2
|
|
};
|
|
|
|
enum {
|
|
COMPLEX_SIGNAL,
|
|
COMPLEX_SIGNAL_EMPTY,
|
|
COMPLEX_SIGNAL_GENERIC,
|
|
COMPLEX_SIGNAL_GENERIC_EMPTY,
|
|
COMPLEX_LAST_SIGNAL
|
|
};
|
|
|
|
static guint complex_signals[COMPLEX_LAST_SIGNAL] = { 0 };
|
|
|
|
static void
|
|
complex_object_finalize (GObject *object)
|
|
{
|
|
G_OBJECT_CLASS (complex_object_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
complex_object_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
ComplexObject *complex = COMPLEX_OBJECT (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_VAL1:
|
|
complex->val1 = g_value_get_int (value);
|
|
break;
|
|
case PROP_VAL2:
|
|
complex->val2 = g_value_get_int (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
complex_object_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
ComplexObject *complex = COMPLEX_OBJECT (object);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_VAL1:
|
|
g_value_set_int (value, complex->val1);
|
|
break;
|
|
case PROP_VAL2:
|
|
g_value_set_int (value, complex->val2);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
complex_object_real_signal (ComplexObject *obj)
|
|
{
|
|
}
|
|
|
|
static void
|
|
complex_object_class_init (ComplexObjectClass *class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
|
|
object_class->finalize = complex_object_finalize;
|
|
object_class->set_property = complex_object_set_property;
|
|
object_class->get_property = complex_object_get_property;
|
|
|
|
class->signal = complex_object_real_signal;
|
|
|
|
complex_signals[COMPLEX_SIGNAL] =
|
|
g_signal_new ("signal",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (ComplexObjectClass, signal),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
|
|
complex_signals[COMPLEX_SIGNAL_EMPTY] =
|
|
g_signal_new ("signal-empty",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (ComplexObjectClass, signal_empty),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
|
|
complex_signals[COMPLEX_SIGNAL_GENERIC] =
|
|
g_signal_new ("signal-generic",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (ComplexObjectClass, signal),
|
|
NULL, NULL,
|
|
NULL,
|
|
G_TYPE_NONE, 0);
|
|
complex_signals[COMPLEX_SIGNAL_GENERIC_EMPTY] =
|
|
g_signal_new ("signal-generic-empty",
|
|
G_TYPE_FROM_CLASS (object_class),
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (ComplexObjectClass, signal_empty),
|
|
NULL, NULL,
|
|
NULL,
|
|
G_TYPE_NONE, 0);
|
|
|
|
g_object_class_install_property (object_class,
|
|
PROP_VAL1,
|
|
g_param_spec_int ("val1",
|
|
"val1",
|
|
"val1",
|
|
0,
|
|
G_MAXINT,
|
|
42,
|
|
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
|
|
g_object_class_install_property (object_class,
|
|
PROP_VAL2,
|
|
g_param_spec_int ("val2",
|
|
"val2",
|
|
"val2",
|
|
0,
|
|
G_MAXINT,
|
|
43,
|
|
G_PARAM_READWRITE));
|
|
|
|
|
|
}
|
|
|
|
static void
|
|
complex_object_iface_method (TestIface *obj)
|
|
{
|
|
ComplexObject *complex = COMPLEX_OBJECT (obj);
|
|
complex->val1++;
|
|
}
|
|
|
|
static void
|
|
complex_test_iface_init (gpointer g_iface,
|
|
gpointer iface_data)
|
|
{
|
|
TestIfaceClass *iface = g_iface;
|
|
iface->method = complex_object_iface_method;
|
|
}
|
|
|
|
static void
|
|
complex_object_init (ComplexObject *complex_object)
|
|
{
|
|
complex_object->val2 = 43;
|
|
}
|
|
|
|
/****************************************************************
|
|
* ParamspecObject is an object using GParamSpec for properties *
|
|
****************************************************************/
|
|
|
|
#define PARAMSPEC_TYPE_OBJECT (paramspec_object_get_type ())
|
|
typedef struct _ParamspecObject ParamspecObject;
|
|
typedef struct _ParamspecObjectClass ParamspecObjectClass;
|
|
typedef struct _ParamspecObjectPrivate ParamspecObjectPrivate;
|
|
|
|
struct _ParamspecObject
|
|
{
|
|
GObject parent_instance;
|
|
|
|
ParamspecObjectPrivate *priv;
|
|
};
|
|
|
|
struct _ParamspecObjectClass
|
|
{
|
|
GObjectClass parent_class;
|
|
};
|
|
|
|
GType paramspec_object_get_type (void); /* for -Wmissing-prototypes */
|
|
|
|
G_DEFINE_TYPE (ParamspecObject, paramspec_object, G_TYPE_OBJECT)
|
|
|
|
#define PARAMSPEC_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PARAMSPEC_TYPE_OBJECT, ParamspecObject))
|
|
|
|
struct _ParamspecObjectPrivate
|
|
{
|
|
int foo;
|
|
gchar *bar;
|
|
float baz;
|
|
};
|
|
|
|
enum {
|
|
PROP_PSPEC_0,
|
|
PROP_PSPEC_FOO,
|
|
PROP_PSPEC_BAR,
|
|
PROP_PSPEC_BAZ,
|
|
PROP_PSPEC_LAST
|
|
};
|
|
|
|
static GParamSpec *pspec_props[PROP_PSPEC_LAST] = { NULL, };
|
|
|
|
static void
|
|
paramspec_object_finalize (GObject *object)
|
|
{
|
|
ParamspecObjectPrivate *priv = PARAMSPEC_OBJECT (object)->priv;
|
|
|
|
g_free (priv->bar);
|
|
|
|
G_OBJECT_CLASS (paramspec_object_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
paramspec_object_set_foo (ParamspecObject *object,
|
|
int value)
|
|
{
|
|
if (object->priv->foo == value)
|
|
return;
|
|
|
|
object->priv->foo = value;
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (object), pspec_props[PROP_PSPEC_FOO]);
|
|
}
|
|
|
|
static int
|
|
paramspec_object_get_foo (ParamspecObject *object)
|
|
{
|
|
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (object, paramspec_object_get_type ()), 0);
|
|
|
|
return object->priv->foo;
|
|
}
|
|
|
|
static void
|
|
paramspec_object_set_bar (ParamspecObject *object,
|
|
const char *value)
|
|
{
|
|
if (g_strcmp0 (object->priv->bar, value) == 0)
|
|
return;
|
|
|
|
g_free (object->priv->bar);
|
|
object->priv->bar = g_strdup (value);
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (object), pspec_props[PROP_PSPEC_BAR]);
|
|
}
|
|
|
|
static void
|
|
paramspec_object_set_baz (ParamspecObject *object,
|
|
float value)
|
|
{
|
|
if (object->priv->baz == value)
|
|
return;
|
|
|
|
object->priv->baz = value;
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (object), pspec_props[PROP_PSPEC_BAZ]);
|
|
}
|
|
|
|
static float
|
|
paramspec_object_get_baz (ParamspecObject *object)
|
|
{
|
|
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (object, paramspec_object_get_type ()), 0.0);
|
|
|
|
return object->priv->baz;
|
|
}
|
|
|
|
static void
|
|
paramspec_object_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
switch (prop_id)
|
|
{
|
|
case PROP_PSPEC_FOO:
|
|
paramspec_object_set_foo (PARAMSPEC_OBJECT (object), g_value_get_int (value));
|
|
break;
|
|
case PROP_PSPEC_BAR:
|
|
paramspec_object_set_bar (PARAMSPEC_OBJECT (object), g_value_get_string (value));
|
|
break;
|
|
case PROP_PSPEC_BAZ:
|
|
paramspec_object_set_baz (PARAMSPEC_OBJECT (object), g_value_get_float (value));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
paramspec_object_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
switch (prop_id)
|
|
{
|
|
case PROP_PSPEC_FOO:
|
|
g_value_set_int (value, PARAMSPEC_OBJECT (object)->priv->foo);
|
|
break;
|
|
case PROP_PSPEC_BAR:
|
|
g_value_set_string (value, PARAMSPEC_OBJECT (object)->priv->bar);
|
|
break;
|
|
case PROP_PSPEC_BAZ:
|
|
g_value_set_float (value, PARAMSPEC_OBJECT (object)->priv->baz);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
paramspec_object_class_init (ParamspecObjectClass *class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
|
|
g_type_class_add_private (class, sizeof (ParamspecObjectPrivate));
|
|
|
|
object_class->finalize = paramspec_object_finalize;
|
|
object_class->set_property = paramspec_object_set_property;
|
|
object_class->get_property = paramspec_object_get_property;
|
|
|
|
pspec_props[PROP_PSPEC_FOO] =
|
|
g_param_spec_int ("foo",
|
|
NULL, NULL,
|
|
-100, 100, 50,
|
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
|
pspec_props[PROP_PSPEC_BAR] =
|
|
g_param_spec_string ("bar",
|
|
NULL, NULL,
|
|
"Hello",
|
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
|
pspec_props[PROP_PSPEC_BAZ] =
|
|
g_param_spec_float ("baz",
|
|
NULL, NULL,
|
|
0.0f, G_MAXFLOAT, 0.0f,
|
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
|
|
|
g_object_class_install_properties (object_class, PROP_PSPEC_LAST, pspec_props);
|
|
}
|
|
|
|
static void
|
|
paramspec_object_init (ParamspecObject *self)
|
|
{
|
|
self->priv = g_type_instance_get_private ((GTypeInstance *) self, PARAMSPEC_TYPE_OBJECT);
|
|
|
|
self->priv->foo = 50;
|
|
self->priv->bar = g_strdup ("Hello");
|
|
self->priv->baz = 0.0f;
|
|
}
|
|
|
|
/**************************************************************
|
|
* PropertyObject is an object using GProperty for properties *
|
|
**************************************************************/
|
|
|
|
#define PROPERTY_TYPE_OBJECT (property_object_get_type ())
|
|
typedef struct _PropertyObject PropertyObject;
|
|
typedef struct _PropertyObjectClass PropertyObjectClass;
|
|
typedef struct _PropertyObjectPrivate PropertyObjectPrivate;
|
|
|
|
struct _PropertyObject
|
|
{
|
|
GObject parent_instance;
|
|
|
|
PropertyObjectPrivate *priv;
|
|
};
|
|
|
|
struct _PropertyObjectClass
|
|
{
|
|
GObjectClass parent_class;
|
|
};
|
|
|
|
GType property_object_get_type (void); /* for -Wmissing-prototypes */
|
|
|
|
G_DEFINE_TYPE (PropertyObject, property_object, G_TYPE_OBJECT)
|
|
|
|
#define PROPERTY_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PROPERTY_TYPE_OBJECT, PropertyObject))
|
|
|
|
struct _PropertyObjectPrivate
|
|
{
|
|
int foo;
|
|
gchar *bar;
|
|
float baz;
|
|
};
|
|
|
|
enum {
|
|
PROP_PROPERTY_0,
|
|
PROP_PROPERTY_FOO,
|
|
PROP_PROPERTY_BAR,
|
|
PROP_PROPERTY_BAZ,
|
|
PROP_PROPERTY_LAST
|
|
};
|
|
|
|
static GParamSpec *property_props[PROP_PROPERTY_LAST] = { NULL, };
|
|
|
|
static void
|
|
property_object_finalize (GObject *object)
|
|
{
|
|
PropertyObjectPrivate *priv = PROPERTY_OBJECT (object)->priv;
|
|
|
|
g_free (priv->bar);
|
|
|
|
G_OBJECT_CLASS (property_object_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
property_object_class_init (PropertyObjectClass *class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
|
|
g_type_class_add_private (class, sizeof (PropertyObjectPrivate));
|
|
|
|
object_class->finalize = property_object_finalize;
|
|
|
|
property_props[PROP_PROPERTY_FOO] =
|
|
g_int_property_new ("foo", G_PROPERTY_READWRITE,
|
|
G_STRUCT_OFFSET (PropertyObjectPrivate, foo),
|
|
NULL, NULL);
|
|
g_property_set_range ((GProperty *) property_props[PROP_PROPERTY_FOO], -100, 100);
|
|
g_property_set_default ((GProperty *) property_props[PROP_PROPERTY_FOO], 50);
|
|
|
|
property_props[PROP_PROPERTY_BAR] =
|
|
g_string_property_new ("bar", G_PROPERTY_READWRITE,
|
|
G_STRUCT_OFFSET (PropertyObjectPrivate, bar),
|
|
NULL, NULL);
|
|
g_property_set_default ((GProperty *) property_props[PROP_PROPERTY_BAR], "Hello");
|
|
|
|
property_props[PROP_PROPERTY_BAZ] =
|
|
g_float_property_new ("baz", G_PROPERTY_READWRITE,
|
|
G_STRUCT_OFFSET (PropertyObjectPrivate, baz),
|
|
NULL, NULL);
|
|
g_property_set_range ((GProperty *) property_props[PROP_PROPERTY_BAZ], 0.0f, G_MAXFLOAT);
|
|
g_property_set_default ((GProperty *) property_props[PROP_PROPERTY_BAZ], 0.0f);
|
|
|
|
g_object_class_install_properties (object_class, PROP_PROPERTY_LAST, property_props);
|
|
}
|
|
|
|
static void
|
|
property_object_init (PropertyObject *self)
|
|
{
|
|
self->priv = g_type_instance_get_private ((GTypeInstance *) self, PROPERTY_TYPE_OBJECT);
|
|
|
|
g_property_get_default ((GProperty *) property_props[PROP_PROPERTY_FOO],
|
|
self,
|
|
&(self->priv->foo));
|
|
g_property_get_default ((GProperty *) property_props[PROP_PROPERTY_BAR],
|
|
self,
|
|
&(self->priv->bar));
|
|
g_property_get_default ((GProperty *) property_props[PROP_PROPERTY_BAZ],
|
|
self,
|
|
&(self->priv->baz));
|
|
}
|
|
|
|
static void
|
|
property_object_set_foo (PropertyObject *self, int value)
|
|
{
|
|
g_property_set (((GProperty *) property_props[PROP_PROPERTY_FOO]), self, value);
|
|
}
|
|
|
|
static int
|
|
property_object_get_foo (PropertyObject *self)
|
|
{
|
|
gint value;
|
|
|
|
if (g_property_is_direct_get (((GProperty *) property_props[PROP_PROPERTY_FOO])))
|
|
{
|
|
gpointer field_p = g_property_get_field (((GProperty *) property_props[PROP_PROPERTY_FOO]), self);
|
|
return (* (int *) field_p);
|
|
}
|
|
|
|
g_property_get (((GProperty *) property_props[PROP_PROPERTY_FOO]), self, &value);
|
|
|
|
return value;
|
|
}
|
|
|
|
static void
|
|
property_object_set_baz (PropertyObject *self, float value)
|
|
{
|
|
g_property_set (((GProperty *) property_props[PROP_PROPERTY_BAZ]), self, value);
|
|
}
|
|
|
|
static float
|
|
property_object_get_baz (PropertyObject *self)
|
|
{
|
|
float value;
|
|
|
|
if (g_property_is_direct_get (((GProperty *) property_props[PROP_PROPERTY_BAZ])))
|
|
{
|
|
gpointer field_p = g_property_get_field (((GProperty *) property_props[PROP_PROPERTY_BAZ]), self);
|
|
return (* (float *) field_p);
|
|
}
|
|
|
|
g_property_get (((GProperty *) property_props[PROP_PROPERTY_BAZ]), self, &value);
|
|
|
|
return value;
|
|
}
|
|
|
|
/*************************************************************
|
|
* Test object construction performance
|
|
*************************************************************/
|
|
|
|
#define NUM_OBJECT_TO_CONSTRUCT 10000
|
|
|
|
struct ConstructionTest {
|
|
GObject **objects;
|
|
int n_objects;
|
|
GType type;
|
|
};
|
|
|
|
static gpointer
|
|
test_construction_setup (PerformanceTest *test)
|
|
{
|
|
struct ConstructionTest *data;
|
|
|
|
data = g_new0 (struct ConstructionTest, 1);
|
|
data->type = ((GType (*)(void))test->extra_data)();
|
|
|
|
return data;
|
|
}
|
|
|
|
static void
|
|
test_construction_init (PerformanceTest *test,
|
|
gpointer _data,
|
|
double count_factor)
|
|
{
|
|
struct ConstructionTest *data = _data;
|
|
int n;
|
|
|
|
n = NUM_OBJECT_TO_CONSTRUCT * count_factor;
|
|
if (data->n_objects != n)
|
|
{
|
|
data->n_objects = n;
|
|
data->objects = g_new (GObject *, n);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_construction_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct ConstructionTest *data = _data;
|
|
GObject **objects = data->objects;
|
|
GType type = data->type;
|
|
int i, n_objects;
|
|
|
|
n_objects = data->n_objects;
|
|
for (i = 0; i < n_objects; i++)
|
|
objects[i] = g_object_new (type, NULL);
|
|
}
|
|
|
|
static void
|
|
test_construction_finish (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct ConstructionTest *data = _data;
|
|
int i;
|
|
|
|
for (i = 0; i < data->n_objects; i++)
|
|
g_object_unref (data->objects[i]);
|
|
}
|
|
|
|
static void
|
|
test_construction_teardown (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct ConstructionTest *data = _data;
|
|
g_free (data->objects);
|
|
g_free (data);
|
|
}
|
|
|
|
static void
|
|
test_construction_print_result (PerformanceTest *test,
|
|
gpointer _data,
|
|
double time)
|
|
{
|
|
struct ConstructionTest *data = _data;
|
|
|
|
g_print ("Number of constructed objects per second: %.0f\n",
|
|
data->n_objects / time);
|
|
}
|
|
|
|
/*************************************************************
|
|
* Test property accessors using GParamSpec
|
|
*************************************************************/
|
|
|
|
#define NUM_ACCESSES_PER_ROUND 10000
|
|
|
|
struct PropertyTest {
|
|
gpointer object;
|
|
int n_accesses;
|
|
};
|
|
|
|
static gpointer
|
|
test_property_setup (PerformanceTest *test)
|
|
{
|
|
struct PropertyTest *data;
|
|
GType gtype;
|
|
|
|
gtype = ((GType (*)())test->extra_data)();
|
|
|
|
data = g_new0 (struct PropertyTest, 1);
|
|
data->object = g_object_new (gtype, NULL);
|
|
|
|
return data;
|
|
}
|
|
|
|
static void
|
|
test_property_init (PerformanceTest *test,
|
|
gpointer _data,
|
|
double factor)
|
|
{
|
|
struct PropertyTest *data = _data;
|
|
|
|
data->n_accesses = factor * NUM_ACCESSES_PER_ROUND;
|
|
}
|
|
|
|
static void
|
|
test_paramspec_direct_set_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct PropertyTest *data = _data;
|
|
int n_accesses, i;
|
|
|
|
n_accesses = data->n_accesses;
|
|
for (i = 0; i < n_accesses; i++)
|
|
{
|
|
gint foo = i % 16;
|
|
gfloat baz = foo * 3.14f;
|
|
|
|
paramspec_object_set_foo (data->object, foo);
|
|
paramspec_object_set_baz (data->object, baz);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_paramspec_direct_get_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct PropertyTest *data = _data;
|
|
int n_accesses, i;
|
|
|
|
n_accesses = data->n_accesses;
|
|
for (i = 0; i < n_accesses; i++)
|
|
{
|
|
gint foo;
|
|
gfloat baz;
|
|
|
|
foo = paramspec_object_get_foo (data->object);
|
|
baz = paramspec_object_get_baz (data->object);
|
|
|
|
g_assert_cmpfloat (baz, ==, 0);
|
|
g_assert_cmpint (foo, ==, 50);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
test_paramspec_object_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct PropertyTest *data = _data;
|
|
int n_accesses, i;
|
|
|
|
n_accesses = data->n_accesses;
|
|
for (i = 0; i < n_accesses; i++)
|
|
{
|
|
gint foo = i % 16;
|
|
gfloat baz = foo * 3.14f;
|
|
|
|
g_object_set (data->object,
|
|
"foo", foo,
|
|
"baz", baz,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_property_direct_set_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct PropertyTest *data = _data;
|
|
int n_accesses, i;
|
|
|
|
n_accesses = data->n_accesses;
|
|
for (i = 0; i < n_accesses; i++)
|
|
{
|
|
gint foo = i % 16;
|
|
gfloat baz = foo * 3.14f;
|
|
|
|
property_object_set_foo (data->object, foo);
|
|
property_object_set_baz (data->object, baz);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_property_direct_get_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct PropertyTest *data = _data;
|
|
int n_accesses, i;
|
|
|
|
n_accesses = data->n_accesses;
|
|
for (i = 0; i < n_accesses; i++)
|
|
{
|
|
gint foo;
|
|
gfloat baz;
|
|
|
|
foo = property_object_get_foo (data->object);
|
|
baz = property_object_get_baz (data->object);
|
|
|
|
g_assert_cmpfloat (baz, ==, 0);
|
|
g_assert_cmpint (foo, ==, 50);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_property_object_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct PropertyTest *data = _data;
|
|
int n_accesses, i;
|
|
|
|
n_accesses = data->n_accesses;
|
|
for (i = 0; i < n_accesses; i++)
|
|
{
|
|
gint foo = i % 16;
|
|
gfloat baz = foo * 3.14f;
|
|
|
|
g_object_set (data->object,
|
|
"foo", foo,
|
|
"baz", baz,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_property_finish (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
}
|
|
|
|
static void
|
|
test_property_print_result (PerformanceTest *test,
|
|
gpointer _data,
|
|
gdouble time)
|
|
{
|
|
struct PropertyTest *data = _data;
|
|
g_print ("Number of accesses per second: %.0f\n",
|
|
data->n_accesses / time);
|
|
}
|
|
|
|
static void
|
|
test_property_teardown (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct PropertyTest *data = _data;
|
|
|
|
g_object_unref (data->object);
|
|
g_free (data);
|
|
}
|
|
|
|
/*************************************************************
|
|
* Test runtime type check performance
|
|
*************************************************************/
|
|
|
|
#define NUM_KILO_CHECKS_PER_ROUND 50
|
|
|
|
struct TypeCheckTest {
|
|
GObject *object;
|
|
int n_checks;
|
|
};
|
|
|
|
static gpointer
|
|
test_type_check_setup (PerformanceTest *test)
|
|
{
|
|
struct TypeCheckTest *data;
|
|
|
|
data = g_new0 (struct TypeCheckTest, 1);
|
|
data->object = g_object_new (COMPLEX_TYPE_OBJECT, NULL);
|
|
|
|
return data;
|
|
}
|
|
|
|
static void
|
|
test_type_check_init (PerformanceTest *test,
|
|
gpointer _data,
|
|
double factor)
|
|
{
|
|
struct TypeCheckTest *data = _data;
|
|
|
|
data->n_checks = factor * NUM_KILO_CHECKS_PER_ROUND;
|
|
}
|
|
|
|
|
|
/* Work around g_type_check_instance_is_a being marked "pure",
|
|
and thus only called once for the loop. */
|
|
gboolean (*my_type_check_instance_is_a) (GTypeInstance *type_instance,
|
|
GType iface_type) = &g_type_check_instance_is_a;
|
|
|
|
static void
|
|
test_type_check_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct TypeCheckTest *data = _data;
|
|
volatile GObject *object = data->object;
|
|
volatile GType type, types[5];
|
|
int i, j;
|
|
|
|
types[0] = test_iface1_get_type ();
|
|
types[1] = test_iface2_get_type ();
|
|
types[2] = test_iface3_get_type ();
|
|
types[3] = test_iface4_get_type ();
|
|
types[4] = test_iface5_get_type ();
|
|
|
|
for (i = 0; i < data->n_checks; i++)
|
|
{
|
|
type = types[i%5];
|
|
for (j = 0; j < 1000; j++)
|
|
{
|
|
my_type_check_instance_is_a ((GTypeInstance *)object,
|
|
type);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
test_type_check_finish (PerformanceTest *test,
|
|
gpointer data)
|
|
{
|
|
}
|
|
|
|
static void
|
|
test_type_check_print_result (PerformanceTest *test,
|
|
gpointer _data,
|
|
double time)
|
|
{
|
|
struct TypeCheckTest *data = _data;
|
|
g_print ("Million type checks per second: %.2f\n",
|
|
data->n_checks / (1000*time));
|
|
}
|
|
|
|
static void
|
|
test_type_check_teardown (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct TypeCheckTest *data = _data;
|
|
|
|
g_object_unref (data->object);
|
|
g_free (data);
|
|
}
|
|
|
|
/*************************************************************
|
|
* Test signal unhandled emissions performance
|
|
*************************************************************/
|
|
|
|
#define NUM_EMISSIONS_PER_ROUND 10000
|
|
|
|
struct EmissionTest {
|
|
GObject *object;
|
|
int n_checks;
|
|
int signal_id;
|
|
};
|
|
|
|
static gpointer
|
|
test_emission_unhandled_setup (PerformanceTest *test)
|
|
{
|
|
struct EmissionTest *data;
|
|
|
|
data = g_new0 (struct EmissionTest, 1);
|
|
data->object = g_object_new (COMPLEX_TYPE_OBJECT, NULL);
|
|
data->signal_id = complex_signals[GPOINTER_TO_INT (test->extra_data)];
|
|
return data;
|
|
}
|
|
|
|
static void
|
|
test_emission_unhandled_init (PerformanceTest *test,
|
|
gpointer _data,
|
|
double factor)
|
|
{
|
|
struct EmissionTest *data = _data;
|
|
|
|
data->n_checks = factor * NUM_EMISSIONS_PER_ROUND;
|
|
}
|
|
|
|
static void
|
|
test_emission_unhandled_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct EmissionTest *data = _data;
|
|
GObject *object = data->object;
|
|
int i;
|
|
|
|
for (i = 0; i < data->n_checks; i++)
|
|
g_signal_emit (object,
|
|
data->signal_id,
|
|
0);
|
|
}
|
|
|
|
static void
|
|
test_emission_unhandled_finish (PerformanceTest *test,
|
|
gpointer data)
|
|
{
|
|
}
|
|
|
|
static void
|
|
test_emission_unhandled_print_result (PerformanceTest *test,
|
|
gpointer _data,
|
|
double time)
|
|
{
|
|
struct EmissionTest *data = _data;
|
|
|
|
g_print ("Emissions per second: %.0f\n",
|
|
data->n_checks / time);
|
|
}
|
|
|
|
static void
|
|
test_emission_unhandled_teardown (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct EmissionTest *data = _data;
|
|
|
|
g_object_unref (data->object);
|
|
g_free (data);
|
|
}
|
|
|
|
/*************************************************************
|
|
* Test signal handled emissions performance
|
|
*************************************************************/
|
|
|
|
static void
|
|
test_emission_handled_handler (ComplexObject *obj, gpointer data)
|
|
{
|
|
}
|
|
|
|
static gpointer
|
|
test_emission_handled_setup (PerformanceTest *test)
|
|
{
|
|
struct EmissionTest *data;
|
|
|
|
data = g_new0 (struct EmissionTest, 1);
|
|
data->object = g_object_new (COMPLEX_TYPE_OBJECT, NULL);
|
|
data->signal_id = complex_signals[GPOINTER_TO_INT (test->extra_data)];
|
|
g_signal_connect (data->object, "signal",
|
|
G_CALLBACK (test_emission_handled_handler),
|
|
NULL);
|
|
g_signal_connect (data->object, "signal-empty",
|
|
G_CALLBACK (test_emission_handled_handler),
|
|
NULL);
|
|
g_signal_connect (data->object, "signal-generic",
|
|
G_CALLBACK (test_emission_handled_handler),
|
|
NULL);
|
|
g_signal_connect (data->object, "signal-generic-empty",
|
|
G_CALLBACK (test_emission_handled_handler),
|
|
NULL);
|
|
|
|
return data;
|
|
}
|
|
|
|
static void
|
|
test_emission_handled_init (PerformanceTest *test,
|
|
gpointer _data,
|
|
double factor)
|
|
{
|
|
struct EmissionTest *data = _data;
|
|
|
|
data->n_checks = factor * NUM_EMISSIONS_PER_ROUND;
|
|
}
|
|
|
|
static void
|
|
test_emission_handled_run (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct EmissionTest *data = _data;
|
|
GObject *object = data->object;
|
|
int i;
|
|
|
|
for (i = 0; i < data->n_checks; i++)
|
|
g_signal_emit (object,
|
|
data->signal_id,
|
|
0);
|
|
}
|
|
|
|
static void
|
|
test_emission_handled_finish (PerformanceTest *test,
|
|
gpointer data)
|
|
{
|
|
}
|
|
|
|
static void
|
|
test_emission_handled_print_result (PerformanceTest *test,
|
|
gpointer _data,
|
|
double time)
|
|
{
|
|
struct EmissionTest *data = _data;
|
|
|
|
g_print ("Emissions per second: %.0f\n",
|
|
data->n_checks / time);
|
|
}
|
|
|
|
static void
|
|
test_emission_handled_teardown (PerformanceTest *test,
|
|
gpointer _data)
|
|
{
|
|
struct EmissionTest *data = _data;
|
|
|
|
g_object_unref (data->object);
|
|
g_free (data);
|
|
}
|
|
|
|
/*************************************************************
|
|
* Main test code
|
|
*************************************************************/
|
|
|
|
static PerformanceTest tests[] = {
|
|
{
|
|
"simple-construction",
|
|
simple_object_get_type,
|
|
test_construction_setup,
|
|
test_construction_init,
|
|
test_construction_run,
|
|
test_construction_finish,
|
|
test_construction_teardown,
|
|
test_construction_print_result
|
|
},
|
|
{
|
|
"complex-construction",
|
|
complex_object_get_type,
|
|
test_construction_setup,
|
|
test_construction_init,
|
|
test_construction_run,
|
|
test_construction_finish,
|
|
test_construction_teardown,
|
|
test_construction_print_result
|
|
},
|
|
{
|
|
"gparamspec-direct-get",
|
|
paramspec_object_get_type,
|
|
test_property_setup,
|
|
test_property_init,
|
|
test_paramspec_direct_get_run,
|
|
test_property_finish,
|
|
test_property_teardown,
|
|
test_property_print_result
|
|
},
|
|
{
|
|
"gproperty-direct-get",
|
|
property_object_get_type,
|
|
test_property_setup,
|
|
test_property_init,
|
|
test_property_direct_get_run,
|
|
test_property_finish,
|
|
test_property_teardown,
|
|
test_property_print_result
|
|
},
|
|
{
|
|
"gparamspec-direct-set",
|
|
paramspec_object_get_type,
|
|
test_property_setup,
|
|
test_property_init,
|
|
test_paramspec_direct_set_run,
|
|
test_property_finish,
|
|
test_property_teardown,
|
|
test_property_print_result
|
|
},
|
|
{
|
|
"gproperty-direct-set",
|
|
property_object_get_type,
|
|
test_property_setup,
|
|
test_property_init,
|
|
test_property_direct_set_run,
|
|
test_property_finish,
|
|
test_property_teardown,
|
|
test_property_print_result
|
|
},
|
|
{
|
|
"gparamspec-gobject-access",
|
|
paramspec_object_get_type,
|
|
test_property_setup,
|
|
test_property_init,
|
|
test_paramspec_object_run,
|
|
test_property_finish,
|
|
test_property_teardown,
|
|
test_property_print_result
|
|
},
|
|
{
|
|
"gproperty-gobject-access",
|
|
property_object_get_type,
|
|
test_property_setup,
|
|
test_property_init,
|
|
test_property_object_run,
|
|
test_property_finish,
|
|
test_property_teardown,
|
|
test_property_print_result
|
|
},
|
|
{
|
|
"type-check",
|
|
NULL,
|
|
test_type_check_setup,
|
|
test_type_check_init,
|
|
test_type_check_run,
|
|
test_type_check_finish,
|
|
test_type_check_teardown,
|
|
test_type_check_print_result
|
|
},
|
|
{
|
|
"emit-unhandled",
|
|
GINT_TO_POINTER (COMPLEX_SIGNAL),
|
|
test_emission_unhandled_setup,
|
|
test_emission_unhandled_init,
|
|
test_emission_unhandled_run,
|
|
test_emission_unhandled_finish,
|
|
test_emission_unhandled_teardown,
|
|
test_emission_unhandled_print_result
|
|
},
|
|
{
|
|
"emit-unhandled-empty",
|
|
GINT_TO_POINTER (COMPLEX_SIGNAL_EMPTY),
|
|
test_emission_unhandled_setup,
|
|
test_emission_unhandled_init,
|
|
test_emission_unhandled_run,
|
|
test_emission_unhandled_finish,
|
|
test_emission_unhandled_teardown,
|
|
test_emission_unhandled_print_result
|
|
},
|
|
{
|
|
"emit-unhandled-generic",
|
|
GINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC),
|
|
test_emission_unhandled_setup,
|
|
test_emission_unhandled_init,
|
|
test_emission_unhandled_run,
|
|
test_emission_unhandled_finish,
|
|
test_emission_unhandled_teardown,
|
|
test_emission_unhandled_print_result
|
|
},
|
|
{
|
|
"emit-unhandled-generic-empty",
|
|
GINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC_EMPTY),
|
|
test_emission_unhandled_setup,
|
|
test_emission_unhandled_init,
|
|
test_emission_unhandled_run,
|
|
test_emission_unhandled_finish,
|
|
test_emission_unhandled_teardown,
|
|
test_emission_unhandled_print_result
|
|
},
|
|
{
|
|
"emit-handled",
|
|
GINT_TO_POINTER (COMPLEX_SIGNAL),
|
|
test_emission_handled_setup,
|
|
test_emission_handled_init,
|
|
test_emission_handled_run,
|
|
test_emission_handled_finish,
|
|
test_emission_handled_teardown,
|
|
test_emission_handled_print_result
|
|
},
|
|
{
|
|
"emit-handled-empty",
|
|
GINT_TO_POINTER (COMPLEX_SIGNAL_EMPTY),
|
|
test_emission_handled_setup,
|
|
test_emission_handled_init,
|
|
test_emission_handled_run,
|
|
test_emission_handled_finish,
|
|
test_emission_handled_teardown,
|
|
test_emission_handled_print_result
|
|
},
|
|
{
|
|
"emit-handled-generic",
|
|
GINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC),
|
|
test_emission_handled_setup,
|
|
test_emission_handled_init,
|
|
test_emission_handled_run,
|
|
test_emission_handled_finish,
|
|
test_emission_handled_teardown,
|
|
test_emission_handled_print_result
|
|
},
|
|
{
|
|
"emit-handled-generic-empty",
|
|
GINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC_EMPTY),
|
|
test_emission_handled_setup,
|
|
test_emission_handled_init,
|
|
test_emission_handled_run,
|
|
test_emission_handled_finish,
|
|
test_emission_handled_teardown,
|
|
test_emission_handled_print_result
|
|
}
|
|
};
|
|
|
|
static PerformanceTest *
|
|
find_test (const char *name)
|
|
{
|
|
int i;
|
|
for (i = 0; i < G_N_ELEMENTS (tests); i++)
|
|
{
|
|
if (strcmp (tests[i].name, name) == 0)
|
|
return &tests[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
int
|
|
main (int argc,
|
|
char *argv[])
|
|
{
|
|
PerformanceTest *test;
|
|
GOptionContext *context;
|
|
GError *error = NULL;
|
|
int i;
|
|
|
|
context = g_option_context_new ("GObject performance tests");
|
|
g_option_context_add_main_entries (context, cmd_entries, NULL);
|
|
if (!g_option_context_parse (context, &argc, &argv, &error))
|
|
{
|
|
g_printerr ("%s: %s\n", argv[0], error->message);
|
|
return 1;
|
|
}
|
|
|
|
if (argc > 1)
|
|
{
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
test = find_test (argv[i]);
|
|
if (test)
|
|
run_test (test);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < G_N_ELEMENTS (tests); i++)
|
|
run_test (&tests[i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|