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