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