brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · e9f8192 Raw
183 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// <condition_variable>13 14// class condition_variable_any;15 16// template<class Lock, class Predicate>17//   bool wait(Lock& lock, stop_token stoken, Predicate pred);18 19#include <atomic>20#include <cassert>21#include <concepts>22#include <condition_variable>23#include <functional>24#include <mutex>25#include <shared_mutex>26#include <stop_token>27#include <thread>28 29#include "make_test_thread.h"30#include "test_macros.h"31 32template <class Mutex, class Lock>33void test() {34  // stop_requested before hand35  {36    std::stop_source ss;37    std::condition_variable_any cv;38    Mutex mutex;39    Lock lock{mutex};40    ss.request_stop();41 42    // [Note 1: The returned value indicates whether the predicate evaluated to true regardless of whether there was a stop request.]43    std::same_as<bool> auto r1 = cv.wait(lock, ss.get_token(), []() { return false; });44    assert(!r1);45 46    std::same_as<bool> auto r2 = cv.wait(lock, ss.get_token(), []() { return true; });47    assert(r2);48 49    // Postconditions: lock is locked by the calling thread.50    assert(lock.owns_lock());51  }52 53  // no stop request54  {55    std::stop_source ss;56    std::condition_variable_any cv;57    Mutex mutex;58    Lock lock{mutex};59    std::same_as<bool> auto r1 = cv.wait(lock, ss.get_token(), []() { return true; });60    assert(r1);61 62    bool flag   = false;63    auto thread = support::make_test_thread([&]() {64      std::this_thread::sleep_for(std::chrono::milliseconds(2));65      std::unique_lock<Mutex> lock2{mutex};66      flag = true;67      cv.notify_all();68    });69 70    std::same_as<bool> auto r2 = cv.wait(lock, ss.get_token(), [&]() { return flag; });71    assert(flag);72    assert(r2);73    thread.join();74 75    assert(lock.owns_lock());76  }77 78  // stop request comes while waiting79  {80    std::stop_source ss;81    std::condition_variable_any cv;82    Mutex mutex;83    Lock lock{mutex};84 85    std::atomic_bool start = false;86    std::atomic_bool done  = false;87    auto thread            = support::make_test_thread([&]() {88      start.wait(false);89      ss.request_stop();90 91      while (!done) {92        cv.notify_all();93        std::this_thread::sleep_for(std::chrono::milliseconds(2));94      }95    });96 97    std::same_as<bool> auto r = cv.wait(lock, ss.get_token(), [&]() {98      start.store(true);99      start.notify_all();100      return false;101    });102    assert(!r);103    done = true;104    thread.join();105 106    assert(lock.owns_lock());107  }108 109  // #76807 Hangs in std::condition_variable_any when used with std::stop_token110  {111    class MyThread {112    public:113      MyThread() {114        thread_ = support::make_test_jthread([this](std::stop_token st) {115          while (!st.stop_requested()) {116            std::unique_lock lock{m_};117            cv_.wait(lock, st, [] { return false; });118          }119        });120      }121 122    private:123      std::mutex m_;124      std::condition_variable_any cv_;125      std::jthread thread_;126    };127 128    [[maybe_unused]] MyThread my_thread;129  }130 131  // request_stop potentially in-between check and wait132  {133    std::stop_source ss;134    std::condition_variable_any cv;135    Mutex mutex;136    Lock lock{mutex};137 138    std::atomic_bool pred_started        = false;139    std::atomic_bool request_stop_called = false;140    auto thread                          = support::make_test_thread([&]() {141      pred_started.wait(false);142      ss.request_stop();143      request_stop_called.store(true);144      request_stop_called.notify_all();145    });146 147    std::same_as<bool> auto r = cv.wait(lock, ss.get_token(), [&]() {148      pred_started.store(true);149      pred_started.notify_all();150      request_stop_called.wait(false);151      return false;152    });153    assert(!r);154    thread.join();155 156    assert(lock.owns_lock());157  }158 159#if !defined(TEST_HAS_NO_EXCEPTIONS)160  // Throws: Any exception thrown by pred.161  {162    std::stop_source ss;163    std::condition_variable_any cv;164    Mutex mutex;165    Lock lock{mutex};166 167    try {168      cv.wait(lock, ss.get_token(), []() -> bool { throw 5; });169      assert(false);170    } catch (int i) {171      assert(i == 5);172    }173  }174#endif //!defined(TEST_HAS_NO_EXCEPTIONS)175}176 177int main(int, char**) {178  test<std::mutex, std::unique_lock<std::mutex>>();179  test<std::shared_mutex, std::shared_lock<std::shared_mutex>>();180 181  return 0;182}183