brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.4 KiB · 5ce5bcc Raw
114 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-threads, c++0310 11// <condition_variable>12 13// class condition_variable;14 15// template <class Predicate>16//   void wait(unique_lock<mutex>& lock, Predicate pred);17 18#include <condition_variable>19#include <atomic>20#include <cassert>21#include <mutex>22#include <thread>23 24#include "make_test_thread.h"25#include "test_macros.h"26 27int main(int, char**) {28  // Test unblocking via a call to notify_one() in another thread.29  //30  // To test this, we try to minimize the likelihood that we got awoken by a31  // spurious wakeup by updating the likely_spurious flag only immediately32  // before we perform the notification.33  {34    std::atomic<bool> ready(false);35    std::atomic<bool> likely_spurious(true);36    std::condition_variable cv;37    std::mutex mutex;38 39    std::thread t1 = support::make_test_thread([&] {40      std::unique_lock<std::mutex> lock(mutex);41      ready = true;42      cv.wait(lock, [&] { return !likely_spurious; });43    });44 45    std::thread t2 = support::make_test_thread([&] {46      while (!ready) {47        // spin48      }49 50      // Acquire the same mutex as t1. This ensures that the condition variable has started51      // waiting (and hence released that mutex).52      std::unique_lock<std::mutex> lock(mutex);53 54      likely_spurious = false;55      lock.unlock();56      cv.notify_one();57    });58 59    t2.join();60    t1.join();61  }62 63  // Test unblocking via a spurious wakeup.64  //65  // To test this, we basically never wake up the condition variable. This way, we66  // are hoping to get out of the wait via a spurious wakeup.67  //68  // However, since spurious wakeups are not required to even happen, this test is69  // only trying to trigger that code path, but not actually asserting that it is70  // taken. In particular, we do need to eventually ensure we get out of the wait71  // by standard means, so we actually wake up the thread at the end.72  {73    std::atomic<bool> ready(false);74    std::atomic<bool> awoken(false);75    std::condition_variable cv;76    std::mutex mutex;77 78    std::thread t1 = support::make_test_thread([&] {79      std::unique_lock<std::mutex> lock(mutex);80      ready = true;81      cv.wait(lock, [&] { return true; });82      awoken = true;83    });84 85    std::thread t2 = support::make_test_thread([&] {86      while (!ready) {87        // spin88      }89 90      // Acquire the same mutex as t1. This ensures that the condition variable has started91      // waiting (and hence released that mutex).92      std::unique_lock<std::mutex> lock(mutex);93      lock.unlock();94 95      // Give some time for t1 to be awoken spuriously so that code path is used.96      std::this_thread::sleep_for(std::chrono::seconds(1));97 98      // We would want to assert that the thread has been awoken after this time,99      // however nothing guarantees us that it ever gets spuriously awoken, so100      // we can't really check anything. This is still left here as documentation.101      bool woke = awoken.load();102      assert(woke || !woke);103 104      // Whatever happened, actually awaken the condition variable to ensure the test finishes.105      cv.notify_one();106    });107 108    t2.join();109    t1.join();110  }111 112  return 0;113}114