While
if (isc_refcount_decrement() == 1) { // memory_order_release
isc_refcount_destroy(); // memory_order_acquire
...
}
is theoretically the most efficent in practice, using
memory_order_acq_rel produces the same code on x86_64 and doesn't
trigger tsan data races (which use a idealistic model) if
isc_refcount_destroy() is not called immediately. In fact
isc_refcount_destroy() could be removed if we didn't want
to check for the count being 0 when isc_refcount_destroy() is
called.
https://stackoverflow.com/questions/
49112732/memory-order-in-shared-pointer-destructor
(cherry picked from commit
6278899a3849b7ee46b6460dff93e555e77d99a2)
atomic_fetch_or_explicit((o), (v), memory_order_release)
#define atomic_exchange_acq_rel(o, v) \
atomic_exchange_explicit((o), (v), memory_order_acq_rel)
+#define atomic_fetch_sub_acq_rel(o, v) \
+ atomic_fetch_sub_explicit((o), (v), memory_order_acq_rel)
#define atomic_compare_exchange_weak_acq_rel(o, e, d) \
atomic_compare_exchange_weak_explicit( \
(o), (e), (d), memory_order_acq_rel, memory_order_acquire)
static inline uint_fast32_t
isc_refcount_decrement(isc_refcount_t *target) {
uint_fast32_t __v;
- __v = (uint_fast32_t)atomic_fetch_sub_release(target, 1);
+ __v = (uint_fast32_t)atomic_fetch_sub_acq_rel(target, 1);
INSIST(__v > 0);
return (__v);
}
({ \
/* cppcheck-suppress shadowVariable */ \
uint_fast32_t __v; \
- __v = atomic_fetch_sub_release(target, 1); \
+ __v = atomic_fetch_sub_acq_rel(target, 1); \
INSIST(__v > 0); \
__v; \
})