111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===//
211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                     The LLVM Compiler Infrastructure
411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This file is dual licensed under the MIT and the University of Illinois Open
611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Source Licenses. See LICENSE.TXT for details.
711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===//
911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// UNSUPPORTED: libcpp-has-no-threads
1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// <atomic>
1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// template <>
1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// struct atomic<integral>
1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// {
1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool is_lock_free() const volatile;
1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool is_lock_free() const;
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     void store(integral desr, memory_order m = memory_order_seq_cst) volatile;
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     void store(integral desr, memory_order m = memory_order_seq_cst);
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral load(memory_order m = memory_order_seq_cst) const volatile;
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral load(memory_order m = memory_order_seq_cst) const;
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     operator integral() const volatile;
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     operator integral() const;
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral exchange(integral desr,
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                       memory_order m = memory_order_seq_cst) volatile;
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral exchange(integral desr, memory_order m = memory_order_seq_cst);
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool compare_exchange_weak(integral& expc, integral desr,
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                memory_order s, memory_order f) volatile;
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool compare_exchange_weak(integral& expc, integral desr,
3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                memory_order s, memory_order f);
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool compare_exchange_strong(integral& expc, integral desr,
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                  memory_order s, memory_order f) volatile;
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool compare_exchange_strong(integral& expc, integral desr,
3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                  memory_order s, memory_order f);
3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool compare_exchange_weak(integral& expc, integral desr,
3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                memory_order m = memory_order_seq_cst) volatile;
3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool compare_exchange_weak(integral& expc, integral desr,
3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                memory_order m = memory_order_seq_cst);
4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool compare_exchange_strong(integral& expc, integral desr,
4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                 memory_order m = memory_order_seq_cst) volatile;
4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     bool compare_exchange_strong(integral& expc, integral desr,
4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//                                  memory_order m = memory_order_seq_cst);
4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral
4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//         fetch_add(integral op, memory_order m = memory_order_seq_cst) volatile;
4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral fetch_add(integral op, memory_order m = memory_order_seq_cst);
4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral
4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//         fetch_sub(integral op, memory_order m = memory_order_seq_cst) volatile;
5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral fetch_sub(integral op, memory_order m = memory_order_seq_cst);
5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral
5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//         fetch_and(integral op, memory_order m = memory_order_seq_cst) volatile;
5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral fetch_and(integral op, memory_order m = memory_order_seq_cst);
5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral
5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//         fetch_or(integral op, memory_order m = memory_order_seq_cst) volatile;
5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral fetch_or(integral op, memory_order m = memory_order_seq_cst);
5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral
5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//         fetch_xor(integral op, memory_order m = memory_order_seq_cst) volatile;
5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral fetch_xor(integral op, memory_order m = memory_order_seq_cst);
6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     atomic() = default;
6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     constexpr atomic(integral desr);
6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     atomic(const atomic&) = delete;
6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     atomic& operator=(const atomic&) = delete;
6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     atomic& operator=(const atomic&) volatile = delete;
6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator=(integral desr) volatile;
6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator=(integral desr);
6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//
6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator++(int) volatile;
7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator++(int);
7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator--(int) volatile;
7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator--(int);
7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator++() volatile;
7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator++();
7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator--() volatile;
7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator--();
7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator+=(integral op) volatile;
7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator+=(integral op);
7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator-=(integral op) volatile;
8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator-=(integral op);
8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator&=(integral op) volatile;
8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator&=(integral op);
8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator|=(integral op) volatile;
8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator|=(integral op);
8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator^=(integral op) volatile;
8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//     integral operator^=(integral op);
8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// };
8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <atomic>
9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <new>
9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <cassert>
9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <cmpxchg_loop.h>
9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9511cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class A, class T>
9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid
9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertdo_test()
9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    A obj(T(0));
10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(0));
10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::atomic_init(&obj, T(1));
10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(1));
10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::atomic_init(&obj, T(2));
10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(2));
10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool b0 = obj.is_lock_free();
10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    ((void)b0); // mark as unused
10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    obj.store(T(0));
10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(0));
10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    obj.store(T(1), std::memory_order_release);
11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(1));
11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj.load() == T(1));
11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj.load(std::memory_order_acquire) == T(1));
11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj.exchange(T(2)) == T(1));
11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(2));
11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj.exchange(T(3), std::memory_order_relaxed) == T(2));
11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(3));
11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    T x = obj;
11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(cmpxchg_weak_loop(obj, x, T(2)) == true);
11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(2));
12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(x == T(3));
12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj.compare_exchange_weak(x, T(1)) == false);
12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(2));
12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(x == T(2));
12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    x = T(2);
12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj.compare_exchange_strong(x, T(1)) == true);
12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(1));
12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(x == T(2));
12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj.compare_exchange_strong(x, T(0)) == false);
12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(1));
13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(x == T(1));
13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert((obj = T(0)) == T(0));
13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(0));
13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj++ == T(0));
13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(1));
13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(++obj == T(2));
13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(2));
13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(--obj == T(1));
13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(1));
13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj-- == T(1));
14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(0));
14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    obj = T(2);
14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert((obj += T(3)) == T(5));
14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(5));
14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert((obj -= T(3)) == T(2));
14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(2));
14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert((obj |= T(5)) == T(7));
14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(7));
14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert((obj &= T(0xF)) == T(7));
14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(7));
15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert((obj ^= T(0xF)) == T(8));
15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(obj == T(8));
15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        _ALIGNAS_TYPE(A) char storage[sizeof(A)] = {23};
15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        A& zero = *new (storage) A();
15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        assert(zero == 0);
15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        zero.~A();
15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16111cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <class A, class T>
16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid test()
16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    do_test<A, T>();
16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    do_test<volatile A, T>();
16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertint main()
17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_char, char>();
17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_schar, signed char>();
17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_uchar, unsigned char>();
17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_short, short>();
17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_ushort, unsigned short>();
17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_int, int>();
17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_uint, unsigned int>();
17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_long, long>();
17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_ulong, unsigned long>();
18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_llong, long long>();
18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_ullong, unsigned long long>();
18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_char16_t, char16_t>();
18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_char32_t, char32_t>();
18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif  // _LIBCPP_HAS_NO_UNICODE_CHARS
18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<std::atomic_wchar_t, wchar_t>();
18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_char, char>();
18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_schar, signed char>();
19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_uchar, unsigned char>();
19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_short, short>();
19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_ushort, unsigned short>();
19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_int, int>();
19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_uint, unsigned int>();
19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_long, long>();
19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_ulong, unsigned long>();
19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_llong, long long>();
19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_ullong, unsigned long long>();
19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_char16_t, char16_t>();
20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_char32_t, char32_t>();
20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif  // _LIBCPP_HAS_NO_UNICODE_CHARS
20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    test<volatile std::atomic_wchar_t, wchar_t>();
20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
205