Skip to content

Commit 9134e65

Browse files
committed
Move Mutex test's threading helpers to a separate header so other tests can use them.
1 parent 2b62570 commit 9134e65

File tree

3 files changed

+137
-118
lines changed

3 files changed

+137
-118
lines changed

unittests/runtime/Concurrent.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information

unittests/runtime/Mutex.cpp

Lines changed: 2 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -16,125 +16,10 @@
1616
#include <chrono>
1717
#include <map>
1818
#include <random>
19-
#include <thread>
2019

21-
using namespace swift;
22-
23-
// When true many of the threaded tests log activity to help triage issues.
24-
static bool trace = false;
25-
26-
template <typename ThreadBody, typename AfterSpinRelease>
27-
void threadedExecute(int threadCount, ThreadBody threadBody,
28-
AfterSpinRelease afterSpinRelease) {
29-
30-
std::vector<std::thread> threads;
31-
32-
// Block the threads we are about to create.
33-
std::atomic<bool> spinWait(true);
34-
std::atomic<int> readyCount(0);
35-
std::atomic<int> activeCount(0);
36-
37-
for (int i = 0; i < threadCount; ++i) {
38-
threads.push_back(std::thread([&, i] {
39-
readyCount++;
40-
41-
while (spinWait) {
42-
std::this_thread::sleep_for(std::chrono::microseconds(10));
43-
}
44-
std::this_thread::sleep_for(std::chrono::milliseconds(1));
45-
46-
activeCount++;
47-
48-
threadBody(i);
49-
}));
50-
}
51-
52-
while (readyCount < threadCount) {
53-
std::this_thread::sleep_for(std::chrono::milliseconds(1));
54-
}
55-
56-
// Allow our threads to fight for the lock.
57-
spinWait = false;
58-
59-
while (activeCount < threadCount) {
60-
std::this_thread::sleep_for(std::chrono::milliseconds(1));
61-
}
62-
63-
afterSpinRelease();
64-
65-
// Wait until all of our threads have finished.
66-
for (auto &thread : threads) {
67-
thread.join();
68-
}
69-
}
70-
71-
template <typename ThreadBody>
72-
void threadedExecute(int threadCount, ThreadBody threadBody) {
73-
threadedExecute(threadCount, threadBody, [] {});
74-
}
75-
76-
template <typename M, typename C, typename ConsumerBody, typename ProducerBody>
77-
void threadedExecute(M &mutex, C &condition, bool &doneCondition,
78-
ConsumerBody consumerBody, ProducerBody producerBody) {
79-
80-
std::vector<std::thread> producers;
81-
std::vector<std::thread> consumers;
20+
#include "ThreadingHelpers.h"
8221

83-
// Block the threads we are about to create.
84-
std::atomic<bool> spinWait(true);
85-
86-
for (int i = 1; i <= 8; ++i) {
87-
consumers.push_back(std::thread([&, i] {
88-
while (spinWait) {
89-
std::this_thread::sleep_for(std::chrono::microseconds(10));
90-
}
91-
std::this_thread::sleep_for(std::chrono::milliseconds(1));
92-
93-
consumerBody(i);
94-
95-
if (trace)
96-
printf("### Consumer[%d] thread exiting.\n", i);
97-
}));
98-
}
99-
100-
for (int i = 1; i <= 5; ++i) {
101-
producers.push_back(std::thread([&, i] {
102-
while (spinWait) {
103-
std::this_thread::sleep_for(std::chrono::microseconds(10));
104-
}
105-
std::this_thread::sleep_for(std::chrono::milliseconds(1));
106-
107-
producerBody(i);
108-
109-
if (trace)
110-
printf("### Producer[%d] thread exiting.\n", i);
111-
}));
112-
}
113-
114-
// Poor mans attempt to get as many threads ready as possible before
115-
// dropping spinWait, it doesn't have to be perfect.
116-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
117-
118-
// Allow our threads to fight for the lock.
119-
spinWait = false;
120-
121-
// Wait until all of our producer threads have finished.
122-
for (auto &thread : producers) {
123-
thread.join();
124-
}
125-
126-
// Inform consumers that producers are done.
127-
mutex.withLockThenNotifyAll(condition, [&] {
128-
if (trace)
129-
printf("### Informing consumers we are done.\n");
130-
doneCondition = true;
131-
});
132-
133-
// Wait for consumers to finish.
134-
for (auto &thread : consumers) {
135-
thread.join();
136-
}
137-
}
22+
using namespace swift;
13823

