c++ - __sync_val_compare_and_swap vs __sync_bool_compare_and_swap -


i've been thinking return values of these 2 functions. __sync_bool_compare_and_swap function's return value seems have obvious benefits, i.e. can use tell whether swap operation took place. can't see use of __sync_val_compare_and_swap's return value.

firstly, lets have function signature reference (from gcc docs minus var args):

type __sync_val_compare_and_swap (type *ptr, type oldval type newval); 

the problem see return value of __sync_val_compare_and_swap old value of *ptr. precise, it's value seen implementation of function once appropriate memory barriers had been put in place. explicitly state cater fact between calling __sync_val_compare_and_swap , executing instructions enforce memory barrier value of *ptr change.

now, when function returns can return value? there's no point trying compare *ptr because *ptr can changed on other threads. likewise comparing newval , *ptr doesn't me either (unless lock *ptr undermines use of atomics in first place).

so that's left me ask whether return value == oldval, (see below caveat) asking whether swap operation took place. have used __sync_bool_compare_and_swap.

the caveat mentioned subtle difference can see here doing doesn't tell me whether swap occured or not, tells me @ point before memory barrier released *ptr had same value newval. i'm considering possibility oldval == newval (although i'd struggle see way of implementing function efficiently check these values first , not swap if same it's moot point). can't see situation knowing difference make difference me @ call site. in fact, can't imagine situation set oldval , newval equal.

my question thus:

is there use case in using __sync_val_compare_and_swap , __sync_bool_compare_and_swap not equivalent, i.e. there situation 1 provides more information other?

aside

the reason thinking found implementation of __sync_val_compare_and_swap in terms of sync_bool_compare_and_swap has race:

inline int32_t __sync_val_compare_and_swap(volatile int32_t* ptr, int32_t oldval, int32_t newval) {     int32_t ret = *ptr;     (void)__sync_bool_compare_and_swap(ptr, oldval, newval);     return ret; } 

the race being on storing of *ptr in ret, *ptr change before __sync_bool_compare_and_swap called. made me realise there doesn't seem safe way (without barriers or locks) of implementing __sync_val_compare_and_swap in terms of sync_bool_compare_and_swap. got me thinking former must provide more "information" latter, per question don't see does.

the operation provided __sync_val_compare_and_swap can implemented in terms of __sync_bool_compare_and_swap (and of course other direction possible), in terms of power 2 equivalent. implementing __sync_val_compare_and_swap in terms of __sync_bool_compare_and_swap not efficient. looks like:

for (;;) {     bool success = __sync_bool_compare_and_swap(ptr, oldval, newval);     if (success) return oldval;     type tmp = *ptr;     __sync_synchronize();     if (tmp != oldval) return tmp; } 

the work needed because observe failure of __sync_bool_compare_and_swap read new value *ptr happens match oldval.

as why might prefer __sync_val_compare_and_swap behavior, value caused failure may give starting point retry operation more efficiently or might indicate meaningful cause of failure operation won't "retried". example, see code pthread_spin_trylock in musl libc (for author):

http://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_spin_trylock.c?id=afbcac6826988d12d9a874359cab735049c17500

there a_cas equivalent __sync_val_compare_and_swap. in ways stupid example since it's saving branch or conditional move using old value, there other situations multiple old values possible , knowing 1 caused operation fail matters.