xref: /llvm-project/libcxx/test/std/thread/thread.stoptoken/stopsource/stop_requested.pass.cpp (revision 121ed5c1985356436d0040dbe81bca26992b1fae)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // UNSUPPORTED: no-threads
10 // UNSUPPORTED: c++03, c++11, c++14, c++17
11 // XFAIL: availability-synchronization_library-missing
12 
13 // [[nodiscard]] bool stop_requested() const noexcept;
14 // true if *this has ownership of a stop state that has received a stop request; otherwise, false.
15 
16 #include <cassert>
17 #include <chrono>
18 #include <concepts>
19 #include <optional>
20 #include <stop_token>
21 #include <type_traits>
22 
23 #include "make_test_thread.h"
24 #include "test_macros.h"
25 
26 template <class T>
27 concept IsStopRequestedNoexcept = requires(const T& t) {
28   { t.stop_requested() } noexcept;
29 };
30 
31 static_assert(IsStopRequestedNoexcept<std::stop_source>);
32 
33 int main(int, char**) {
34   // no state
35   {
36     const std::stop_source ss{std::nostopstate};
37     assert(!ss.stop_requested());
38   }
39 
40   // has state
41   {
42     std::stop_source ss;
43     assert(!ss.stop_requested());
44 
45     ss.request_stop();
46     assert(ss.stop_requested());
47   }
48 
49   // request from another instance with same state
50   {
51     std::stop_source ss1;
52     auto ss2 = ss1;
53     ss2.request_stop();
54     assert(ss1.stop_requested());
55   }
56 
57   // request from another instance with different state
58   {
59     std::stop_source ss1;
60     std::stop_source ss2;
61 
62     ss2.request_stop();
63     assert(!ss1.stop_requested());
64   }
65 
66   // multiple threads
67   {
68     std::stop_source ss;
69 
70     std::thread t = support::make_test_thread([&]() { ss.request_stop(); });
71 
72     t.join();
73     assert(ss.stop_requested());
74   }
75 
76   // [thread.stopsource.intro] A call to request_stop that returns true
77   // synchronizes with a call to stop_requested on an associated stop_source
78   // or stop_source object that returns true.
79   {
80     std::stop_source ss;
81 
82     bool flag = false;
83 
84     std::thread t = support::make_test_thread([&]() {
85       using namespace std::chrono_literals;
86       std::this_thread::sleep_for(1ms);
87 
88       // happens-before request_stop
89       flag   = true;
90       auto b = ss.request_stop();
91       assert(b);
92     });
93 
94     while (!ss.stop_requested()) {
95       std::this_thread::yield();
96     }
97 
98     // write should be visible to the current thread
99     assert(flag == true);
100 
101     t.join();
102   }
103 
104   return 0;
105 }
106