13924
// -----------------------------------------------------------------------------
14025

unittests/runtime/ThreadingHelpers.h

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
//===--- Concurrent.cpp - Concurrent data structure tests -----------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef THREADING_HELPERS_H
14+
#define THREADING_HELPERS_H
15+
16+
#include <thread>
17+
18+
// When true many of the threaded tests log activity to help triage issues.
19+
static bool trace = false;
20+
21+
template <typename ThreadBody, typename AfterSpinRelease>
22+
void threadedExecute(int threadCount, ThreadBody threadBody,
23+
AfterSpinRelease afterSpinRelease) {
24+
25+
std::vector<std::thread> threads;
26+
27+
// Block the threads we are about to create.
28+
std::atomic<bool> spinWait(true);
29+
std::atomic<int> readyCount(0);
30+
std::atomic<int> activeCount(0);
31+
32+
for (int i = 0; i < threadCount; ++i) {
33+
threads.push_back(std::thread([&, i] {
34+
readyCount++;
35+
36+
while (spinWait) {
37+
std::this_thread::sleep_for(std::chrono::microseconds(10));
38+
}
39+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
40+
41+
activeCount++;
42+
43+
threadBody(i);
44+
}));
45+
}
46+
47+
while (readyCount < threadCount) {
48+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
49+
}
50+
51+
// Allow our threads to fight for the lock.
52+
spinWait = false;
53+
54+
while (activeCount < threadCount) {
55+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
56+
}
57+
58+
afterSpinRelease();
59+
60+
// Wait until all of our threads have finished.
61+
for (auto &thread : threads) {
62+
thread.join();
63+
}
64+
}
65+
66+
template <typename ThreadBody>
67+
void threadedExecute(int threadCount, ThreadBody threadBody) {
68+
threadedExecute(threadCount, threadBody, [] {});
69+
}
70+
71+
template <typename M, typename C, typename ConsumerBody, typename ProducerBody>
72+
void threadedExecute(M &mutex, C &condition, bool &doneCondition,
73+
ConsumerBody consumerBody, ProducerBody producerBody) {
74+
75+
std::vector<std::thread> producers;
76+
std::vector<std::thread> consumers;
77+
78+
// Block the threads we are about to create.
79+
std::atomic<bool> spinWait(true);
80+
81+
for (int i = 1; i <= 8; ++i) {
82+
consumers.push_back(std::thread([&, i] {
83+
while (spinWait) {
84+
std::this_thread::sleep_for(std::chrono::microseconds(10));
85+
}
86+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
87+
88+
consumerBody(i);
89+
90+
if (trace)
91+
printf("### Consumer[%d] thread exiting.\n", i);
92+
}));
93+
}
94+
95+
for (int i = 1; i <= 5; ++i) {
96+
producers.push_back(std::thread([&, i] {
97+
while (spinWait) {
98+
std::this_thread::sleep_for(std::chrono::microseconds(10));
99+
}
100+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
101+
102+
producerBody(i);
103+
104+
if (trace)
105+
printf("### Producer[%d] thread exiting.\n", i);
106+
}));
107+
}
108+
109+
// Poor mans attempt to get as many threads ready as possible before
110+
// dropping spinWait, it doesn't have to be perfect.
111+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
112+
113+
// Allow our threads to fight for the lock.
114+
spinWait = false;
115+
116+
// Wait until all of our producer threads have finished.
117+
for (auto &thread : producers) {
118+
thread.join();
119+
}
120+
121+
// Inform consumers that producers are done.
122+
mutex.withLockThenNotifyAll(condition, [&] {
123+
if (trace)
124+
printf("### Informing consumers we are done.\n");
125+
doneCondition = true;
126+
});
127+
128+
// Wait for consumers to finish.
129+
for (auto &thread : consumers) {
130+
thread.join();
131+
}
132+
}
133+
134+
#endif

0 commit comments

Comments
 (0)