mirror of https://github.com/PCSX2/pcsx2.git
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).
This commit is contained in:
parent
a583fafa37
commit
cb2c9ce4e6
|
@ -29,7 +29,6 @@ template<class T, int CAPACITY> class GSJobQueue final
|
||||||
private:
|
private:
|
||||||
std::thread m_thread;
|
std::thread m_thread;
|
||||||
std::function<void(T&)> m_func;
|
std::function<void(T&)> m_func;
|
||||||
std::atomic<int32_t> m_count;
|
|
||||||
std::atomic<bool> m_exit;
|
std::atomic<bool> m_exit;
|
||||||
ringbuffer_base<T, CAPACITY> m_queue;
|
ringbuffer_base<T, CAPACITY> m_queue;
|
||||||
|
|
||||||
|
@ -43,42 +42,30 @@ private:
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
while (m_count == 0) {
|
while (m_queue.empty()) {
|
||||||
if (m_exit.load(memory_order_relaxed))
|
if (m_exit.load(memory_order_relaxed))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_notempty.wait(l);
|
m_notempty.wait(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nb = m_count;
|
|
||||||
|
|
||||||
l.unlock();
|
l.unlock();
|
||||||
|
|
||||||
int32_t consumed = 0;
|
while (m_queue.consume_one(*this))
|
||||||
for (; nb >= 0; nb--) {
|
;
|
||||||
if (m_queue.consume_one(*this))
|
|
||||||
consumed++;
|
{
|
||||||
|
std::lock_guard<std::mutex> wait_guard(m_wait_lock);
|
||||||
}
|
}
|
||||||
|
m_empty.notify_one();
|
||||||
|
|
||||||
l.lock();
|
l.lock();
|
||||||
|
|
||||||
int32_t old_count = m_count.fetch_sub(consumed);
|
|
||||||
|
|
||||||
if (old_count == consumed) {
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> wait_guard(m_wait_lock);
|
|
||||||
}
|
|
||||||
m_empty.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GSJobQueue(std::function<void(T&)> func) :
|
GSJobQueue(std::function<void(T&)> func) :
|
||||||
m_func(func),
|
m_func(func),
|
||||||
m_count(0),
|
|
||||||
m_exit(false)
|
m_exit(false)
|
||||||
{
|
{
|
||||||
m_thread = std::thread(&GSJobQueue::ThreadProc, this);
|
m_thread = std::thread(&GSJobQueue::ThreadProc, this);
|
||||||
|
@ -95,34 +82,31 @@ public:
|
||||||
m_thread.join();
|
m_thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEmpty() const {
|
bool IsEmpty()
|
||||||
ASSERT(m_count >= 0);
|
{
|
||||||
|
return m_queue.empty();
|
||||||
return m_count == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Push(const T& item) {
|
void Push(const T& item) {
|
||||||
while(!m_queue.push(item))
|
while(!m_queue.push(item))
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
|
|
||||||
std::unique_lock<std::mutex> l(m_lock);
|
{
|
||||||
|
std::lock_guard<std::mutex> l(m_lock);
|
||||||
m_count++;
|
}
|
||||||
|
|
||||||
l.unlock();
|
|
||||||
|
|
||||||
m_notempty.notify_one();
|
m_notempty.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wait() {
|
void Wait()
|
||||||
if (m_count > 0) {
|
{
|
||||||
std::unique_lock<std::mutex> l(m_wait_lock);
|
if (IsEmpty())
|
||||||
while (m_count > 0) {
|
return;
|
||||||
m_empty.wait(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(m_count == 0);
|
std::unique_lock<std::mutex> l(m_wait_lock);
|
||||||
|
while (!IsEmpty())
|
||||||
|
m_empty.wait(l);
|
||||||
|
|
||||||
|
assert(IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator() (T& item) {
|
void operator() (T& item) {
|
||||||
|
|
Loading…
Reference in New Issue