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 11 12 // <atomic> 13 14 // template <> 15 // struct atomic<integral> 16 // { 17 // bool is_lock_free() const volatile; 18 // bool is_lock_free() const; 19 // void store(integral desr, memory_order m = memory_order_seq_cst) volatile; 20 // void store(integral desr, memory_order m = memory_order_seq_cst); 21 // integral load(memory_order m = memory_order_seq_cst) const volatile; 22 // integral load(memory_order m = memory_order_seq_cst) const; 23 // operator integral() const volatile; 24 // operator integral() const; 25 // integral exchange(integral desr, 26 // memory_order m = memory_order_seq_cst) volatile; 27 // integral exchange(integral desr, memory_order m = memory_order_seq_cst); 28 // bool compare_exchange_weak(integral& expc, integral desr, 29 // memory_order s, memory_order f) volatile; 30 // bool compare_exchange_weak(integral& expc, integral desr, 31 // memory_order s, memory_order f); 32 // bool compare_exchange_strong(integral& expc, integral desr, 33 // memory_order s, memory_order f) volatile; 34 // bool compare_exchange_strong(integral& expc, integral desr, 35 // memory_order s, memory_order f); 36 // bool compare_exchange_weak(integral& expc, integral desr, 37 // memory_order m = memory_order_seq_cst) volatile; 38 // bool compare_exchange_weak(integral& expc, integral desr, 39 // memory_order m = memory_order_seq_cst); 40 // bool compare_exchange_strong(integral& expc, integral desr, 41 // memory_order m = memory_order_seq_cst) volatile; 42 // bool compare_exchange_strong(integral& expc, integral desr, 43 // memory_order m = memory_order_seq_cst); 44 // 45 // integral 46 // fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile; 47 // integral fetch_add(integral op, memory_order m = memory_order_seq_cst); 48 // integral 49 // fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile; 50 // integral fetch_sub(integral op, memory_order m = memory_order_seq_cst); 51 // integral 52 // fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile; 53 // integral fetch_and(integral op, memory_order m = memory_order_seq_cst); 54 // integral 55 // fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile; 56 // integral fetch_or(integral op, memory_order m = memory_order_seq_cst); 57 // integral 58 // fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile; 59 // integral fetch_xor(integral op, memory_order m = memory_order_seq_cst); 60 // 61 // atomic() = default; 62 // constexpr atomic(integral desr); 63 // atomic(const atomic&) = delete; 64 // atomic& operator=(const atomic&) = delete; 65 // atomic& operator=(const atomic&) volatile = delete; 66 // integral operator=(integral desr) volatile; 67 // integral operator=(integral desr); 68 // 69 // integral operator++(int) volatile; 70 // integral operator++(int); 71 // integral operator--(int) volatile; 72 // integral operator--(int); 73 // integral operator++() volatile; 74 // integral operator++(); 75 // integral operator--() volatile; 76 // integral operator--(); 77 // integral operator+=(integral op) volatile; 78 // integral operator+=(integral op); 79 // integral operator-=(integral op) volatile; 80 // integral operator-=(integral op); 81 // integral operator&=(integral op) volatile; 82 // integral operator&=(integral op); 83 // integral operator|=(integral op) volatile; 84 // integral operator|=(integral op); 85 // integral operator^=(integral op) volatile; 86 // integral operator^=(integral op); 87 // }; 88 89 #include <atomic> 90 #include <new> 91 #include <cassert> 92 93 #include <cmpxchg_loop.h> 94 95 template <class A, class T> 96 void 97 do_test() 98 { 99 A obj(T(0)); 100 assert(obj == T(0)); 101 std::atomic_init(&obj, T(1)); 102 assert(obj == T(1)); 103 std::atomic_init(&obj, T(2)); 104 assert(obj == T(2)); 105 bool b0 = obj.is_lock_free(); 106 ((void)b0); // mark as unused 107 obj.store(T(0)); 108 assert(obj == T(0)); 109 obj.store(T(1), std::memory_order_release); 110 assert(obj == T(1)); 111 assert(obj.load() == T(1)); 112 assert(obj.load(std::memory_order_acquire) == T(1)); 113 assert(obj.exchange(T(2)) == T(1)); 114 assert(obj == T(2)); 115 assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2)); 116 assert(obj == T(3)); 117 T x = obj; 118 assert(cmpxchg_weak_loop(obj, x, T(2)) == true); 119 assert(obj == T(2)); 120 assert(x == T(3)); 121 assert(obj.compare_exchange_weak(x, T(1)) == false); 122 assert(obj == T(2)); 123 assert(x == T(2)); 124 x = T(2); 125 assert(obj.compare_exchange_strong(x, T(1)) == true); 126 assert(obj == T(1)); 127 assert(x == T(2)); 128 assert(obj.compare_exchange_strong(x, T(0)) == false); 129 assert(obj == T(1)); 130 assert(x == T(1)); 131 assert((obj = T(0)) == T(0)); 132 assert(obj == T(0)); 133 assert(obj++ == T(0)); 134 assert(obj == T(1)); 135 assert(++obj == T(2)); 136 assert(obj == T(2)); 137 assert(--obj == T(1)); 138 assert(obj == T(1)); 139 assert(obj-- == T(1)); 140 assert(obj == T(0)); 141 obj = T(2); 142 assert((obj += T(3)) == T(5)); 143 assert(obj == T(5)); 144 assert((obj -= T(3)) == T(2)); 145 assert(obj == T(2)); 146 assert((obj |= T(5)) == T(7)); 147 assert(obj == T(7)); 148 assert((obj &= T(0xF)) == T(7)); 149 assert(obj == T(7)); 150 assert((obj ^= T(0xF)) == T(8)); 151 assert(obj == T(8)); 152 153 { 154 _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23}; 155 A& zero = *new (storage) A(); 156 assert(zero == 0); 157 zero.~A(); 158 } 159 } 160 161 template <class A, class T> 162 void test() 163 { 164 do_test<A, T>(); 165 do_test<volatile A, T>(); 166 } 167 168 169 int main() 170 { 171 test<std::atomic_char, char>(); 172 test<std::atomic_schar, signed char>(); 173 test<std::atomic_uchar, unsigned char>(); 174 test<std::atomic_short, short>(); 175 test<std::atomic_ushort, unsigned short>(); 176 test<std::atomic_int, int>(); 177 test<std::atomic_uint, unsigned int>(); 178 test<std::atomic_long, long>(); 179 test<std::atomic_ulong, unsigned long>(); 180 test<std::atomic_llong, long long>(); 181 test<std::atomic_ullong, unsigned long long>(); 182 #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS 183 test<std::atomic_char16_t, char16_t>(); 184 test<std::atomic_char32_t, char32_t>(); 185 #endif // _LIBCPP_HAS_NO_UNICODE_CHARS 186 test<std::atomic_wchar_t, wchar_t>(); 187 188 test<volatile std::atomic_char, char>(); 189 test<volatile std::atomic_schar, signed char>(); 190 test<volatile std::atomic_uchar, unsigned char>(); 191 test<volatile std::atomic_short, short>(); 192 test<volatile std::atomic_ushort, unsigned short>(); 193 test<volatile std::atomic_int, int>(); 194 test<volatile std::atomic_uint, unsigned int>(); 195 test<volatile std::atomic_long, long>(); 196 test<volatile std::atomic_ulong, unsigned long>(); 197 test<volatile std::atomic_llong, long long>(); 198 test<volatile std::atomic_ullong, unsigned long long>(); 199 #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS 200 test<volatile std::atomic_char16_t, char16_t>(); 201 test<volatile std::atomic_char32_t, char32_t>(); 202 #endif // _LIBCPP_HAS_NO_UNICODE_CHARS 203 test<volatile std::atomic_wchar_t, wchar_t>(); 204 } 205