gbitlock: add g_pointer_bit_lock_and_get()

Usually, after g_pointer_bit_lock() we want to read the pointer that we
have. In many cases, when we g_pointer_bit_lock() a pointer, we can
access it afterwards without atomic, as nobody is going to modify the
pointer then.

However, gdataset also supports g_datalist_set_flags(), so the pointer
may change at any time and we must always use atomics to read it. For
that reason, g_datalist_lock_and_get() does an atomic read right after
g_pointer_bit_lock().

g_pointer_bit_lock() can easily access the value that it just set. Add
g_pointer_bit_lock_and_get() which can return the value that gets set
afterwards.

Aside from saving the second atomic-get in certain scenarios, the
returned value is also atomically the one that we just set.
This commit is contained in:
Thomas Haller
2024-01-05 14:05:58 +01:00
parent abe4b4e7d8
commit 5609370de9
4 changed files with 90 additions and 55 deletions

View File

@@ -515,6 +515,7 @@ test_threaded_g_pointer_bit_unlock_and_set (void)
GObject *obj;
gpointer plock;
gpointer ptr;
guintptr ptr2;
gpointer mangled_obj;
#if defined(__GNUC__)
@@ -548,14 +549,15 @@ test_threaded_g_pointer_bit_unlock_and_set (void)
g_assert_true (plock == obj);
plock = obj;
g_pointer_bit_lock (&plock, 0);
g_pointer_bit_lock_and_get (&plock, 0, &ptr2);
g_assert_true ((gpointer) ptr2 == plock);
g_assert_true (plock != obj);
g_atomic_pointer_set (&plock, mangled_obj);
g_pointer_bit_unlock_and_set (&plock, 0, obj, 0);
g_assert_true (plock == obj);
plock = obj;
g_pointer_bit_lock (&plock, 0);
g_pointer_bit_lock_and_get (&plock, 0, NULL);
g_assert_true (plock != obj);
g_atomic_pointer_set (&plock, mangled_obj);
g_pointer_bit_unlock_and_set (&plock, 0, obj, 0x7);