mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-26 22:16:16 +01:00
092be080c5
_object_unref_clear_weak_locations() is called twice during g_object_unref(). In both cases, it is when we expect that the reference count is 1 and we are either about to call dispose() or finalize(). At this point, we must check for GWeakRef to avoid a race that the ref count gets increased just at that point. However, we can do something better than to always take the global lock. On the object, whenever an object is set to a GWeakRef, set a flag OPTIONAL_FLAG_EVER_HAD_WEAK_REF. Most objects are not involved with weak references and won't have this flag set. If we reach _object_unref_clear_weak_locations() we just (atomically) checked that the ref count is one. If the object at this point never had a GWeakRef registered, we know that nobody else could have raced against obtaining another reference. In this case, we can skip taking the lock and checking for weak locations. As most object don't ever have a GWeakRef registered, this significantly avoids unnecessary work during _object_unref_clear_weak_locations(). This even fixes a hard to hit race in the do_unref=FALSE case. Previously, if do_unref=FALSE there were code paths where we avoided taking the global lock. We do so, when quark_weak_locations is unset. However, that is not race free. If we enter _object_unref_clear_weak_locations() with a ref-count of 1 and one GWeakRef registered, another thread can take a strong reference and unset the GWeakRef. Then quark_weak_locations will be unset, and _object_unref_clear_weak_locations() misses the fact that the ref count is now bumped to two. That is now fixed, because once OPTIONAL_FLAG_EVER_HAD_WEAK_REF is set, it will stick. Previously, there was an optimization to first take a read lock to check whether there are weak locations to clear. It's not clear that this is worth it, because we now already have a hint that there might be a weak location. Unfortunately, GRWLock does not support an upgradable lock, so we cannot take an (upgradable) read lock, and when necessary upgrade that to a write lock. |
||
---|---|---|
.. | ||
tests | ||
gatomicarray.c | ||
gatomicarray.h | ||
gbinding.c | ||
gbinding.h | ||
gbindinggroup.c | ||
gbindinggroup.h | ||
gboxed.c | ||
gboxed.h | ||
gclosure.c | ||
gclosure.h | ||
genums.c | ||
genums.h | ||
glib-enumtypes.c.template | ||
glib-enumtypes.h.template | ||
glib-genmarshal.in | ||
glib-mkenums.in | ||
glib-types.h | ||
gmarshal.c | ||
gmarshal.h | ||
gobject_gdb.py | ||
gobject_probes.d | ||
gobject_trace.h | ||
gobject-autocleanups.h | ||
gobject-query.c | ||
gobject.c | ||
gobject.h | ||
gobject.rc.in | ||
gobject.stp.in | ||
gobjectnotifyqueue.c | ||
gparam.c | ||
gparam.h | ||
gparamspecs.c | ||
gparamspecs.h | ||
gsignal.c | ||
gsignal.h | ||
gsignalgroup.c | ||
gsignalgroup.h | ||
gsourceclosure.c | ||
gsourceclosure.h | ||
gtype-private.h | ||
gtype.c | ||
gtype.h | ||
gtypemodule.c | ||
gtypemodule.h | ||
gtypeplugin.c | ||
gtypeplugin.h | ||
gvalue.c | ||
gvalue.h | ||
gvaluearray.c | ||
gvaluearray.h | ||
gvaluecollector.h | ||
gvaluetransform.c | ||
gvaluetypes.c | ||
gvaluetypes.h | ||
libgobject-gdb.py.in | ||
meson.build |