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