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