[glib/gobject-speedups: 12/13] Avoid allocating GObjectNotifyQueue
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/gobject-speedups: 12/13] Avoid allocating GObjectNotifyQueue
- Date: Mon, 16 May 2022 03:51:51 +0000 (UTC)
commit 0732f8ff6a02c9b6bf64274a5cad76692e962bb6
Author: Matthias Clasen <mclasen redhat com>
Date: Sun May 15 22:12:10 2022 -0400
Avoid allocating GObjectNotifyQueue
gobject/gobject.c | 31 ++++++++++++++-----------
gobject/gobject.h | 19 ++++++++++++++-
tests/gobject/performance.c | 56 ++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 89 insertions(+), 17 deletions(-)
---
diff --git a/gobject/gobject.c b/gobject/gobject.c
index d272f85875..1f43b28422 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -239,16 +239,6 @@ static void object_interface_check_properties (gpointer check_d
gpointer g_iface);
static void weak_locations_free_unlocked (GSList **weak_locations);
-/* --- typedefs --- */
-typedef struct _GObjectNotifyQueue GObjectNotifyQueue;
-
-struct _GObjectNotifyQueue
-{
- GSList *pspecs;
- guint16 n_pspecs;
- guint16 freeze_count;
-};
-
/* --- variables --- */
G_LOCK_DEFINE_STATIC (closure_array_mutex);
G_LOCK_DEFINE_STATIC (weak_refs_mutex);
@@ -280,6 +270,13 @@ g_object_notify_queue_free (gpointer data)
static GObjectNotifyQueue*
g_object_notify_queue_freeze (GObject *object,
gboolean conditional)
+{
+ return G_OBJECT_GET_CLASS (object)->freeze_notify (object, conditional);
+}
+
+static GObjectNotifyQueue*
+g_object_default_freeze_notify (GObject *object,
+ gboolean conditional)
{
GObjectNotifyQueue *nqueue;
@@ -314,6 +311,13 @@ g_object_notify_queue_freeze (GObject *object,
static void
g_object_notify_queue_thaw (GObject *object,
GObjectNotifyQueue *nqueue)
+{
+ G_OBJECT_GET_CLASS (object)->thaw_notify (object, nqueue);
+}
+
+static void
+g_object_default_thaw_notify (GObject *object,
+ GObjectNotifyQueue *nqueue)
{
GParamSpec *pspecs_mem[16], **pspecs, **free_me = NULL;
GSList *slist;
@@ -528,6 +532,8 @@ g_object_do_class_init (GObjectClass *class)
class->finalize = g_object_finalize;
class->dispatch_properties_changed = g_object_dispatch_properties_changed;
class->notify = NULL;
+ class->freeze_notify = g_object_default_freeze_notify;
+ class->thaw_notify = g_object_default_thaw_notify;
/**
* GObject::notify:
@@ -2074,9 +2080,8 @@ g_object_new_internal (GObjectClass *class,
if (CLASS_HAS_NOTIFY (class))
{
- /* This will have been setup in g_object_init() */
- nqueue = g_datalist_id_get_data (&object->qdata, quark_notify_queue);
- g_assert (nqueue != NULL);
+ nqueue = g_object_notify_queue_freeze (object, FALSE);
+ g_object_notify_queue_thaw (object, nqueue);
}
/* We will set exactly n_construct_properties construct
diff --git a/gobject/gobject.h b/gobject/gobject.h
index c67794ae50..60c55cd1d2 100644
--- a/gobject/gobject.h
+++ b/gobject/gobject.h
@@ -246,6 +246,16 @@ typedef void (*GObjectFinalizeFunc) (GObject *object);
*/
typedef void (*GWeakNotify) (gpointer data,
GObject *where_the_object_was);
+
+typedef struct _GObjectNotifyQueue GObjectNotifyQueue;
+
+struct _GObjectNotifyQueue
+{
+ GSList *pspecs;
+ guint16 n_pspecs;
+ guint16 freeze_count;
+};
+
/**
* GObject:
*
@@ -366,12 +376,19 @@ struct _GObjectClass
/* called when done constructing */
void (*constructed) (GObject *object);
+ GObjectNotifyQueue *
+ (*freeze_notify) (GObject *object,
+ gboolean conditional);
+
+ void (*thaw_notify) (GObject *object,
+ GObjectNotifyQueue *nqueue);
+
/*< private >*/
gsize flags;
gsize n_construct_properties;
/* padding */
- gpointer pdummy[5];
+ gpointer pdummy[3];
};
/**
diff --git a/tests/gobject/performance.c b/tests/gobject/performance.c
index f77c93b5d0..c80720a5d6 100644
--- a/tests/gobject/performance.c
+++ b/tests/gobject/performance.c
@@ -253,6 +253,7 @@ typedef struct _ComplexObjectClass ComplexObjectClass;
struct _ComplexObject
{
GObject parent_instance;
+ GObjectNotifyQueue nqueue;
int val1;
char *val2;
};
@@ -298,7 +299,7 @@ static guint complex_signals[COMPLEX_LAST_SIGNAL] = { 0 };
static void
complex_object_finalize (GObject *object)
{
- ComplexObject *c = COMPLEX_OBJECT (object);
+ ComplexObject *c = (ComplexObject *) object;
g_free (c->val2);
@@ -311,7 +312,7 @@ complex_object_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
- ComplexObject *complex = COMPLEX_OBJECT (object);
+ ComplexObject *complex = (ComplexObject *)object;
switch (prop_id)
{
@@ -334,7 +335,7 @@ complex_object_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
- ComplexObject *complex = COMPLEX_OBJECT (object);
+ ComplexObject *complex = (ComplexObject *)object;
switch (prop_id)
{
@@ -355,6 +356,53 @@ complex_object_real_signal (ComplexObject *obj)
{
}
+static GObjectNotifyQueue *
+complex_object_freeze_notify (GObject *object,
+ gboolean conditional)
+{
+ ComplexObject *complex = (ComplexObject *)object;
+
+ if (conditional && complex->nqueue.freeze_count == 0)
+ return NULL;
+
+ complex->nqueue.freeze_count++;
+
+ return &complex->nqueue;
+}
+
+static void
+complex_object_thaw_notify (GObject *object,
+ GObjectNotifyQueue *nqueue)
+{
+ int n_pspecs;
+ GParamSpec **pspecs;
+
+ /* Just make sure we never get into some nasty race condition */
+ if (G_UNLIKELY (nqueue->freeze_count == 0))
+ {
+ g_warning ("%s: property-changed notification for %s(%p) is not frozen",
+ G_STRFUNC, G_OBJECT_TYPE_NAME (object), object);
+ return;
+ }
+
+ nqueue->freeze_count--;
+ if (nqueue->freeze_count)
+ return;
+
+ n_pspecs = 0;
+ pspecs = g_newa (GParamSpec *, nqueue->n_pspecs);
+
+ for (GSList *l = nqueue->pspecs; l; l = l->next)
+ pspecs[n_pspecs++] = l->data;
+
+ g_slist_free (nqueue->pspecs);
+ nqueue->pspecs = NULL;
+ nqueue->n_pspecs = 0;
+
+ if (n_pspecs)
+ G_OBJECT_GET_CLASS (object)->dispatch_properties_changed (object, n_pspecs, pspecs);
+}
+
static void
complex_object_class_init (ComplexObjectClass *class)
{
@@ -363,6 +411,8 @@ complex_object_class_init (ComplexObjectClass *class)
object_class->finalize = complex_object_finalize;
object_class->set_property = complex_object_set_property;
object_class->get_property = complex_object_get_property;
+ object_class->freeze_notify = complex_object_freeze_notify;
+ object_class->thaw_notify = complex_object_thaw_notify;
class->signal = complex_object_real_signal;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]