c++macosclanglock-freestdatomic

`is_always_lock_free` gives `true` but `is_lock_free()` gives `false` on macOS, why?


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?


Solution

  • 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.