1 //========- unittests/Support/ThreadPools.cpp - ThreadPools.h tests --========//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/ThreadPool.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SmallVector.h"
13 #include "llvm/ADT/Triple.h"
14 #include "llvm/Support/Host.h"
15 #include "llvm/Support/TargetSelect.h"
17 #include "gtest/gtest.h"
21 // Fixture for the unittests, allowing to *temporarily* disable the unittests
22 // on a particular platform
23 class ThreadPoolTest
: public testing::Test
{
25 SmallVector
<Triple::ArchType
, 4> UnsupportedArchs
;
26 SmallVector
<Triple::OSType
, 4> UnsupportedOSs
;
27 SmallVector
<Triple::EnvironmentType
, 1> UnsupportedEnvironments
;
29 // This is intended for platform as a temporary "XFAIL"
30 bool isUnsupportedOSOrEnvironment() {
31 Triple
Host(Triple::normalize(sys::getProcessTriple()));
33 if (find(UnsupportedEnvironments
, Host
.getEnvironment()) !=
34 UnsupportedEnvironments
.end())
37 if (is_contained(UnsupportedOSs
, Host
.getOS()))
40 if (is_contained(UnsupportedArchs
, Host
.getArch()))
47 // Add unsupported configuration here, example:
48 // UnsupportedArchs.push_back(Triple::x86_64);
50 // See https://llvm.org/bugs/show_bug.cgi?id=25829
51 UnsupportedArchs
.push_back(Triple::ppc64le
);
52 UnsupportedArchs
.push_back(Triple::ppc64
);
55 /// Make sure this thread not progress faster than the main thread.
56 void waitForMainThread() {
57 std::unique_lock
<std::mutex
> LockGuard(WaitMainThreadMutex
);
58 WaitMainThread
.wait(LockGuard
, [&] { return MainThreadReady
; });
61 /// Set the readiness of the main thread.
62 void setMainThreadReady() {
64 std::unique_lock
<std::mutex
> LockGuard(WaitMainThreadMutex
);
65 MainThreadReady
= true;
67 WaitMainThread
.notify_all();
70 void SetUp() override
{ MainThreadReady
= false; }
72 std::condition_variable WaitMainThread
;
73 std::mutex WaitMainThreadMutex
;
78 #define CHECK_UNSUPPORTED() \
80 if (isUnsupportedOSOrEnvironment()) \
84 TEST_F(ThreadPoolTest, AsyncBarrier) {
86 // test that async & barrier work together properly.
88 std::atomic_int checked_in
{0};
91 for (size_t i
= 0; i
< 5; ++i
) {
92 Pool
.async([this, &checked_in
] {
97 ASSERT_EQ(0, checked_in
);
100 ASSERT_EQ(5, checked_in
);
103 static void TestFunc(std::atomic_int
&checked_in
, int i
) { checked_in
+= i
; }
105 TEST_F(ThreadPoolTest
, AsyncBarrierArgs
) {
107 // Test that async works with a function requiring multiple parameters.
108 std::atomic_int checked_in
{0};
111 for (size_t i
= 0; i
< 5; ++i
) {
112 Pool
.async(TestFunc
, std::ref(checked_in
), i
);
115 ASSERT_EQ(10, checked_in
);
118 TEST_F(ThreadPoolTest
, Async
) {
121 std::atomic_int i
{0};
122 Pool
.async([this, &i
] {
126 Pool
.async([&i
] { ++i
; });
127 ASSERT_NE(2, i
.load());
128 setMainThreadReady();
130 ASSERT_EQ(2, i
.load());
133 TEST_F(ThreadPoolTest
, GetFuture
) {
136 std::atomic_int i
{0};
137 Pool
.async([this, &i
] {
141 // Force the future using get()
142 Pool
.async([&i
] { ++i
; }).get();
143 ASSERT_NE(2, i
.load());
144 setMainThreadReady();
146 ASSERT_EQ(2, i
.load());
149 TEST_F(ThreadPoolTest
, PoolDestruction
) {
151 // Test that we are waiting on destruction
152 std::atomic_int checked_in
{0};
155 for (size_t i
= 0; i
< 5; ++i
) {
156 Pool
.async([this, &checked_in
] {
161 ASSERT_EQ(0, checked_in
);
162 setMainThreadReady();
164 ASSERT_EQ(5, checked_in
);