1 //========- unittests/Support/TaskQueue.cpp - TaskQueue.h tests ------========//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/Support/TaskQueue.h"
11 
12 #include "gtest/gtest.h"
13 
14 using namespace llvm;
15 
16 #if LLVM_ENABLE_THREADS
17 class TaskQueueTest : public testing::Test {
18 protected:
19   TaskQueueTest() {}
20 };
21 
22 TEST_F(TaskQueueTest, OrderedFutures) {
23   ThreadPool TP(1);
24   TaskQueue TQ(TP);
25   std::atomic<int> X{ 0 };
26   std::atomic<int> Y{ 0 };
27   std::atomic<int> Z{ 0 };
28 
29   std::mutex M1, M2, M3;
30   std::unique_lock<std::mutex> L1(M1);
31   std::unique_lock<std::mutex> L2(M2);
32   std::unique_lock<std::mutex> L3(M3);
33 
34   std::future<void> F1 = TQ.async([&] {
35     std::unique_lock<std::mutex> Lock(M1);
36     ++X;
37   });
38   std::future<void> F2 = TQ.async([&] {
39     std::unique_lock<std::mutex> Lock(M2);
40     ++Y;
41   });
42   std::future<void> F3 = TQ.async([&] {
43     std::unique_lock<std::mutex> Lock(M3);
44     ++Z;
45   });
46 
47   L1.unlock();
48   F1.wait();
49   ASSERT_EQ(1, X);
50   ASSERT_EQ(0, Y);
51   ASSERT_EQ(0, Z);
52 
53   L2.unlock();
54   F2.wait();
55   ASSERT_EQ(1, X);
56   ASSERT_EQ(1, Y);
57   ASSERT_EQ(0, Z);
58 
59   L3.unlock();
60   F3.wait();
61   ASSERT_EQ(1, X);
62   ASSERT_EQ(1, Y);
63   ASSERT_EQ(1, Z);
64 }
65 
66 TEST_F(TaskQueueTest, UnOrderedFutures) {
67   ThreadPool TP(1);
68   TaskQueue TQ(TP);
69   std::atomic<int> X{ 0 };
70   std::atomic<int> Y{ 0 };
71   std::atomic<int> Z{ 0 };
72   std::mutex M;
73 
74   std::unique_lock<std::mutex> Lock(M);
75 
76   std::future<void> F1 = TQ.async([&] { ++X; });
77   std::future<void> F2 = TQ.async([&] { ++Y; });
78   std::future<void> F3 = TQ.async([&M, &Z] {
79     std::unique_lock<std::mutex> Lock(M);
80     ++Z;
81   });
82 
83   F2.wait();
84   ASSERT_EQ(1, X);
85   ASSERT_EQ(1, Y);
86   ASSERT_EQ(0, Z);
87 
88   Lock.unlock();
89 
90   F3.wait();
91   ASSERT_EQ(1, X);
92   ASSERT_EQ(1, Y);
93   ASSERT_EQ(1, Z);
94 }
95 
96 TEST_F(TaskQueueTest, FutureWithReturnValue) {
97   ThreadPool TP(1);
98   TaskQueue TQ(TP);
99   std::future<std::string> F1 = TQ.async([&] { return std::string("Hello"); });
100   std::future<int> F2 = TQ.async([&] { return 42; });
101 
102   ASSERT_EQ(42, F2.get());
103   ASSERT_EQ("Hello", F1.get());
104 }
105 #endif
106