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#include "test_macros.h" 96 97template <class A, class T> 98void 99do_test() 100{ 101 A obj(T(0)); 102 assert(obj == T(0)); 103 std::atomic_init(&obj, T(1)); 104 assert(obj == T(1)); 105 std::atomic_init(&obj, T(2)); 106 assert(obj == T(2)); 107 bool b0 = obj.is_lock_free(); 108 ((void)b0); // mark as unused 109 obj.store(T(0)); 110 assert(obj == T(0)); 111 obj.store(T(1), std::memory_order_release); 112 assert(obj == T(1)); 113 assert(obj.load() == T(1)); 114 assert(obj.load(std::memory_order_acquire) == T(1)); 115 assert(obj.exchange(T(2)) == T(1)); 116 assert(obj == T(2)); 117 assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2)); 118 assert(obj == T(3)); 119 T x = obj; 120 assert(cmpxchg_weak_loop(obj, x, T(2)) == true); 121 assert(obj == T(2)); 122 assert(x == T(3)); 123 assert(obj.compare_exchange_weak(x, T(1)) == false); 124 assert(obj == T(2)); 125 assert(x == T(2)); 126 x = T(2); 127 assert(obj.compare_exchange_strong(x, T(1)) == true); 128 assert(obj == T(1)); 129 assert(x == T(2)); 130 assert(obj.compare_exchange_strong(x, T(0)) == false); 131 assert(obj == T(1)); 132 assert(x == T(1)); 133 assert((obj = T(0)) == T(0)); 134 assert(obj == T(0)); 135 assert(obj++ == T(0)); 136 assert(obj == T(1)); 137 assert(++obj == T(2)); 138 assert(obj == T(2)); 139 assert(--obj == T(1)); 140 assert(obj == T(1)); 141 assert(obj-- == T(1)); 142 assert(obj == T(0)); 143 obj = T(2); 144 assert((obj += T(3)) == T(5)); 145 assert(obj == T(5)); 146 assert((obj -= T(3)) == T(2)); 147 assert(obj == T(2)); 148 assert((obj |= T(5)) == T(7)); 149 assert(obj == T(7)); 150 assert((obj &= T(0xF)) == T(7)); 151 assert(obj == T(7)); 152 assert((obj ^= T(0xF)) == T(8)); 153 assert(obj == T(8)); 154 155 { 156 TEST_ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23}; 157 A& zero = *new (storage) A(); 158 assert(zero == 0); 159 zero.~A(); 160 } 161} 162 163template <class A, class T> 164void test() 165{ 166 do_test<A, T>(); 167 do_test<volatile A, T>(); 168} 169 170 171int main() 172{ 173 test<std::atomic_char, char>(); 174 test<std::atomic_schar, signed char>(); 175 test<std::atomic_uchar, unsigned char>(); 176 test<std::atomic_short, short>(); 177 test<std::atomic_ushort, unsigned short>(); 178 test<std::atomic_int, int>(); 179 test<std::atomic_uint, unsigned int>(); 180 test<std::atomic_long, long>(); 181 test<std::atomic_ulong, unsigned long>(); 182 test<std::atomic_llong, long long>(); 183 test<std::atomic_ullong, unsigned long long>(); 184#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS 185 test<std::atomic_char16_t, char16_t>(); 186 test<std::atomic_char32_t, char32_t>(); 187#endif // _LIBCPP_HAS_NO_UNICODE_CHARS 188 test<std::atomic_wchar_t, wchar_t>(); 189 190 test<std::atomic_int8_t, int8_t>(); 191 test<std::atomic_uint8_t, uint8_t>(); 192 test<std::atomic_int16_t, int16_t>(); 193 test<std::atomic_uint16_t, uint16_t>(); 194 test<std::atomic_int32_t, int32_t>(); 195 test<std::atomic_uint32_t, uint32_t>(); 196 test<std::atomic_int64_t, int64_t>(); 197 test<std::atomic_uint64_t, uint64_t>(); 198 199 test<volatile std::atomic_char, char>(); 200 test<volatile std::atomic_schar, signed char>(); 201 test<volatile std::atomic_uchar, unsigned char>(); 202 test<volatile std::atomic_short, short>(); 203 test<volatile std::atomic_ushort, unsigned short>(); 204 test<volatile std::atomic_int, int>(); 205 test<volatile std::atomic_uint, unsigned int>(); 206 test<volatile std::atomic_long, long>(); 207 test<volatile std::atomic_ulong, unsigned long>(); 208 test<volatile std::atomic_llong, long long>(); 209 test<volatile std::atomic_ullong, unsigned long long>(); 210#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS 211 test<volatile std::atomic_char16_t, char16_t>(); 212 test<volatile std::atomic_char32_t, char32_t>(); 213#endif // _LIBCPP_HAS_NO_UNICODE_CHARS 214 test<volatile std::atomic_wchar_t, wchar_t>(); 215 216 test<volatile std::atomic_int8_t, int8_t>(); 217 test<volatile std::atomic_uint8_t, uint8_t>(); 218 test<volatile std::atomic_int16_t, int16_t>(); 219 test<volatile std::atomic_uint16_t, uint16_t>(); 220 test<volatile std::atomic_int32_t, int32_t>(); 221 test<volatile std::atomic_uint32_t, uint32_t>(); 222 test<volatile std::atomic_int64_t, int64_t>(); 223 test<volatile std::atomic_uint64_t, uint64_t>(); 224} 225