Home | History | Annotate | Download | only in atomics.lockfree
      1 //===----------------------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // UNSUPPORTED: libcpp-has-no-threads, c++98, c++03, c++11, c++14
     11 
     12 // <atomic>
     13 
     14 // static constexpr bool is_always_lock_free;
     15 
     16 #include <atomic>
     17 #include <cassert>
     18 
     19 #if !defined(__cpp_lib_atomic_is_always_lock_free)
     20 # error Feature test macro missing.
     21 #endif
     22 
     23 template <typename T> void checkAlwaysLockFree() {
     24   if (std::atomic<T>::is_always_lock_free)
     25     assert(std::atomic<T>().is_lock_free());
     26 }
     27 
     28 // FIXME: This separate test is needed to work around llvm.org/PR31864
     29 // which causes ATOMIC_LLONG_LOCK_FREE to be defined as '1' in 32-bit builds
     30 // even though __atomic_always_lock_free returns true for the same type.
     31 constexpr bool NeedWorkaroundForPR31864 =
     32 #if defined(__clang__)
     33 (sizeof(void*) == 4); // Needed on 32 bit builds
     34 #else
     35 false;
     36 #endif
     37 
     38 template <bool Disable = NeedWorkaroundForPR31864,
     39   std::enable_if_t<!Disable>* = nullptr,
     40   class LLong = long long,
     41   class ULLong = unsigned long long>
     42 void checkLongLongTypes() {
     43   static_assert(std::atomic<LLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE));
     44   static_assert(std::atomic<ULLong>::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE));
     45 }
     46 
     47 // Used to make the calls to __atomic_always_lock_free dependent on a template
     48 // parameter.
     49 template <class T> constexpr size_t getSizeOf() { return sizeof(T); }
     50 
     51 template <bool Enable = NeedWorkaroundForPR31864,
     52   std::enable_if_t<Enable>* = nullptr,
     53   class LLong = long long,
     54   class ULLong = unsigned long long>
     55 void checkLongLongTypes() {
     56   constexpr bool ExpectLockFree = __atomic_always_lock_free(getSizeOf<LLong>(), 0);
     57   static_assert(std::atomic<LLong>::is_always_lock_free == ExpectLockFree, "");
     58   static_assert(std::atomic<ULLong>::is_always_lock_free == ExpectLockFree, "");
     59   static_assert((0 != ATOMIC_LLONG_LOCK_FREE) == ExpectLockFree, "");
     60 }
     61 
     62 void run()
     63 {
     64 // structs and unions can't be defined in the template invocation.
     65 // Work around this with a typedef.
     66 #define CHECK_ALWAYS_LOCK_FREE(T)                                              \
     67   do {                                                                         \
     68     typedef T type;                                                            \
     69     checkAlwaysLockFree<type>();                                               \
     70   } while (0)
     71 
     72     CHECK_ALWAYS_LOCK_FREE(bool);
     73     CHECK_ALWAYS_LOCK_FREE(char);
     74     CHECK_ALWAYS_LOCK_FREE(signed char);
     75     CHECK_ALWAYS_LOCK_FREE(unsigned char);
     76     CHECK_ALWAYS_LOCK_FREE(char16_t);
     77     CHECK_ALWAYS_LOCK_FREE(char32_t);
     78     CHECK_ALWAYS_LOCK_FREE(wchar_t);
     79     CHECK_ALWAYS_LOCK_FREE(short);
     80     CHECK_ALWAYS_LOCK_FREE(unsigned short);
     81     CHECK_ALWAYS_LOCK_FREE(int);
     82     CHECK_ALWAYS_LOCK_FREE(unsigned int);
     83     CHECK_ALWAYS_LOCK_FREE(long);
     84     CHECK_ALWAYS_LOCK_FREE(unsigned long);
     85     CHECK_ALWAYS_LOCK_FREE(long long);
     86     CHECK_ALWAYS_LOCK_FREE(unsigned long long);
     87     CHECK_ALWAYS_LOCK_FREE(std::nullptr_t);
     88     CHECK_ALWAYS_LOCK_FREE(void*);
     89     CHECK_ALWAYS_LOCK_FREE(float);
     90     CHECK_ALWAYS_LOCK_FREE(double);
     91     CHECK_ALWAYS_LOCK_FREE(long double);
     92 #if __has_attribute(vector_size) && defined(_LIBCPP_VERSION)
     93     CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(1 * sizeof(int)))));
     94     CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(2 * sizeof(int)))));
     95     CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(4 * sizeof(int)))));
     96     CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(16 * sizeof(int)))));
     97     CHECK_ALWAYS_LOCK_FREE(int __attribute__((vector_size(32 * sizeof(int)))));
     98     CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(1 * sizeof(float)))));
     99     CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(2 * sizeof(float)))));
    100     CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(4 * sizeof(float)))));
    101     CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(16 * sizeof(float)))));
    102     CHECK_ALWAYS_LOCK_FREE(float __attribute__((vector_size(32 * sizeof(float)))));
    103     CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(1 * sizeof(double)))));
    104     CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(2 * sizeof(double)))));
    105     CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(4 * sizeof(double)))));
    106     CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(16 * sizeof(double)))));
    107     CHECK_ALWAYS_LOCK_FREE(double __attribute__((vector_size(32 * sizeof(double)))));
    108 #endif // __has_attribute(vector_size) && defined(_LIBCPP_VERSION)
    109     CHECK_ALWAYS_LOCK_FREE(struct Empty {});
    110     CHECK_ALWAYS_LOCK_FREE(struct OneInt { int i; });
    111     CHECK_ALWAYS_LOCK_FREE(struct IntArr2 { int i[2]; });
    112     CHECK_ALWAYS_LOCK_FREE(struct LLIArr2 { long long int i[2]; });
    113     CHECK_ALWAYS_LOCK_FREE(struct LLIArr4 { long long int i[4]; });
    114     CHECK_ALWAYS_LOCK_FREE(struct LLIArr8 { long long int i[8]; });
    115     CHECK_ALWAYS_LOCK_FREE(struct LLIArr16 { long long int i[16]; });
    116     CHECK_ALWAYS_LOCK_FREE(struct Padding { char c; /* padding */ long long int i; });
    117     CHECK_ALWAYS_LOCK_FREE(union IntFloat { int i; float f; });
    118 
    119     // C macro and static constexpr must be consistent.
    120     static_assert(std::atomic<bool>::is_always_lock_free == (2 == ATOMIC_BOOL_LOCK_FREE));
    121     static_assert(std::atomic<char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE));
    122     static_assert(std::atomic<signed char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE));
    123     static_assert(std::atomic<unsigned char>::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE));
    124     static_assert(std::atomic<char16_t>::is_always_lock_free == (2 == ATOMIC_CHAR16_T_LOCK_FREE));
    125     static_assert(std::atomic<char32_t>::is_always_lock_free == (2 == ATOMIC_CHAR32_T_LOCK_FREE));
    126     static_assert(std::atomic<wchar_t>::is_always_lock_free == (2 == ATOMIC_WCHAR_T_LOCK_FREE));
    127     static_assert(std::atomic<short>::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE));
    128     static_assert(std::atomic<unsigned short>::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE));
    129     static_assert(std::atomic<int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE));
    130     static_assert(std::atomic<unsigned int>::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE));
    131     static_assert(std::atomic<long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE));
    132     static_assert(std::atomic<unsigned long>::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE));
    133     checkLongLongTypes();
    134     static_assert(std::atomic<void*>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE));
    135     static_assert(std::atomic<std::nullptr_t>::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE));
    136 }
    137 
    138 int main() { run(); }
    139