keep ring buffer read pos centered for event seek ahead/behind

This commit is contained in:
2025-09-28 16:22:30 -05:00
parent 691a9e3d0a
commit ef4afe5ca0
2 changed files with 51 additions and 13 deletions

View File

@@ -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<std::size_t>(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

View File

@@ -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());
}
}