From 5624b001aedd5e2eb51c61541dd6454675e494dd Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 12 Oct 2019 22:37:52 +0300 Subject: [PATCH] lf_queue: add range-for support (endless loop with waiting) --- Utilities/lockless.h | 58 +++++++++++++++++++++++++++++ rpcs3/Emu/Cell/Modules/cellVdec.cpp | 17 ++++----- 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/Utilities/lockless.h b/Utilities/lockless.h index 7b20b798cd..84064a3110 100644 --- a/Utilities/lockless.h +++ b/Utilities/lockless.h @@ -401,6 +401,64 @@ public: return count; } + + // Iterator that enables direct endless range-for loop: for (auto* ptr : queue) ... + class iterator + { + lf_queue* _this = nullptr; + + lf_queue_slice m_data; + + public: + constexpr iterator() = default; + + explicit iterator(lf_queue* _this) + : _this(_this) + { + m_data = _this->pop_all(); + } + + bool operator !=(const iterator& rhs) const + { + return _this != rhs._this; + } + + T* operator *() const + { + return m_data ? m_data.get() : nullptr; + } + + iterator& operator ++() + { + if (m_data) + { + m_data.pop_front(); + } + + if (!m_data) + { + m_data = _this->pop_all(); + + if (!m_data) + { + _this->wait(); + m_data = _this->pop_all(); + } + } + + return *this; + } + }; + + iterator begin() + { + return iterator{this}; + } + + iterator end() + { + return iterator{}; + } }; // Assignable lock-free thread-safe value of any type (memory-inefficient) diff --git a/rpcs3/Emu/Cell/Modules/cellVdec.cpp b/rpcs3/Emu/Cell/Modules/cellVdec.cpp index ff3ba7202c..3c9e7a9b03 100644 --- a/rpcs3/Emu/Cell/Modules/cellVdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellVdec.cpp @@ -180,15 +180,14 @@ struct vdec_context final { ppu_tid = ppu.id; - for (auto cmds = in_cmd.pop_all(); thread_ctrl::state() != thread_state::aborting; cmds ? cmds.pop_front() : cmds = in_cmd.pop_all()) + // pcmd can be nullptr + for (auto* pcmd : in_cmd) { - if (!cmds) + if (thread_ctrl::state() == thread_state::aborting) { - in_cmd.wait(); - continue; + break; } - - if (std::get_if(&*cmds)) + else if (std::get_if(pcmd)) { avcodec_flush_buffers(ctx); @@ -197,7 +196,7 @@ struct vdec_context final next_dts = 0; cellVdec.trace("Start sequence..."); } - else if (auto* cmd = std::get_if(&*cmds)) + else if (auto* cmd = std::get_if(pcmd)) { AVPacket packet{}; packet.pos = -1; @@ -399,11 +398,11 @@ struct vdec_context final thread_ctrl::wait_for(1000); } } - else if (auto* frc = std::get_if(&*cmds)) + else if (auto* frc = std::get_if(pcmd)) { frc_set = *frc; } - else + else if (std::get_if(pcmd)) { break; }