From ef4afe5ca0af89b904697dee3d5bc4ff38b245d9 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sun, 28 Sep 2025 16:22:30 -0500 Subject: [PATCH] keep ring buffer read pos centered for event seek ahead/behind --- .../src/file_manager/ring_buffer_base.cpp | 31 +++++++++++++++-- .../src/ring_buffer_open_file_test.cpp | 33 +++++++++++++------ 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/repertory/librepertory/src/file_manager/ring_buffer_base.cpp b/repertory/librepertory/src/file_manager/ring_buffer_base.cpp index d1bebd8b..491dbd9e 100644 --- a/repertory/librepertory/src/file_manager/ring_buffer_base.cpp +++ b/repertory/librepertory/src/file_manager/ring_buffer_base.cpp @@ -350,7 +350,33 @@ void ring_buffer_base::set_api_path(const std::string &api_path) { } void ring_buffer_base::update_position(std::size_t count, bool is_forward) { + if (count == 0U) { + return; + } + mutex_lock chunk_lock(chunk_mtx_); + const auto center_ring = [this]() -> void { + auto ring_size = static_cast(read_state_.size()); + auto half_ring_size = ring_size / 2U; + + auto offset = ring_pos_ - ring_begin_; + if (offset > half_ring_size) { + auto steps = offset - half_ring_size; + + auto max_steps = (total_chunks_ - 1U) - ring_end_; + if (steps > max_steps) { + steps = max_steps; + } + + while (steps-- != 0U) { + ++ring_begin_; + ++ring_end_; + read_state_[ring_end_ % ring_size] = false; + } + } + + chunk_notify_.notify_all(); + }; if (is_forward) { if ((ring_pos_ + count) > (total_chunks_ - 1U)) { @@ -363,7 +389,7 @@ void ring_buffer_base::update_position(std::size_t count, bool is_forward) { if (is_forward ? (ring_pos_ + count) <= ring_end_ : (ring_pos_ - count) >= ring_begin_) { ring_pos_ += is_forward ? count : -count; - chunk_notify_.notify_all(); + center_ring(); return; } @@ -387,7 +413,6 @@ void ring_buffer_base::update_position(std::size_t count, bool is_forward) { ring_end_ = std::min(total_chunks_ - 1U, ring_begin_ + read_state_.size() - 1U); - - chunk_notify_.notify_all(); + center_ring(); } } // namespace repertory diff --git a/repertory/repertory_test/src/ring_buffer_open_file_test.cpp b/repertory/repertory_test/src/ring_buffer_open_file_test.cpp index 1f0ca6c9..97df5f79 100644 --- a/repertory/repertory_test/src/ring_buffer_open_file_test.cpp +++ b/repertory/repertory_test/src/ring_buffer_open_file_test.cpp @@ -64,15 +64,21 @@ TEST_F(ring_buffer_open_file_test, can_forward_to_last_chunk) { { ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, provider, 8U); + file.set(0U, 3U); file.forward(4U); EXPECT_EQ(std::size_t(7U), file.get_current_chunk()); - EXPECT_EQ(std::size_t(0U), file.get_first_chunk()); - EXPECT_EQ(std::size_t(7U), file.get_last_chunk()); - for (std::size_t chunk = 0U; chunk < 8U; chunk++) { + EXPECT_EQ(std::size_t(3U), file.get_first_chunk()); + EXPECT_EQ(std::size_t(10U), file.get_last_chunk()); + + for (std::size_t chunk = 3U; chunk <= 7U; ++chunk) { EXPECT_TRUE(file.get_read_state(chunk)); } + + for (std::size_t chunk = 8U; chunk <= 10U; ++chunk) { + EXPECT_FALSE(file.get_read_state(chunk)); + } } } @@ -117,16 +123,22 @@ TEST_F(ring_buffer_open_file_test, can_forward_after_last_chunk) { { ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, provider, 8U); + file.set(0U, 3U); file.forward(5U); EXPECT_EQ(std::size_t(8U), file.get_current_chunk()); - EXPECT_EQ(std::size_t(1U), file.get_first_chunk()); - EXPECT_EQ(std::size_t(8U), file.get_last_chunk()); + EXPECT_EQ(std::size_t(4U), file.get_first_chunk()); + EXPECT_EQ(std::size_t(11U), file.get_last_chunk()); + + EXPECT_TRUE(file.get_read_state(4U)); + EXPECT_TRUE(file.get_read_state(5U)); + EXPECT_TRUE(file.get_read_state(6U)); + EXPECT_TRUE(file.get_read_state(7U)); EXPECT_FALSE(file.get_read_state(8U)); - for (std::size_t chunk = 1U; chunk < 8U; chunk++) { - EXPECT_TRUE(file.get_read_state(chunk)); - } + EXPECT_FALSE(file.get_read_state(9U)); + EXPECT_FALSE(file.get_read_state(10U)); + EXPECT_FALSE(file.get_read_state(11U)); } } @@ -144,12 +156,13 @@ TEST_F(ring_buffer_open_file_test, can_forward_and_rollover_after_last_chunk) { { ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, provider, 8U); + file.set(16U, 20U); file.forward(8U); EXPECT_EQ(std::size_t(28U), file.get_current_chunk()); - EXPECT_EQ(std::size_t(21U), file.get_first_chunk()); - EXPECT_EQ(std::size_t(28U), file.get_last_chunk()); + EXPECT_EQ(std::size_t(24U), file.get_first_chunk()); + EXPECT_EQ(std::size_t(31U), file.get_last_chunk()); } }