15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier //
95a83710eSEric Fiselier // UNSUPPORTED: libcpp-has-no-threads
105a83710eSEric Fiselier 
115a83710eSEric Fiselier // <condition_variable>
125a83710eSEric Fiselier 
135a83710eSEric Fiselier // class condition_variable;
145a83710eSEric Fiselier 
155a83710eSEric Fiselier // void notify_one();
165a83710eSEric Fiselier 
175a83710eSEric Fiselier #include <condition_variable>
1892499e45SEric Fiselier #include <atomic>
195a83710eSEric Fiselier #include <mutex>
205a83710eSEric Fiselier #include <thread>
215a83710eSEric Fiselier #include <cassert>
225a83710eSEric Fiselier 
237fc6a556SMarshall Clow #include "test_macros.h"
247fc6a556SMarshall Clow 
2510967a6eSEric Fiselier 
265a83710eSEric Fiselier std::condition_variable cv;
275a83710eSEric Fiselier std::mutex mut;
285a83710eSEric Fiselier 
2992499e45SEric Fiselier std::atomic_int test1(0);
3092499e45SEric Fiselier std::atomic_int test2(0);
31*1c4238e7SDavid Zarzycki std::atomic_int ready(2);
32*1c4238e7SDavid Zarzycki std::atomic_int which(0);
335a83710eSEric Fiselier 
345a83710eSEric Fiselier void f1()
355a83710eSEric Fiselier {
36*1c4238e7SDavid Zarzycki   --ready;
375a83710eSEric Fiselier   std::unique_lock<std::mutex> lk(mut);
385a83710eSEric Fiselier   assert(test1 == 0);
395a83710eSEric Fiselier   while (test1 == 0)
405a83710eSEric Fiselier     cv.wait(lk);
41*1c4238e7SDavid Zarzycki   which = 1;
425a83710eSEric Fiselier   assert(test1 == 1);
435a83710eSEric Fiselier   test1 = 2;
445a83710eSEric Fiselier }
455a83710eSEric Fiselier 
465a83710eSEric Fiselier void f2()
475a83710eSEric Fiselier {
48*1c4238e7SDavid Zarzycki   --ready;
495a83710eSEric Fiselier   std::unique_lock<std::mutex> lk(mut);
505a83710eSEric Fiselier   assert(test2 == 0);
515a83710eSEric Fiselier   while (test2 == 0)
525a83710eSEric Fiselier     cv.wait(lk);
53*1c4238e7SDavid Zarzycki   which = 2;
545a83710eSEric Fiselier   assert(test2 == 1);
555a83710eSEric Fiselier   test2 = 2;
565a83710eSEric Fiselier }
575a83710eSEric Fiselier 
582df59c50SJF Bastien int main(int, char**)
595a83710eSEric Fiselier {
605a83710eSEric Fiselier   std::thread t1(f1);
615a83710eSEric Fiselier   std::thread t2(f2);
62*1c4238e7SDavid Zarzycki   while (ready > 0)
63*1c4238e7SDavid Zarzycki     std::this_thread::yield();
64*1c4238e7SDavid Zarzycki   // In case the threads were preempted right after the atomic decrement but
65*1c4238e7SDavid Zarzycki   // before cv.wait(), we yield one more time.
66*1c4238e7SDavid Zarzycki   std::this_thread::yield();
675a83710eSEric Fiselier   {
685a83710eSEric Fiselier     std::unique_lock<std::mutex>lk(mut);
695a83710eSEric Fiselier     test1 = 1;
705a83710eSEric Fiselier     test2 = 1;
71*1c4238e7SDavid Zarzycki     ready = 1;
725a83710eSEric Fiselier   }
735a83710eSEric Fiselier   cv.notify_one();
745a83710eSEric Fiselier   {
75*1c4238e7SDavid Zarzycki     while (which == 0)
76*1c4238e7SDavid Zarzycki       std::this_thread::yield();
775a83710eSEric Fiselier     std::unique_lock<std::mutex>lk(mut);
785a83710eSEric Fiselier   }
79*1c4238e7SDavid Zarzycki   if (test1 == 2) {
8010967a6eSEric Fiselier     assert(test2 == 1);
815a83710eSEric Fiselier     t1.join();
825a83710eSEric Fiselier     test1 = 0;
83*1c4238e7SDavid Zarzycki   } else {
8410967a6eSEric Fiselier     assert(test1 == 1);
85*1c4238e7SDavid Zarzycki     assert(test2 == 2);
865a83710eSEric Fiselier     t2.join();
875a83710eSEric Fiselier     test2 = 0;
885a83710eSEric Fiselier   }
89*1c4238e7SDavid Zarzycki   which = 0;
905a83710eSEric Fiselier   cv.notify_one();
915a83710eSEric Fiselier   {
92*1c4238e7SDavid Zarzycki     while (which == 0)
93*1c4238e7SDavid Zarzycki       std::this_thread::yield();
945a83710eSEric Fiselier     std::unique_lock<std::mutex>lk(mut);
955a83710eSEric Fiselier   }
96*1c4238e7SDavid Zarzycki   if (test1 == 2) {
9710967a6eSEric Fiselier     assert(test2 == 0);
985a83710eSEric Fiselier     t1.join();
995a83710eSEric Fiselier     test1 = 0;
100*1c4238e7SDavid Zarzycki   } else {
10110967a6eSEric Fiselier     assert(test1 == 0);
102*1c4238e7SDavid Zarzycki     assert(test2 == 2);
1035a83710eSEric Fiselier     t2.join();
1045a83710eSEric Fiselier     test2 = 0;
1055a83710eSEric Fiselier   }
1062df59c50SJF Bastien 
1072df59c50SJF Bastien   return 0;
1085a83710eSEric Fiselier }
109