summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shared/nm-glib-aux/nm-ref-string.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/shared/nm-glib-aux/nm-ref-string.c b/shared/nm-glib-aux/nm-ref-string.c
index 0a0b0d3a41..ece69b7473 100644
--- a/shared/nm-glib-aux/nm-ref-string.c
+++ b/shared/nm-glib-aux/nm-ref-string.c
@@ -169,24 +169,25 @@ void
_nm_ref_string_unref_non_null (NMRefString *rstr)
{
RefString *const rstr0 = (RefString *) rstr;
+ int r;
_ASSERT (rstr0);
- if (G_LIKELY (!g_atomic_int_dec_and_test (&rstr0->ref_count)))
+ /* fast-path: first try to decrement the ref-count without bringing it
+ * to zero. */
+ r = rstr0->ref_count;
+ if (G_LIKELY (r > 1 && g_atomic_int_compare_and_exchange (&rstr0->ref_count, r, r - 1)))
return;
+ /* We apparently are about to return the last reference. Take a lock. */
+
G_LOCK (gl_lock);
- /* in the fast-path above, we already decremented the ref-count to zero.
- * We need recheck that the ref-count is still zero. */
+ nm_assert (g_hash_table_lookup (gl_hash, rstr0) == rstr0);
- if (g_atomic_int_get (&rstr0->ref_count) == 0) {
+ if (G_LIKELY(g_atomic_int_dec_and_test (&rstr0->ref_count))) {
if (!g_hash_table_remove (gl_hash, rstr0))
nm_assert_not_reached ();
- } else {
-#if NM_MORE_ASSERTS > 5
- nm_assert (g_hash_table_lookup (gl_hash, rstr0) == rstr0);
-#endif
}
G_UNLOCK (gl_lock);