From 9095dad00900034649d7f3ec78bd5e5558e97fb7 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 6 Mar 2011 00:52:04 +0000 Subject: [PATCH] Fix preprocessor prob.(recursive mutexes were being used where not necessary) Hopefully fix Common::Event to handle spurious wakeups since it uses condition variables now. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7307 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/StdConditionVariable.h | 1 + Source/Core/Common/Src/StdMutex.h | 2 +- Source/Core/Common/Src/Thread.h | 42 +++++++++++++++++-- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Source/Core/Common/Src/StdConditionVariable.h b/Source/Core/Common/Src/StdConditionVariable.h index fddc83bc63..2781872c8f 100644 --- a/Source/Core/Common/Src/StdConditionVariable.h +++ b/Source/Core/Common/Src/StdConditionVariable.h @@ -99,6 +99,7 @@ public: #elif USE_CONDITION_VARIABLES SleepConditionVariableCS(m_handle, lock.mutex()->native_handle(), INFINITE); #else + // TODO: broken, the unlock and wait need to be atomic lock.unlock(); WaitForSingleObject(m_handle, INFINITE); lock.lock(); diff --git a/Source/Core/Common/Src/StdMutex.h b/Source/Core/Common/Src/StdMutex.h index 580917f2e8..5a1bc6a282 100644 --- a/Source/Core/Common/Src/StdMutex.h +++ b/Source/Core/Common/Src/StdMutex.h @@ -106,7 +106,7 @@ private: native_type m_handle; }; -#ifdef USE_SRWLOCKS +#if !defined(_WIN32) || defined(USE_SRWLOCKS) class mutex { diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index cac189c6b0..27d898e63c 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -57,6 +57,7 @@ public: void Set() { + std::lock_guard lk(m_mutex); if (!is_set) { is_set = true; @@ -68,12 +69,28 @@ public: { std::unique_lock lk(m_mutex); if (!is_set) - m_condvar.wait(lk); + m_condvar.wait(lk, IsSet(this)); is_set = false; } private: - bool is_set; + class IsSet + { + public: + IsSet(const Event* ev) + : m_event(ev) + {} + + bool operator()() + { + return m_event->is_set; + } + + private: + const Event* const m_event; + }; + + volatile bool is_set; std::condition_variable m_condvar; std::mutex m_mutex; }; @@ -91,6 +108,9 @@ public: { std::unique_lock lk(m_mutex); + // TODO: broken when next round of Wait()s + // is entered before all waiting threads return from the notify_all + if (m_count == ++m_waiting) { m_waiting = 0; @@ -99,12 +119,28 @@ public: } else { - m_condvar.wait(lk); + m_condvar.wait(lk, IsDoneWating(this)); return false; } } private: + class IsDoneWating + { + public: + IsDoneWating(const Barrier* bar) + : m_bar(bar) + {} + + bool operator()() + { + return (0 == m_bar->m_waiting); + } + + private: + const Barrier* const m_bar; + }; + std::condition_variable m_condvar; std::mutex m_mutex; const size_t m_count;