1 //===----------------------------------------------------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: no-threads, c++03
11 // <condition_variable>
13 // class condition_variable_any;
15 // template <class Lock, class Predicate>
16 // void wait(Lock& lock, Predicate pred);
18 #include <condition_variable>
24 #include "make_test_thread.h"
25 #include "test_macros.h"
27 template <class Mutex
>
28 struct MyLock
: std::unique_lock
<Mutex
> {
29 using std::unique_lock
<Mutex
>::unique_lock
;
34 using Mutex
= typename
Lock::mutex_type
;
36 // Test unblocking via a call to notify_one() in another thread.
38 // To test this, we try to minimize the likelihood that we got awoken by a
39 // spurious wakeup by updating the likely_spurious flag only immediately
40 // before we perform the notification.
42 std::atomic
<bool> ready(false);
43 std::atomic
<bool> likely_spurious(true);
44 std::condition_variable_any cv
;
47 std::thread t1
= support::make_test_thread([&] {
50 cv
.wait(lock
, [&] { return !likely_spurious
; });
53 std::thread t2
= support::make_test_thread([&] {
58 // Acquire the same mutex as t1. This ensures that the condition variable has started
59 // waiting (and hence released that mutex).
62 likely_spurious
= false;
71 // Test unblocking via a spurious wakeup.
73 // To test this, we basically never wake up the condition variable. This way, we
74 // are hoping to get out of the wait via a spurious wakeup.
76 // However, since spurious wakeups are not required to even happen, this test is
77 // only trying to trigger that code path, but not actually asserting that it is
78 // taken. In particular, we do need to eventually ensure we get out of the wait
79 // by standard means, so we actually wake up the thread at the end.
81 std::atomic
<bool> ready(false);
82 std::atomic
<bool> awoken(false);
83 std::condition_variable_any cv
;
86 std::thread t1
= support::make_test_thread([&] {
89 cv
.wait(lock
, [&] { return true; });
93 std::thread t2
= support::make_test_thread([&] {
98 // Acquire the same mutex as t1. This ensures that the condition variable has started
99 // waiting (and hence released that mutex).
103 // Give some time for t1 to be awoken spuriously so that code path is used.
104 std::this_thread::sleep_for(std::chrono::seconds(1));
106 // We would want to assert that the thread has been awoken after this time,
107 // however nothing guarantees us that it ever gets spuriously awoken, so
108 // we can't really check anything. This is still left here as documentation.
109 bool woke
= awoken
.load();
110 assert(woke
|| !woke
);
112 // Whatever happened, actually awaken the condition variable to ensure the test finishes.
121 int main(int, char**) {
122 test
<std::unique_lock
<std::mutex
>>();
123 test
<std::unique_lock
<std::timed_mutex
>>();
124 test
<MyLock
<std::mutex
>>();
125 test
<MyLock
<std::timed_mutex
>>();