155 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// UNSUPPORTED: no-threads10// UNSUPPORTED: c++03, c++11, c++14, c++1711 12// [[nodiscard]] bool stop_requested() const noexcept;13// Returns: true if *this has ownership of a stop state that has received a stop request; otherwise, false.14 15#include <cassert>16#include <chrono>17#include <concepts>18#include <optional>19#include <stop_token>20#include <type_traits>21 22#include "make_test_thread.h"23#include "test_macros.h"24 25template <class T>26concept IsStopRequestedNoexcept = requires(const T& t) {27 { t.stop_requested() } noexcept;28};29 30static_assert(IsStopRequestedNoexcept<std::stop_token>);31 32int main(int, char**) {33 // no state34 {35 const std::stop_token st;36 assert(!st.stop_requested());37 }38 39 // has state40 {41 std::stop_source ss;42 const auto st = ss.get_token();43 assert(!st.stop_requested());44 45 ss.request_stop();46 assert(st.stop_requested());47 }48 49 // already requested before constructor50 {51 std::stop_source ss;52 ss.request_stop();53 const auto st = ss.get_token();54 assert(st.stop_requested());55 }56 57 // stop_token should share the state58 {59 std::optional<std::stop_source> ss{std::in_place};60 ss->request_stop();61 const auto st = ss->get_token();62 63 ss.reset();64 assert(st.stop_requested());65 }66 67 // single stop_source, multiple stop_token68 {69 std::stop_source ss;70 const auto st1 = ss.get_token();71 const auto st2 = ss.get_token();72 assert(!st1.stop_requested());73 assert(!st2.stop_requested());74 75 ss.request_stop();76 assert(st1.stop_requested());77 assert(st2.stop_requested());78 }79 80 // multiple stop_source, multiple stop_token81 {82 std::stop_source ss1;83 std::stop_source ss2;84 85 const auto st1 = ss1.get_token();86 const auto st2 = ss2.get_token();87 assert(!st1.stop_requested());88 assert(!st2.stop_requested());89 90 ss1.request_stop();91 assert(st1.stop_requested());92 assert(!st2.stop_requested());93 }94 95 // multiple threads96 {97 std::stop_source ss;98 const auto st = ss.get_token();99 assert(!st.stop_requested());100 101 std::thread t = support::make_test_thread([&]() { ss.request_stop(); });102 103 t.join();104 assert(st.stop_requested());105 }106 107 // maybe concurrent calls108 {109 std::stop_source ss;110 const auto st = ss.get_token();111 assert(!st.stop_requested());112 113 std::thread t = support::make_test_thread([&]() { ss.request_stop(); });114 115 while (!st.stop_requested()) {116 // should eventually exit the loop117 std::this_thread::yield();118 }119 120 t.join();121 }122 123 // [thread.stoptoken.intro] A call to request_stop that returns true124 // synchronizes with a call to stop_requested on an associated stop_token125 // or stop_source object that returns true.126 {127 std::stop_source ss;128 const auto st = ss.get_token();129 assert(!st.stop_requested());130 131 bool flag = false;132 133 std::thread t = support::make_test_thread([&]() {134 using namespace std::chrono_literals;135 std::this_thread::sleep_for(1ms);136 137 // happens-before request_stop138 flag = true;139 auto b = ss.request_stop();140 assert(b);141 });142 143 while (!st.stop_requested()) {144 std::this_thread::yield();145 }146 147 // write should be visible to the current thread148 assert(flag == true);149 150 t.join();151 }152 153 return 0;154}155