Skip to content

Commit 032d053

Browse files
authored
Merge pull request #7797 from bitjammer/rdar-30729901-link-pthread-linux-unittests
[Syntax] ThreadSafeCachingTests: Use a thread pool
2 parents 860252f + 45a7320 commit 032d053

File tree

1 file changed

+70
-17
lines changed

1 file changed

+70
-17
lines changed

unittests/Syntax/ThreadSafeCachingTests.cpp

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,78 @@
44
#include "llvm/ADT/SmallString.h"
55
#include "gtest/gtest.h"
66

7+
#include <future>
78
#include <thread>
9+
#include <queue>
810

911
using namespace swift;
1012
using namespace swift::syntax;
1113

12-
static void getExpressionFrom(ReturnStmtSyntax Return,
13-
uintptr_t *DataPointer) {
14+
static uintptr_t getExpressionFrom(ReturnStmtSyntax Return) {
1415
auto Expression = Return.getExpression().getValue();
15-
auto Data = Expression.getDataPointer();
16-
*DataPointer = reinterpret_cast<uintptr_t>(Data);
16+
return reinterpret_cast<uintptr_t>(Expression.getDataPointer());
1717
}
1818

19+
class Pool {
20+
static constexpr size_t NumThreads = 2;
21+
using FuncTy = std::function<uintptr_t(ReturnStmtSyntax)>;
22+
std::vector<std::thread> Workers;
23+
std::queue<std::function<void()>> Tasks;
24+
std::mutex QueueLock;
25+
std::condition_variable Condition;
26+
bool Stop;
27+
28+
public:
29+
Pool() : Stop(false) {
30+
for(size_t i = 0; i < NumThreads; ++i)
31+
Workers.emplace_back([this] {
32+
while (true) {
33+
std::function<void()> Task;
34+
{
35+
std::unique_lock<std::mutex> L(QueueLock);
36+
37+
Condition.wait(L, [this]{
38+
return Stop || !Tasks.empty();
39+
});
40+
41+
if(Stop && Tasks.empty()) {
42+
return;
43+
}
44+
45+
Task = std::move(Tasks.front());
46+
Tasks.pop();
47+
}
48+
49+
Task();
50+
}
51+
});
52+
}
53+
54+
std::future<uintptr_t> run(FuncTy Func, ReturnStmtSyntax Return) {
55+
auto Task = std::make_shared<std::packaged_task<uintptr_t()>>(
56+
std::bind(Func, Return));
57+
58+
auto Future = Task->get_future();
59+
{
60+
std::unique_lock<std::mutex> L(QueueLock);
61+
Tasks.emplace([Task](){ (*Task)(); });
62+
}
63+
Condition.notify_one();
64+
return Future;
65+
}
66+
67+
~Pool() {
68+
{
69+
std::lock_guard<std::mutex> L(QueueLock);
70+
Stop = true;
71+
}
72+
Condition.notify_all();
73+
for(auto &Worker : Workers) {
74+
Worker.join();
75+
}
76+
}
77+
};
78+
1979
// Tests that, when multiple threads ask for a child node of the same syntax
2080
// node:
2181
// - Only one thread inserts the realized child into the parent
@@ -27,29 +87,22 @@ TEST(ThreadSafeCachingTests, ReturnGetExpression) {
2787
auto One = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
2888
auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, One);
2989

90+
Pool P;
91+
3092
for (unsigned i = 0; i < 10000; ++i) {
31-
llvm::SmallString<48> Scratch;
32-
llvm::raw_svector_ostream OS(Scratch);
3393
auto Return = SyntaxFactory::makeReturnStmt(ReturnKW, MinusOne);
3494

35-
uintptr_t FirstDataPointer;
36-
uintptr_t SecondDataPointer;
95+
auto Future1 = P.run(getExpressionFrom, Return);
96+
auto Future2 = P.run(getExpressionFrom, Return);
3797

38-
std::thread first(getExpressionFrom, Return, &FirstDataPointer);
39-
std::thread second(getExpressionFrom, Return, &SecondDataPointer);
40-
first.join();
41-
second.join();
98+
auto FirstDataPointer = Future1.get();
99+
auto SecondDataPointer = Future2.get();
42100

43101
auto DataPointer = reinterpret_cast<uintptr_t>(
44102
Return.getExpression().getValue().getDataPointer());
45103

46104
ASSERT_EQ(FirstDataPointer, SecondDataPointer);
47105
ASSERT_EQ(FirstDataPointer, DataPointer);
48-
49-
if (FirstDataPointer != SecondDataPointer ||
50-
FirstDataPointer != DataPointer) {
51-
break;
52-
}
53106
}
54107
#endif
55108
}

0 commit comments

Comments
 (0)