mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-24 18:08:54 +02:00
Make refcounting threadsafe by using atomic operations. (#166020, Wim
2005-07-15 Matthias Clasen <mclasen@redhat.com> Make refcounting threadsafe by using atomic operations. (#166020, Wim Taymans) * gobject.c: Use a recursive lock to protect the notify queue. (g_object_unref): Get rid of g_object_last_unref and do the last unref handling in g_object_unref. (g_object_ref, g_object_unref): Use atomic operations. * gsignal.c (struct _HandlerMatch): Use a full integer for the ref_count field. (handler_ref, handler_unref_R): Use atomic operations. * gparam.c (g_param_spec_ref, g_param_spec_unref): Use atomic operations instead of a lock to make the refcounting threadsafe. * gclosure.c (g_closure_ref, g_closure_unref): Use atomic operations. This is more complicated here, since the refcount is stored in a bitfield, so we also have to access all other bitfield members atomically. * gsignal.c (handlers_find): Read the meta_marshal flag of the closure atomically. * tests/Makefile.am (SUBDIRS): Add tests/refcount * configure.in: Add tests/refcount * tests/refcount/properties.c: Test property changes from multiple threads. * tests/refcount/signals.c: Test signal emission from multiple threads. * tests/refcount/objects.c: Test refcounting from multiple threads. * tests/refcount/objects2.c: * tests/refcount/properties2.c: Tests to measure the overhead of threadsafe refcounting. * glib/giochannel.c (g_io_channel_ref, g_io_channel_unref): Use atomic operations to make refcounting threadsafe. (#166020, Wim Taymans)
This commit is contained in:
committed by
Matthias Clasen
parent
58729b464b
commit
39ea11ce6b
@@ -64,7 +64,6 @@ static gchar* value_param_lcopy_value (const GValue *value,
|
||||
|
||||
/* --- variables --- */
|
||||
static GQuark quark_floating = 0;
|
||||
G_LOCK_DEFINE_STATIC (pspec_ref_count);
|
||||
|
||||
|
||||
/* --- functions --- */
|
||||
@@ -169,43 +168,26 @@ GParamSpec*
|
||||
g_param_spec_ref (GParamSpec *pspec)
|
||||
{
|
||||
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
|
||||
g_return_val_if_fail (pspec->ref_count > 0, NULL);
|
||||
|
||||
g_atomic_int_inc (&pspec->ref_count);
|
||||
|
||||
G_LOCK (pspec_ref_count);
|
||||
if (pspec->ref_count > 0)
|
||||
{
|
||||
pspec->ref_count += 1;
|
||||
G_UNLOCK (pspec_ref_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
G_UNLOCK (pspec_ref_count);
|
||||
g_return_val_if_fail (pspec->ref_count > 0, NULL);
|
||||
}
|
||||
|
||||
return pspec;
|
||||
}
|
||||
|
||||
void
|
||||
g_param_spec_unref (GParamSpec *pspec)
|
||||
{
|
||||
gboolean is_zero;
|
||||
|
||||
g_return_if_fail (G_IS_PARAM_SPEC (pspec));
|
||||
g_return_if_fail (pspec->ref_count > 0);
|
||||
|
||||
G_LOCK (pspec_ref_count);
|
||||
if (pspec->ref_count > 0)
|
||||
{
|
||||
gboolean need_finalize;
|
||||
is_zero = g_atomic_int_dec_and_test (&pspec->ref_count);
|
||||
|
||||
/* sync with _sink */
|
||||
pspec->ref_count -= 1;
|
||||
need_finalize = pspec->ref_count == 0;
|
||||
G_UNLOCK (pspec_ref_count);
|
||||
if (need_finalize)
|
||||
G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
|
||||
}
|
||||
else
|
||||
if (G_UNLIKELY (is_zero))
|
||||
{
|
||||
G_UNLOCK (pspec_ref_count);
|
||||
g_return_if_fail (pspec->ref_count > 0);
|
||||
G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,29 +195,11 @@ void
|
||||
g_param_spec_sink (GParamSpec *pspec)
|
||||
{
|
||||
g_return_if_fail (G_IS_PARAM_SPEC (pspec));
|
||||
g_return_if_fail (pspec->ref_count > 0);
|
||||
|
||||
G_LOCK (pspec_ref_count);
|
||||
if (pspec->ref_count > 0)
|
||||
if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
|
||||
{
|
||||
if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
|
||||
{
|
||||
/* sync with _unref */
|
||||
if (pspec->ref_count > 1)
|
||||
pspec->ref_count -= 1;
|
||||
else
|
||||
{
|
||||
G_UNLOCK (pspec_ref_count);
|
||||
g_param_spec_unref (pspec);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
G_UNLOCK (pspec_ref_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
G_UNLOCK (pspec_ref_count);
|
||||
g_return_if_fail (pspec->ref_count > 0);
|
||||
g_param_spec_unref (pspec);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user