I'm experimenting with C++ atomic's std::atomic<T>::is_always_lock_free
and std::atomic<T>::is_lock_free
.
I wrote a simple struct A
and want to know if the atomic version of A
is lock-free:
#include <iostream>
#include <atomic>
using namespace std;
struct A {
int x;
int y;
int z;
};
int main() {
atomic<A> b;
cout << boolalpha;
cout << "b.is_always_lock_free = " << b.is_always_lock_free << endl;
cout << "b.is_lock_free = " << b.is_lock_free() << endl;
return 0;
}
On a x86-64 Linux, I compiled it with g++ 9.4.0 and C++17, the output is normal:
b.is_always_lock_free = false
b.is_lock_free = false
However, I also compiled it with clang++ 16.0.0 on my Mac (ARM64), the output is strange:
b.is_always_lock_free = true
b.is_lock_free = false
Why is_always_lock_free = true
and is_lock_free = false
? If it can always be lock-free, why b
is not lock-free?
It's a bug in the standard library libc++ (that is not present in libstdc++). Effectively it calls the builtin:
atomic_always_lock_free
with sizeof(__cxx_atomic_impl<A>)
which is 16
,
whereas it calls
atomic_is_lock_free
with sizeof(A)
which is 12
,
thus yielding inconsistent results.