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 <cassert> 89 90 template <class A, class T> 91 void 92 do_test() 93 { 94 A obj(T(0)); 95 assert(obj == T(0)); 96 std::atomic_init(&obj, T(1)); 97 assert(obj == T(1)); 98 std::atomic_init(&obj, T(2)); 99 assert(obj == T(2)); 100 bool b0 = obj.is_lock_free(); 101 obj.store(T(0)); 102 assert(obj == T(0)); 103 obj.store(T(1), std::memory_order_release); 104 assert(obj == T(1)); 105 assert(obj.load() == T(1)); 106 assert(obj.load(std::memory_order_acquire) == T(1)); 107 assert(obj.exchange(T(2)) == T(1)); 108 assert(obj == T(2)); 109 assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2)); 110 assert(obj == T(3)); 111 T x = obj; 112 assert(obj.compare_exchange_weak(x, T(2)) == true); 113 assert(obj == T(2)); 114 assert(x == T(3)); 115 assert(obj.compare_exchange_weak(x, T(1)) == false); 116 assert(obj == T(2)); 117 assert(x == T(2)); 118 x = T(2); 119 assert(obj.compare_exchange_strong(x, T(1)) == true); 120 assert(obj == T(1)); 121 assert(x == T(2)); 122 assert(obj.compare_exchange_strong(x, T(0)) == false); 123 assert(obj == T(1)); 124 assert(x == T(1)); 125 assert((obj = T(0)) == T(0)); 126 assert(obj == T(0)); 127 assert(obj++ == T(0)); 128 assert(obj == T(1)); 129 assert(++obj == T(2)); 130 assert(obj == T(2)); 131 assert(--obj == T(1)); 132 assert(obj == T(1)); 133 assert(obj-- == T(1)); 134 assert(obj == T(0)); 135 obj = T(2); 136 assert((obj += T(3)) == T(5)); 137 assert(obj == T(5)); 138 assert((obj -= T(3)) == T(2)); 139 assert(obj == T(2)); 140 assert((obj |= T(5)) == T(7)); 141 assert(obj == T(7)); 142 assert((obj &= T(0xF)) == T(7)); 143 assert(obj == T(7)); 144 assert((obj ^= T(0xF)) == T(8)); 145 assert(obj == T(8)); 146 } 147 148 template <class A, class T> 149 void test() 150 { 151 do_test<A, T>(); 152 do_test<volatile A, T>(); 153 } 154 155 156 int main() 157 { 158 test<std::atomic_char, char>(); 159 test<std::atomic_schar, signed char>(); 160 test<std::atomic_uchar, unsigned char>(); 161 test<std::atomic_short, short>(); 162 test<std::atomic_ushort, unsigned short>(); 163 test<std::atomic_int, int>(); 164 test<std::atomic_uint, unsigned int>(); 165 test<std::atomic_long, long>(); 166 test<std::atomic_ulong, unsigned long>(); 167 test<std::atomic_llong, long long>(); 168 test<std::atomic_ullong, unsigned long long>(); 169 #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS 170 test<std::atomic_char16_t, char16_t>(); 171 test<std::atomic_char32_t, char32_t>(); 172 #endif // _LIBCPP_HAS_NO_UNICODE_CHARS 173 test<std::atomic_wchar_t, wchar_t>(); 174 175 test<volatile std::atomic_char, char>(); 176 test<volatile std::atomic_schar, signed char>(); 177 test<volatile std::atomic_uchar, unsigned char>(); 178 test<volatile std::atomic_short, short>(); 179 test<volatile std::atomic_ushort, unsigned short>(); 180 test<volatile std::atomic_int, int>(); 181 test<volatile std::atomic_uint, unsigned int>(); 182 test<volatile std::atomic_long, long>(); 183 test<volatile std::atomic_ulong, unsigned long>(); 184 test<volatile std::atomic_llong, long long>(); 185 test<volatile std::atomic_ullong, unsigned long long>(); 186 #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS 187 test<volatile std::atomic_char16_t, char16_t>(); 188 test<volatile std::atomic_char32_t, char32_t>(); 189 #endif // _LIBCPP_HAS_NO_UNICODE_CHARS 190 test<volatile std::atomic_wchar_t, wchar_t>(); 191 } 192