diff --git a/src/xenia/base/testing/threading_test.cc b/src/xenia/base/testing/threading_test.cc index 37af92c80..5c391b9de 100644 --- a/src/xenia/base/testing/threading_test.cc +++ b/src/xenia/base/testing/threading_test.cc @@ -18,9 +18,56 @@ using namespace threading; using namespace std::chrono_literals; TEST_CASE("Fence") { - // TODO(bwrsandman): - REQUIRE(true); -} + std::unique_ptr pFence; + std::unique_ptr pTimer; + + // Signal without wait + pFence = std::make_unique(); + pFence->Signal(); + + // Signal once and wait + pFence = std::make_unique(); + pFence->Signal(); + pFence->Wait(); + + // Signal twice and wait + pFence = std::make_unique(); + pFence->Signal(); + pFence->Signal(); + pFence->Wait(); + + // Test to synchronize multiple threads + std::atomic started(0); + std::atomic finished(0); + pFence = std::make_unique(); + auto func = [&pFence, &started, &finished] { + started.fetch_add(1); + pFence->Wait(); + finished.fetch_add(1); + }; + + auto threads = std::array({ + 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(); diff --git a/src/xenia/base/threading.h b/src/xenia/base/threading.h index fef37dd06..7c635fcea 100644 --- a/src/xenia/base/threading.h +++ b/src/xenia/base/threading.h @@ -32,21 +32,19 @@ class Fence { Fence() : signaled_(false) {} void Signal() { std::unique_lock lock(mutex_); - signaled_.store(true); + signaled_ = true; cond_.notify_all(); } void Wait() { std::unique_lock 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 signaled_; + bool signaled_; }; // Returns the total number of logical processors in the host system.