From cb2c9ce4e68f8e3aa988b19ebd36516cc76c3c75 Mon Sep 17 00:00:00 2001 From: Jonathan Li Date: Mon, 2 Jan 2017 12:10:06 +0000 Subject: [PATCH] gsdx: Don't use separate count variable It's only ever updated after the queue is updated, so its state will always lag slightly behind it. It's sufficient to just use empty(). This seems to fix some caching issues that were noticeable on Skylake CPUs (#998). --- plugins/GSdx/GSThread_CXX11.h | 60 +++++++++++++---------------------- 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/plugins/GSdx/GSThread_CXX11.h b/plugins/GSdx/GSThread_CXX11.h index bb48ddf41b..a178142092 100644 --- a/plugins/GSdx/GSThread_CXX11.h +++ b/plugins/GSdx/GSThread_CXX11.h @@ -29,7 +29,6 @@ template class GSJobQueue final private: std::thread m_thread; std::function m_func; - std::atomic m_count; std::atomic m_exit; ringbuffer_base m_queue; @@ -43,42 +42,30 @@ private: while (true) { - while (m_count == 0) { + while (m_queue.empty()) { if (m_exit.load(memory_order_relaxed)) return; m_notempty.wait(l); } - int32_t nb = m_count; - l.unlock(); - int32_t consumed = 0; - for (; nb >= 0; nb--) { - if (m_queue.consume_one(*this)) - consumed++; + while (m_queue.consume_one(*this)) + ; + + { + std::lock_guard wait_guard(m_wait_lock); } + m_empty.notify_one(); l.lock(); - - int32_t old_count = m_count.fetch_sub(consumed); - - if (old_count == consumed) { - - { - std::lock_guard wait_guard(m_wait_lock); - } - m_empty.notify_one(); - } - } } public: GSJobQueue(std::function func) : m_func(func), - m_count(0), m_exit(false) { m_thread = std::thread(&GSJobQueue::ThreadProc, this); @@ -95,34 +82,31 @@ public: m_thread.join(); } - bool IsEmpty() const { - ASSERT(m_count >= 0); - - return m_count == 0; + bool IsEmpty() + { + return m_queue.empty(); } void Push(const T& item) { while(!m_queue.push(item)) std::this_thread::yield(); - std::unique_lock l(m_lock); - - m_count++; - - l.unlock(); - + { + std::lock_guard l(m_lock); + } m_notempty.notify_one(); } - void Wait() { - if (m_count > 0) { - std::unique_lock l(m_wait_lock); - while (m_count > 0) { - m_empty.wait(l); - } - } + void Wait() + { + if (IsEmpty()) + return; - ASSERT(m_count == 0); + std::unique_lock l(m_wait_lock); + while (!IsEmpty()) + m_empty.wait(l); + + assert(IsEmpty()); } void operator() (T& item) {