[threading] Simplify and test Fence

Remove atomic boolean in fence. Variable signaled_ is already protected
by mutex.
Remove wait loop with single predicate wait protected with mutex.

Add Fence Signal and Wait tests
Test signaling without waiting.
Test signaling before waiting.
Test signaling twice before waiting.
Test synchronizing threads with fence.

Few REQUIRES were used to test as there are no return codes.
A failing test may hang indefinitely or cause a segfault which would still
register as a fail.
This commit is contained in:
Sandy Carter 2018-03-11 16:22:53 -04:00 committed by Rick Gibbed
parent b5ea686475
commit 4280a6451d
2 changed files with 54 additions and 9 deletions

View File

@ -18,9 +18,56 @@ using namespace threading;
using namespace std::chrono_literals;
TEST_CASE("Fence") {
// TODO(bwrsandman):
REQUIRE(true);
}
std::unique_ptr<threading::Fence> pFence;
std::unique_ptr<threading::HighResolutionTimer> pTimer;
// Signal without wait
pFence = std::make_unique<threading::Fence>();
pFence->Signal();
// Signal once and wait
pFence = std::make_unique<threading::Fence>();
pFence->Signal();
pFence->Wait();
// Signal twice and wait
pFence = std::make_unique<threading::Fence>();
pFence->Signal();
pFence->Signal();
pFence->Wait();
// Test to synchronize multiple threads
std::atomic<int> started(0);
std::atomic<int> finished(0);
pFence = std::make_unique<threading::Fence>();
auto func = [&pFence, &started, &finished] {
started.fetch_add(1);
pFence->Wait();
finished.fetch_add(1);
};
auto threads = std::array<std::thread, 5>({
std::thread(func),
std::thread(func),
std::thread(func),
std::thread(func),
std::thread(func),
});
Sleep(100ms);
REQUIRE(finished.load() == 0);
// TODO(bwrsandman): Check if this is correct behaviour: looping with Sleep
// is the only way to get fence to signal all threads on windows
for (int i = 0; i < threads.size(); ++i) {
Sleep(10ms);
pFence->Signal();
}
REQUIRE(started.load() == threads.size());
for (auto& t : threads) t.join();
REQUIRE(finished.load() == threads.size());
} // namespace test
TEST_CASE("Get number of logical processors") {
auto count = std::thread::hardware_concurrency();

View File

@ -32,21 +32,19 @@ class Fence {
Fence() : signaled_(false) {}
void Signal() {
std::unique_lock<std::mutex> lock(mutex_);
signaled_.store(true);
signaled_ = true;
cond_.notify_all();
}
void Wait() {
std::unique_lock<std::mutex> lock(mutex_);
while (!signaled_.load()) {
cond_.wait(lock);
}
signaled_.store(false);
cond_.wait(lock, [this] { return signaled_; });
signaled_ = false;
}
private:
std::mutex mutex_;
std::condition_variable cond_;
std::atomic<bool> signaled_;
bool signaled_;
};
// Returns the total number of logical processors in the host system.