135169f66SZachary Turner //========- unittests/Support/TaskQueue.cpp - TaskQueue.h tests ------========//
235169f66SZachary Turner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
635169f66SZachary Turner //
735169f66SZachary Turner //===----------------------------------------------------------------------===//
835169f66SZachary Turner 
90d63dbbcSNico Weber #include "llvm/Config/llvm-config.h"
100d63dbbcSNico Weber 
11a7f9e66cSNico Weber #if LLVM_ENABLE_THREADS
12a7f9e66cSNico Weber 
1335169f66SZachary Turner #include "llvm/Support/TaskQueue.h"
1435169f66SZachary Turner 
1535169f66SZachary Turner #include "gtest/gtest.h"
1635169f66SZachary Turner 
1735169f66SZachary Turner using namespace llvm;
1835169f66SZachary Turner 
1935169f66SZachary Turner class TaskQueueTest : public testing::Test {
2035169f66SZachary Turner protected:
TaskQueueTest()2135169f66SZachary Turner   TaskQueueTest() {}
2235169f66SZachary Turner };
2335169f66SZachary Turner 
TEST_F(TaskQueueTest,OrderedFutures)2435169f66SZachary Turner TEST_F(TaskQueueTest, OrderedFutures) {
25*8404aeb5SAlexandre Ganea   ThreadPool TP(hardware_concurrency(1));
2635169f66SZachary Turner   TaskQueue TQ(TP);
27eee66518SZachary Turner   std::atomic<int> X{ 0 };
28eee66518SZachary Turner   std::atomic<int> Y{ 0 };
29eee66518SZachary Turner   std::atomic<int> Z{ 0 };
3035169f66SZachary Turner 
3135169f66SZachary Turner   std::mutex M1, M2, M3;
3235169f66SZachary Turner   std::unique_lock<std::mutex> L1(M1);
3335169f66SZachary Turner   std::unique_lock<std::mutex> L2(M2);
3435169f66SZachary Turner   std::unique_lock<std::mutex> L3(M3);
3535169f66SZachary Turner 
3635169f66SZachary Turner   std::future<void> F1 = TQ.async([&] {
3735169f66SZachary Turner     std::unique_lock<std::mutex> Lock(M1);
3835169f66SZachary Turner     ++X;
3935169f66SZachary Turner   });
4035169f66SZachary Turner   std::future<void> F2 = TQ.async([&] {
4135169f66SZachary Turner     std::unique_lock<std::mutex> Lock(M2);
4235169f66SZachary Turner     ++Y;
4335169f66SZachary Turner   });
4435169f66SZachary Turner   std::future<void> F3 = TQ.async([&] {
4535169f66SZachary Turner     std::unique_lock<std::mutex> Lock(M3);
4635169f66SZachary Turner     ++Z;
4735169f66SZachary Turner   });
4835169f66SZachary Turner 
4935169f66SZachary Turner   L1.unlock();
5035169f66SZachary Turner   F1.wait();
5135169f66SZachary Turner   ASSERT_EQ(1, X);
5235169f66SZachary Turner   ASSERT_EQ(0, Y);
5335169f66SZachary Turner   ASSERT_EQ(0, Z);
5435169f66SZachary Turner 
5535169f66SZachary Turner   L2.unlock();
5635169f66SZachary Turner   F2.wait();
5735169f66SZachary Turner   ASSERT_EQ(1, X);
5835169f66SZachary Turner   ASSERT_EQ(1, Y);
5935169f66SZachary Turner   ASSERT_EQ(0, Z);
6035169f66SZachary Turner 
6135169f66SZachary Turner   L3.unlock();
6235169f66SZachary Turner   F3.wait();
6335169f66SZachary Turner   ASSERT_EQ(1, X);
6435169f66SZachary Turner   ASSERT_EQ(1, Y);
6535169f66SZachary Turner   ASSERT_EQ(1, Z);
6635169f66SZachary Turner }
6735169f66SZachary Turner 
TEST_F(TaskQueueTest,UnOrderedFutures)6835169f66SZachary Turner TEST_F(TaskQueueTest, UnOrderedFutures) {
69*8404aeb5SAlexandre Ganea   ThreadPool TP(hardware_concurrency(1));
7035169f66SZachary Turner   TaskQueue TQ(TP);
71eee66518SZachary Turner   std::atomic<int> X{ 0 };
72eee66518SZachary Turner   std::atomic<int> Y{ 0 };
73eee66518SZachary Turner   std::atomic<int> Z{ 0 };
7435169f66SZachary Turner   std::mutex M;
7535169f66SZachary Turner 
7635169f66SZachary Turner   std::unique_lock<std::mutex> Lock(M);
7735169f66SZachary Turner 
7835169f66SZachary Turner   std::future<void> F1 = TQ.async([&] { ++X; });
7935169f66SZachary Turner   std::future<void> F2 = TQ.async([&] { ++Y; });
8035169f66SZachary Turner   std::future<void> F3 = TQ.async([&M, &Z] {
8135169f66SZachary Turner     std::unique_lock<std::mutex> Lock(M);
8235169f66SZachary Turner     ++Z;
8335169f66SZachary Turner   });
8435169f66SZachary Turner 
8535169f66SZachary Turner   F2.wait();
8635169f66SZachary Turner   ASSERT_EQ(1, X);
8735169f66SZachary Turner   ASSERT_EQ(1, Y);
8835169f66SZachary Turner   ASSERT_EQ(0, Z);
8935169f66SZachary Turner 
9035169f66SZachary Turner   Lock.unlock();
9135169f66SZachary Turner 
9235169f66SZachary Turner   F3.wait();
9335169f66SZachary Turner   ASSERT_EQ(1, X);
9435169f66SZachary Turner   ASSERT_EQ(1, Y);
9535169f66SZachary Turner   ASSERT_EQ(1, Z);
9635169f66SZachary Turner }
9735169f66SZachary Turner 
TEST_F(TaskQueueTest,FutureWithReturnValue)9835169f66SZachary Turner TEST_F(TaskQueueTest, FutureWithReturnValue) {
99*8404aeb5SAlexandre Ganea   ThreadPool TP(hardware_concurrency(1));
10035169f66SZachary Turner   TaskQueue TQ(TP);
10135169f66SZachary Turner   std::future<std::string> F1 = TQ.async([&] { return std::string("Hello"); });
10235169f66SZachary Turner   std::future<int> F2 = TQ.async([&] { return 42; });
10335169f66SZachary Turner 
10435169f66SZachary Turner   ASSERT_EQ(42, F2.get());
10535169f66SZachary Turner   ASSERT_EQ("Hello", F1.get());
10635169f66SZachary Turner }
10735169f66SZachary Turner #endif
108