diff --git a/Utilities/SQueue.h b/Utilities/SQueue.h index c6e4f7c01a..4e3b317a9d 100644 --- a/Utilities/SQueue.h +++ b/Utilities/SQueue.h @@ -4,6 +4,8 @@ template class SQueue { std::mutex m_mutex; + NamedThreadBase* push_waiter; + NamedThreadBase* pop_waiter; u32 m_pos; u32 m_count; T m_data[SQSize]; @@ -12,6 +14,8 @@ public: SQueue() : m_pos(0) , m_count(0) + , push_waiter(nullptr) + , pop_waiter(nullptr) { } @@ -22,6 +26,9 @@ public: bool Push(const T& data) { + NamedThreadBase* t = GetCurrentNamedThread(); + push_waiter = t; + while (true) { if (m_count >= SQSize) @@ -30,7 +37,8 @@ public: { return false; } - Sleep(1); + + SM_Sleep(); continue; } @@ -38,9 +46,11 @@ public: std::lock_guard lock(m_mutex); if (m_count >= SQSize) continue; + if (pop_waiter && !m_count) pop_waiter->Notify(); m_data[(m_pos + m_count++) % SQSize] = data; + push_waiter = nullptr; return true; } } @@ -48,6 +58,9 @@ public: bool Pop(T& data) { + NamedThreadBase* t = GetCurrentNamedThread(); + pop_waiter = t; + while (true) { if (!m_count) @@ -56,7 +69,8 @@ public: { return false; } - Sleep(1); + + SM_Sleep(); continue; } @@ -64,22 +78,24 @@ public: std::lock_guard lock(m_mutex); if (!m_count) continue; + if (push_waiter && m_count >= SQSize) push_waiter->Notify(); data = m_data[m_pos]; m_pos = (m_pos + 1) % SQSize; m_count--; + pop_waiter = nullptr; return true; } } } - volatile u32 GetCount() // may be not safe + volatile u32 GetCount() // may be thread unsafe { return m_count; } - volatile bool IsEmpty() // may be not safe + volatile bool IsEmpty() // may be thread unsafe { return !m_count; } @@ -87,11 +103,15 @@ public: void Clear() { std::lock_guard lock(m_mutex); + if (push_waiter && m_count >= SQSize) push_waiter->Notify(); m_count = 0; } T& Peek(u32 pos = 0) { + NamedThreadBase* t = GetCurrentNamedThread(); + pop_waiter = t; + while (true) { if (!m_count) @@ -100,13 +120,18 @@ public: { break; } - Sleep(1); + + SM_Sleep(); continue; } { std::lock_guard lock(m_mutex); - if (m_count) break; + if (m_count) + { + pop_waiter = nullptr; + break; + } } } return m_data[(m_pos + pos) % SQSize];