gobject: rework g_object_add_toggle_ref() to use g_datalist_id_update_atomic()

This commit is contained in:
Thomas Haller 2024-01-30 12:48:19 +01:00
parent 50b5ea1781
commit d37a899d68

View File

@ -4091,12 +4091,22 @@ g_object_force_floating (GObject *object)
floating_flag_handler (object, +1);
}
typedef struct {
typedef struct
{
GToggleNotify notify;
gpointer data;
} ToggleRefTuple;
typedef struct
{
GObject *object;
ToggleRefTuple tuple;
} ToggleRefCallbackData;
typedef struct
{
guint n_toggle_refs;
struct {
GToggleNotify notify;
gpointer data;
} toggle_refs[1]; /* flexible array */
ToggleRefTuple toggle_refs[1]; /* flexible array */
} ToggleRefStack;
static gpointer
@ -4202,6 +4212,38 @@ toggle_refs_check_and_ref_or_deref (GObject *object,
return TRUE;
}
static gpointer
toggle_refs_ref_cb (gpointer *data,
GDestroyNotify *destroy_notify,
gpointer user_data)
{
ToggleRefCallbackData *trdata = user_data;
ToggleRefStack *tstack = *data;
guint i;
if (!tstack)
{
tstack = g_new (ToggleRefStack, 1);
tstack->n_toggle_refs = 1;
i = 0;
g_datalist_set_flags (&trdata->object->qdata, OBJECT_HAS_TOGGLE_REF_FLAG);
*destroy_notify = g_free;
}
else
{
i = tstack->n_toggle_refs++;
tstack = g_realloc (tstack, sizeof (*tstack) + sizeof (tstack->toggle_refs[0]) * i);
}
*data = tstack;
tstack->toggle_refs[i] = trdata->tuple;
return NULL;
}
/**
* g_object_add_toggle_ref: (skip)
* @object: a #GObject
@ -4249,13 +4291,10 @@ toggle_refs_check_and_ref_or_deref (GObject *object,
* Since: 2.8
*/
void
g_object_add_toggle_ref (GObject *object,
GToggleNotify notify,
gpointer data)
g_object_add_toggle_ref (GObject *object,
GToggleNotify notify,
gpointer data)
{
ToggleRefStack *tstack;
guint i;
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (notify != NULL);
g_return_if_fail (g_atomic_int_get (&object->ref_count) >= 1);
@ -4263,29 +4302,16 @@ g_object_add_toggle_ref (GObject *object,
g_object_ref (object);
object_bit_lock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
tstack = g_datalist_id_remove_no_notify (&object->qdata, quark_toggle_refs);
if (tstack)
{
i = tstack->n_toggle_refs++;
/* allocate i = tstate->n_toggle_refs - 1 positions beyond the 1 declared
* in tstate->toggle_refs */
tstack = g_realloc (tstack, sizeof (*tstack) + sizeof (tstack->toggle_refs[0]) * i);
}
else
{
tstack = g_renew (ToggleRefStack, NULL, 1);
tstack->n_toggle_refs = 1;
i = 0;
}
/* Set a flag for fast lookup after adding the first toggle reference */
if (tstack->n_toggle_refs == 1)
g_datalist_set_flags (&object->qdata, OBJECT_HAS_TOGGLE_REF_FLAG);
_g_datalist_id_update_atomic (&object->qdata,
quark_toggle_refs,
toggle_refs_ref_cb,
&((ToggleRefCallbackData){
.object = object,
.tuple.notify = notify,
.tuple.data = data,
}));
tstack->toggle_refs[i].notify = notify;
tstack->toggle_refs[i].data = data;
g_datalist_id_set_data_full (&object->qdata, quark_toggle_refs, tstack,
(GDestroyNotify)g_free);
object_bit_unlock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
}