diff --git a/repertory/librepertory/include/file_manager/ring_file_base.hpp b/repertory/librepertory/include/file_manager/ring_file_base.hpp index 5ad9e80d..270714d2 100644 --- a/repertory/librepertory/include/file_manager/ring_file_base.hpp +++ b/repertory/librepertory/include/file_manager/ring_file_base.hpp @@ -69,6 +69,8 @@ private: void reader_thread(); + void update_position(std::size_t count, bool is_forward); + protected: [[nodiscard]] auto get_read_state_size() const -> std::size_t; diff --git a/repertory/librepertory/src/file_manager/ring_file_base.cpp b/repertory/librepertory/src/file_manager/ring_file_base.cpp index 137bb4c5..aa108550 100644 --- a/repertory/librepertory/src/file_manager/ring_file_base.cpp +++ b/repertory/librepertory/src/file_manager/ring_file_base.cpp @@ -183,32 +183,7 @@ auto ring_file_base::download_chunk(std::size_t chunk, } void ring_file_base::forward(std::size_t count) { - mutex_lock chunk_lock(chunk_mtx_); - if ((ring_pos_ + count) > (total_chunks_ - 1U)) { - count = (total_chunks_ - 1U) - ring_pos_; - } - - if ((ring_pos_ + count) <= ring_end_) { - ring_pos_ += count; - } else { - auto added = count - (ring_end_ - ring_pos_); - if (added >= ring_state_.size()) { - ring_state_.set(0U, ring_state_.size(), false); - ring_pos_ += count; - ring_begin_ += added; - } else { - for (std::size_t idx = 0U; idx < added; ++idx) { - ring_state_[(ring_begin_ + idx) % ring_state_.size()] = false; - } - ring_begin_ += added; - ring_pos_ += count; - } - - ring_end_ = - std::min(total_chunks_ - 1U, ring_begin_ + ring_state_.size() - 1U); - } - - chunk_notify_.notify_all(); + update_position(count, true); } auto ring_file_base::get_read_state() const -> boost::dynamic_bitset<> { @@ -347,30 +322,7 @@ void ring_file_base::reader_thread() { } void ring_file_base::reverse(std::size_t count) { - mutex_lock chunk_lock(chunk_mtx_); - count = std::min(ring_pos_, count); - - if ((ring_pos_ - count) >= ring_begin_) { - ring_pos_ -= count; - } else { - auto removed = count - (ring_pos_ - ring_begin_); - if (removed >= ring_state_.size()) { - ring_state_.set(0U, ring_state_.size(), false); - ring_pos_ -= count; - ring_begin_ = ring_pos_; - } else { - for (std::size_t idx = 0U; idx < removed; ++idx) { - ring_state_[(ring_end_ - idx) % ring_state_.size()] = false; - } - ring_begin_ -= removed; - ring_pos_ -= count; - } - - ring_end_ = - std::min(total_chunks_ - 1U, ring_begin_ + ring_state_.size() - 1U); - } - - chunk_notify_.notify_all(); + update_position(count, false); } void ring_file_base::set(std::size_t first_chunk, std::size_t current_chunk) { @@ -401,4 +353,46 @@ void ring_file_base::set_api_path(const std::string &api_path) { open_file_base::set_api_path(api_path); chunk_notify_.notify_all(); } + +void ring_file_base::update_position(std::size_t count, bool is_forward) { + mutex_lock chunk_lock(chunk_mtx_); + + if (is_forward) { + if ((ring_pos_ + count) > (total_chunks_ - 1U)) { + count = (total_chunks_ - 1U) - ring_pos_; + } + } else { + count = std::min(ring_pos_, count); + } + + if (is_forward ? (ring_pos_ + count) <= ring_end_ + : (ring_pos_ - count) >= ring_begin_) { + ring_pos_ += is_forward ? count : -count; + } else { + auto delta = is_forward ? count - (ring_end_ - ring_pos_) + : count - (ring_pos_ - ring_begin_); + + if (delta >= ring_state_.size()) { + ring_state_.set(0U, ring_state_.size(), false); + ring_pos_ += is_forward ? count : -count; + ring_begin_ += is_forward ? delta : -delta; + } else { + for (std::size_t idx = 0U; idx < delta; ++idx) { + if (is_forward) { + ring_state_[(ring_begin_ + idx) % ring_state_.size()] = false; + } else { + ring_state_[(ring_end_ - idx) % ring_state_.size()] = false; + } + } + + ring_begin_ += is_forward ? delta : -delta; + ring_pos_ += is_forward ? count : -count; + } + + ring_end_ = + std::min(total_chunks_ - 1U, ring_begin_ + ring_state_.size() - 1U); + } + + chunk_notify_.notify_all(); +} } // namespace repertory