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