brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.6 KiB · 2169366 Raw
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