threads and monitor
This commit is contained in:
108
src/Core/testing/MutexTest.cpp
Normal file
108
src/Core/testing/MutexTest.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "Core/Monitor.h"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
using namespace uLib;
|
||||
|
||||
void TestBasicLock() {
|
||||
std::cout << "Testing basic Mutex Lock/Unlock..." << std::endl;
|
||||
Mutex m;
|
||||
m.Lock();
|
||||
m.Unlock();
|
||||
assert(m.TryLock());
|
||||
m.Unlock();
|
||||
std::cout << " Passed." << std::endl;
|
||||
}
|
||||
|
||||
void TestScopedLock() {
|
||||
std::cout << "Testing Mutex::ScopedLock..." << std::endl;
|
||||
Mutex m;
|
||||
{
|
||||
Mutex::ScopedLock lock(m);
|
||||
assert(!m.TryLock());
|
||||
}
|
||||
assert(m.TryLock());
|
||||
m.Unlock();
|
||||
std::cout << " Passed." << std::endl;
|
||||
}
|
||||
|
||||
void TestTimedLock() {
|
||||
std::cout << "Testing Mutex TryLockFor..." << std::endl;
|
||||
Mutex m;
|
||||
m.Lock();
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
bool locked = m.TryLockFor(100);
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
|
||||
assert(!locked);
|
||||
assert(diff >= 100);
|
||||
m.Unlock();
|
||||
std::cout << " Passed (waited " << diff << "ms)." << std::endl;
|
||||
}
|
||||
|
||||
void TestMacros() {
|
||||
std::cout << "Testing ULIB_STATIC_LOCK and ULIB_MUTEX_LOCK macros..." << std::endl;
|
||||
|
||||
int counter = 0;
|
||||
auto task = [&]() {
|
||||
for(int i=0; i<500; ++i) {
|
||||
ULIB_STATIC_LOCK(-1) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
for(int i=0; i<4; ++i) threads.emplace_back(task);
|
||||
for(auto& t : threads) t.join();
|
||||
|
||||
assert(counter == 2000);
|
||||
|
||||
Mutex m;
|
||||
int counter2 = 0;
|
||||
ULIB_MUTEX_LOCK(m, -1) {
|
||||
counter2++;
|
||||
}
|
||||
assert(counter2 == 1);
|
||||
|
||||
std::cout << " Passed." << std::endl;
|
||||
}
|
||||
|
||||
void TestMonitor() {
|
||||
std::cout << "Testing Monitor pattern..." << std::endl;
|
||||
struct Resource {
|
||||
int value = 0;
|
||||
void increment() { value++; }
|
||||
};
|
||||
|
||||
Monitor<Resource> monitor(new Resource());
|
||||
|
||||
auto task = [&]() {
|
||||
for(int i=0; i<1000; ++i) {
|
||||
monitor.Access([](Resource& r) {
|
||||
r.increment();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
for(int i=0; i<5; ++i) threads.emplace_back(task);
|
||||
for(auto& t : threads) t.join();
|
||||
|
||||
int final_value = monitor.Access([](Resource& r) { return r.value; });
|
||||
assert(final_value == 5000);
|
||||
std::cout << " Passed (final value: " << final_value << ")." << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
TestBasicLock();
|
||||
TestScopedLock();
|
||||
TestTimedLock();
|
||||
TestMacros();
|
||||
TestMonitor();
|
||||
std::cout << "All Mutex and Monitor tests passed!" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user