mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Tests] Make Mutex.cpp tests more reliable.
Many of these tests would fail if one of the test threads didn't begin execution within 100 milliseconds. They would hit while (!done) the very first time and never execute the loop body. That does happen from time to time, and the result would be a spurious failure. Change the loops to do {} while(!done) to ensure they always execute at least one iteration.
Many tests also had the test threads concurrently write results to a std::vector, which appeared to be causing some failures in my local testing when I had extra sleeps inserted to simulate pathological scheduling. Change the results vectors to be vectors of std::atomic to ensure that this concurrent writing is safe.
These changes shouldn't affect its ability to test the functionality it intends to test.
rdar://problem/49386389
This commit is contained in:
@@ -555,20 +555,21 @@ TEST(StaticReadWriteLockTest, ScopedWriteUnlockThreaded) {
|
||||
template <typename RW> void readLockWhileReadLockedThreaded(RW &lock) {
|
||||
lock.readLock();
|
||||
|
||||
std::vector<bool> results;
|
||||
results.assign(10, false);
|
||||
std::vector<std::atomic<bool>> results(10);
|
||||
|
||||
std::atomic<bool> done(false);
|
||||
threadedExecute(10,
|
||||
[&](int index) {
|
||||
while (!done) {
|
||||
// Always perform at least one iteration of this loop to
|
||||
// avoid spurious failures if this thread is slow to run.
|
||||
do {
|
||||
lock.withReadLock([&] {
|
||||
results[index] = true;
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::milliseconds(5));
|
||||
});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
} while (!done);
|
||||
},
|
||||
[&] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
@@ -577,7 +578,7 @@ template <typename RW> void readLockWhileReadLockedThreaded(RW &lock) {
|
||||
|
||||
lock.readUnlock();
|
||||
|
||||
for (auto result : results) {
|
||||
for (auto &result : results) {
|
||||
ASSERT_TRUE(result);
|
||||
}
|
||||
}
|
||||
@@ -595,20 +596,21 @@ TEST(StaticReadWriteLockTest, ReadLockWhileReadLockedThreaded) {
|
||||
template <typename RW> void readLockWhileWriteLockedThreaded(RW &lock) {
|
||||
lock.writeLock();
|
||||
|
||||
std::vector<int> results;
|
||||
results.assign(10, 0);
|
||||
std::vector<std::atomic<int>> results(10);
|
||||
|
||||
std::atomic<bool> done(false);
|
||||
threadedExecute(10,
|
||||
[&](int index) {
|
||||
while (!done) {
|
||||
// Always perform at least one iteration of this loop to
|
||||
// avoid spurious failures if this thread is slow to run.
|
||||
do {
|
||||
lock.withReadLock([&] {
|
||||
results[index] += 1;
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::milliseconds(5));
|
||||
});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
} while (!done);
|
||||
},
|
||||
[&] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
@@ -616,7 +618,7 @@ template <typename RW> void readLockWhileWriteLockedThreaded(RW &lock) {
|
||||
lock.writeUnlock();
|
||||
});
|
||||
|
||||
for (auto result : results) {
|
||||
for (auto &result : results) {
|
||||
ASSERT_EQ(result, 1);
|
||||
}
|
||||
}
|
||||
@@ -636,20 +638,21 @@ template <typename RW> void writeLockWhileReadLockedThreaded(RW &lock) {
|
||||
|
||||
const int threadCount = 10;
|
||||
|
||||
std::vector<int> results;
|
||||
results.assign(threadCount, 0);
|
||||
std::vector<std::atomic<int>> results(threadCount);
|
||||
|
||||
std::atomic<bool> done(false);
|
||||
threadedExecute(threadCount,
|
||||
[&](int index) {
|
||||
while (!done) {
|
||||
// Always perform at least one iteration of this loop to
|
||||
// avoid spurious failures if this thread is slow to run.
|
||||
do {
|
||||
lock.withWriteLock([&] {
|
||||
results[index] += 1;
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::milliseconds(5));
|
||||
});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
} while (!done);
|
||||
},
|
||||
[&] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
@@ -657,7 +660,7 @@ template <typename RW> void writeLockWhileReadLockedThreaded(RW &lock) {
|
||||
lock.readUnlock();
|
||||
});
|
||||
|
||||
for (auto result : results) {
|
||||
for (auto &result : results) {
|
||||
ASSERT_EQ(result, 1);
|
||||
}
|
||||
}
|
||||
@@ -677,20 +680,21 @@ template <typename RW> void writeLockWhileWriteLockedThreaded(RW &lock) {
|
||||
|
||||
const int threadCount = 10;
|
||||
|
||||
std::vector<int> results;
|
||||
results.assign(threadCount, 0);
|
||||
std::vector<std::atomic<int>> results(threadCount);
|
||||
|
||||
std::atomic<bool> done(false);
|
||||
threadedExecute(threadCount,
|
||||
[&](int index) {
|
||||
while (!done) {
|
||||
// Always perform at least one iteration of this loop to
|
||||
// avoid spurious failures if this thread is slow to run.
|
||||
do {
|
||||
lock.withWriteLock([&] {
|
||||
results[index] += 1;
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::milliseconds(5));
|
||||
});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
} while (!done);
|
||||
},
|
||||
[&] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
@@ -698,7 +702,7 @@ template <typename RW> void writeLockWhileWriteLockedThreaded(RW &lock) {
|
||||
lock.writeUnlock();
|
||||
});
|
||||
|
||||
for (auto result : results) {
|
||||
for (auto &result : results) {
|
||||
ASSERT_EQ(result, 1);
|
||||
}
|
||||
}
|
||||
@@ -719,10 +723,12 @@ template <typename RW> void tryReadLockWhileWriteLockedThreaded(RW &lock) {
|
||||
std::atomic<bool> done(false);
|
||||
threadedExecute(10,
|
||||
[&](int) {
|
||||
while (!done) {
|
||||
// Always perform at least one iteration of this loop to
|
||||
// avoid spurious failures if this thread is slow to run.
|
||||
do {
|
||||
ASSERT_FALSE(lock.try_readLock());
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
} while (!done);
|
||||
},
|
||||
[&] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
@@ -747,19 +753,20 @@ template <typename RW> void tryReadLockWhileReadLockedThreaded(RW &lock) {
|
||||
|
||||
const int threadCount = 10;
|
||||
|
||||
std::vector<bool> results;
|
||||
results.assign(threadCount, false);
|
||||
std::vector<std::atomic<bool>> results(threadCount);
|
||||
|
||||
std::atomic<bool> done(false);
|
||||
threadedExecute(threadCount,
|
||||
[&](int index) {
|
||||
while (!done) {
|
||||
// Always perform at least one iteration of this loop to
|
||||
// avoid spurious failures if this thread is slow to run.
|
||||
do {
|
||||
ASSERT_TRUE(lock.try_readLock());
|
||||
results[index] = true;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
lock.readUnlock();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
} while (!done);
|
||||
},
|
||||
[&] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
@@ -768,7 +775,7 @@ template <typename RW> void tryReadLockWhileReadLockedThreaded(RW &lock) {
|
||||
|
||||
lock.readUnlock();
|
||||
|
||||
for (auto result : results) {
|
||||
for (auto &result : results) {
|
||||
ASSERT_TRUE(result);
|
||||
}
|
||||
}
|
||||
@@ -789,10 +796,12 @@ template <typename RW> void tryWriteLockWhileWriteLockedThreaded(RW &lock) {
|
||||
std::atomic<bool> done(false);
|
||||
threadedExecute(10,
|
||||
[&](int) {
|
||||
while (!done) {
|
||||
// Always perform at least one iteration of this loop to
|
||||
// avoid spurious failures if this thread is slow to run.
|
||||
do {
|
||||
ASSERT_FALSE(lock.try_writeLock());
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
} while (!done);
|
||||
},
|
||||
[&] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
@@ -818,10 +827,12 @@ template <typename RW> void tryWriteLockWhileReadLockedThreaded(RW &lock) {
|
||||
std::atomic<bool> done(false);
|
||||
threadedExecute(10,
|
||||
[&](int) {
|
||||
while (!done) {
|
||||
// Always perform at least one iteration of this loop to
|
||||
// avoid spurious failures if this thread is slow to run.
|
||||
do {
|
||||
ASSERT_FALSE(lock.try_writeLock());
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
} while (!done);
|
||||
},
|
||||
[&] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
Reference in New Issue
Block a user