1 | // |
2 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
3 | // See https://llvm.org/LICENSE.txt for license information. |
4 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
5 | // |
6 | //===----------------------------------------------------------------------===// |
7 | |
8 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
9 | // UNSUPPORTED: no-threads |
10 | // XFAIL: availability-synchronization_library-missing |
11 | // XFAIL: !has-64-bit-atomics |
12 | // XFAIL: !has-1024-bit-atomics |
13 | |
14 | // MSVC warning C4310: cast truncates constant value |
15 | // ADDITIONAL_COMPILE_FLAGS(cl-style-warnings): /wd4310 |
16 | |
17 | // void wait(T, memory_order = memory_order::seq_cst) const noexcept; |
18 | |
19 | #include <atomic> |
20 | #include <cassert> |
21 | #include <type_traits> |
22 | |
23 | #include "atomic_helpers.h" |
24 | #include "make_test_thread.h" |
25 | #include "test_helper.h" |
26 | #include "test_macros.h" |
27 | |
28 | template <typename T> |
29 | struct TestWait { |
30 | void operator()() const { |
31 | { |
32 | T x(T(1)); |
33 | std::atomic_ref<T> const a(x); |
34 | |
35 | assert(a.load() == T(1)); |
36 | a.wait(T(0)); |
37 | std::thread t1 = support::make_test_thread([&]() { |
38 | a.store(T(3)); |
39 | a.notify_one(); |
40 | }); |
41 | a.wait(T(1)); |
42 | assert(a.load() == T(3)); |
43 | t1.join(); |
44 | ASSERT_NOEXCEPT(a.wait(T(0))); |
45 | |
46 | assert(a.load() == T(3)); |
47 | a.wait(T(0), std::memory_order_seq_cst); |
48 | std::thread t2 = support::make_test_thread([&]() { |
49 | a.store(T(5)); |
50 | a.notify_one(); |
51 | }); |
52 | a.wait(T(3), std::memory_order_seq_cst); |
53 | assert(a.load() == T(5)); |
54 | t2.join(); |
55 | ASSERT_NOEXCEPT(a.wait(T(0), std::memory_order_seq_cst)); |
56 | } |
57 | |
58 | // memory_order::acquire |
59 | { |
60 | auto store = [](std::atomic_ref<T> const& x, T, T new_val) { x.store(new_val, std::memory_order::release); }; |
61 | auto load = [](std::atomic_ref<T> const& x) { |
62 | auto result = x.load(std::memory_order::relaxed); |
63 | x.wait(T(255), std::memory_order::acquire); |
64 | return result; |
65 | }; |
66 | test_acquire_release<T>(store, load); |
67 | } |
68 | |
69 | // memory_order::seq_cst |
70 | { |
71 | auto store = [](std::atomic_ref<T> const& x, T, T new_val) { x.store(new_val); }; |
72 | auto load_no_arg = [](std::atomic_ref<T> const& x) { |
73 | auto result = x.load(std::memory_order::relaxed); |
74 | x.wait(T(255)); |
75 | return result; |
76 | }; |
77 | auto load_with_order = [](std::atomic_ref<T> const& x) { |
78 | auto result = x.load(std::memory_order::relaxed); |
79 | x.wait(T(255), std::memory_order::seq_cst); |
80 | return result; |
81 | }; |
82 | test_seq_cst<T>(store, load_no_arg); |
83 | test_seq_cst<T>(store, load_with_order); |
84 | } |
85 | } |
86 | }; |
87 | |
88 | int main(int, char**) { |
89 | TestEachAtomicType<TestWait>()(); |
90 | return 0; |
91 | } |
92 | |