mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Unittests] Add more threading library tests.
Added explicit tests for `swift::once` and also for the ulock implementation used on Linux. rdar://90776105
This commit is contained in:
@@ -17,28 +17,50 @@
|
||||
#include <map>
|
||||
#include <random>
|
||||
|
||||
#include "ThreadingHelpers.h"
|
||||
#include "LockingHelpers.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <typename M> void basicLockableThreaded(M &mutex) {
|
||||
int count1 = 0;
|
||||
int count2 = 0;
|
||||
TEST(MutexTest, BasicLockable) {
|
||||
Mutex mutex(/* checked = */ true);
|
||||
basicLockable(mutex);
|
||||
}
|
||||
|
||||
threadedExecute(10, [&](int) {
|
||||
for (int j = 0; j < 50; ++j) {
|
||||
mutex.lock();
|
||||
auto count = count2;
|
||||
count1++;
|
||||
count2 = count + 1;
|
||||
mutex.unlock();
|
||||
}
|
||||
});
|
||||
TEST(LazyMutexTest, BasicLockable) {
|
||||
static LazyMutex mutex;
|
||||
basicLockable(mutex);
|
||||
}
|
||||
|
||||
ASSERT_EQ(count1, 500);
|
||||
ASSERT_EQ(count2, 500);
|
||||
TEST(LazyUnsafeMutexTest, BasicLockable) {
|
||||
static LazyUnsafeMutex mutex;
|
||||
basicLockable(mutex);
|
||||
}
|
||||
|
||||
TEST(SmallMutex, BasicLockable) {
|
||||
SmallMutex mutex;
|
||||
basicLockable(mutex);
|
||||
}
|
||||
|
||||
TEST(MutexTest, TryLockable) {
|
||||
Mutex mutex(/* checked = */ true);
|
||||
tryLockable(mutex);
|
||||
}
|
||||
|
||||
TEST(LazyMutexTest, TryLockable) {
|
||||
static LazyMutex mutex;
|
||||
tryLockable(mutex);
|
||||
}
|
||||
|
||||
TEST(LazyUnsafeMutexTest, TryLockable) {
|
||||
static LazyUnsafeMutex mutex;
|
||||
tryLockable(mutex);
|
||||
}
|
||||
|
||||
TEST(SmallMutex, TryLockable) {
|
||||
SmallMutex mutex;
|
||||
tryLockable(mutex);
|
||||
}
|
||||
|
||||
TEST(MutexTest, BasicLockableThreaded) {
|
||||
@@ -61,34 +83,6 @@ TEST(SmallMutex, BasicLockableThreaded) {
|
||||
basicLockableThreaded(mutex);
|
||||
}
|
||||
|
||||
template <typename M> void lockableThreaded(M &mutex) {
|
||||
mutex.lock();
|
||||
threadedExecute(5, [&](int) { ASSERT_FALSE(mutex.try_lock()); });
|
||||
mutex.unlock();
|
||||
threadedExecute(1, [&](int) {
|
||||
ASSERT_TRUE(mutex.try_lock());
|
||||
mutex.unlock();
|
||||
});
|
||||
|
||||
int count1 = 0;
|
||||
int count2 = 0;
|
||||
threadedExecute(10, [&](int) {
|
||||
for (int j = 0; j < 50; ++j) {
|
||||
if (mutex.try_lock()) {
|
||||
auto count = count2;
|
||||
count1++;
|
||||
count2 = count + 1;
|
||||
mutex.unlock();
|
||||
} else {
|
||||
j--;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ASSERT_EQ(count1, 500);
|
||||
ASSERT_EQ(count2, 500);
|
||||
}
|
||||
|
||||
TEST(MutexTest, LockableThreaded) {
|
||||
Mutex mutex(/* checked = */ true);
|
||||
lockableThreaded(mutex);
|
||||
@@ -104,23 +98,6 @@ TEST(SmallMutexTest, LockableThreaded) {
|
||||
lockableThreaded(Mutex);
|
||||
}
|
||||
|
||||
template <typename SL, typename M> void scopedLockThreaded(M &mutex) {
|
||||
int count1 = 0;
|
||||
int count2 = 0;
|
||||
|
||||
threadedExecute(10, [&](int) {
|
||||
for (int j = 0; j < 50; ++j) {
|
||||
SL guard(mutex);
|
||||
auto count = count2;
|
||||
count1++;
|
||||
count2 = count + 1;
|
||||
}
|
||||
});
|
||||
|
||||
ASSERT_EQ(count1, 500);
|
||||
ASSERT_EQ(count2, 500);
|
||||
}
|
||||
|
||||
TEST(MutexTest, ScopedLockThreaded) {
|
||||
Mutex mutex(/* checked = */ true);
|
||||
scopedLockThreaded<Mutex::ScopedLock>(mutex);
|
||||
@@ -136,29 +113,6 @@ TEST(SmallMutexTest, ScopedLockThreaded) {
|
||||
scopedLockThreaded<ScopedLockT<SmallMutex, false>>(mutex);
|
||||
}
|
||||
|
||||
template <typename SL, typename SU, typename M>
|
||||
void scopedUnlockUnderScopedLockThreaded(M &mutex) {
|
||||
int count1 = 0;
|
||||
int count2 = 0;
|
||||
int badCount = 0;
|
||||
|
||||
threadedExecute(10, [&](int) {
|
||||
for (int j = 0; j < 50; ++j) {
|
||||
SL guard(mutex);
|
||||
{
|
||||
SU unguard(mutex);
|
||||
badCount++;
|
||||
}
|
||||
auto count = count2;
|
||||
count1++;
|
||||
count2 = count + 1;
|
||||
}
|
||||
});
|
||||
|
||||
ASSERT_EQ(count1, 500);
|
||||
ASSERT_EQ(count2, 500);
|
||||
}
|
||||
|
||||
TEST(MutexTest, ScopedUnlockUnderScopedLockThreaded) {
|
||||
Mutex mutex(/* checked = */ true);
|
||||
scopedUnlockUnderScopedLockThreaded<Mutex::ScopedLock, Mutex::ScopedUnlock>(
|
||||
@@ -177,24 +131,6 @@ TEST(SmallMutexTest, ScopedUnlockUnderScopedLockThreaded) {
|
||||
SmallMutex::ScopedUnlock>(mutex);
|
||||
}
|
||||
|
||||
template <typename M> void criticalSectionThreaded(M &mutex) {
|
||||
int count1 = 0;
|
||||
int count2 = 0;
|
||||
|
||||
threadedExecute(10, [&](int) {
|
||||
for (int j = 0; j < 50; ++j) {
|
||||
mutex.withLock([&] {
|
||||
auto count = count2;
|
||||
count1++;
|
||||
count2 = count + 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
ASSERT_EQ(count1, 500);
|
||||
ASSERT_EQ(count2, 500);
|
||||
}
|
||||
|
||||
TEST(MutexTest, CriticalSectionThreaded) {
|
||||
Mutex mutex(/* checked = */ true);
|
||||
criticalSectionThreaded(mutex);
|
||||
@@ -204,53 +140,3 @@ TEST(LazyMutexTest, CriticalSectionThreaded) {
|
||||
static LazyMutex Mutex;
|
||||
criticalSectionThreaded(Mutex);
|
||||
}
|
||||
|
||||
template <typename SRL, bool Locking, typename RW>
|
||||
void scopedReadThreaded(RW &lock) {
|
||||
const int threadCount = 10;
|
||||
|
||||
std::set<int> writerHistory;
|
||||
std::vector<std::set<int>> readerHistory;
|
||||
readerHistory.assign(threadCount, std::set<int>());
|
||||
|
||||
int protectedValue = 0;
|
||||
writerHistory.insert(protectedValue);
|
||||
|
||||
threadedExecute(threadCount,
|
||||
[&](int index) {
|
||||
if (Locking) {
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
{
|
||||
SRL guard(lock);
|
||||
readerHistory[index].insert(protectedValue);
|
||||
}
|
||||
std::this_thread::yield();
|
||||
}
|
||||
} else {
|
||||
lock.readLock();
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
readerHistory[index].insert(protectedValue);
|
||||
|
||||
{
|
||||
SRL unguard(lock);
|
||||
std::this_thread::yield();
|
||||
}
|
||||
}
|
||||
lock.readUnlock();
|
||||
}
|
||||
},
|
||||
[&] {
|
||||
for (int i = 0; i < 25; ++i) {
|
||||
lock.writeLock();
|
||||
protectedValue += i;
|
||||
writerHistory.insert(protectedValue);
|
||||
lock.writeUnlock();
|
||||
}
|
||||
});
|
||||
|
||||
for (auto &history : readerHistory) {
|
||||
for (auto value : history) {
|
||||
ASSERT_EQ(writerHistory.count(value), 1U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user