keep ring buffer read pos centered for event seek ahead/behind
This commit is contained in:
@@ -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) {
|
void ring_buffer_base::update_position(std::size_t count, bool is_forward) {
|
||||||
|
if (count == 0U) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_lock chunk_lock(chunk_mtx_);
|
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 (is_forward) {
|
||||||
if ((ring_pos_ + count) > (total_chunks_ - 1U)) {
|
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_
|
if (is_forward ? (ring_pos_ + count) <= ring_end_
|
||||||
: (ring_pos_ - count) >= ring_begin_) {
|
: (ring_pos_ - count) >= ring_begin_) {
|
||||||
ring_pos_ += is_forward ? count : -count;
|
ring_pos_ += is_forward ? count : -count;
|
||||||
chunk_notify_.notify_all();
|
center_ring();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +413,6 @@ void ring_buffer_base::update_position(std::size_t count, bool is_forward) {
|
|||||||
|
|
||||||
ring_end_ =
|
ring_end_ =
|
||||||
std::min(total_chunks_ - 1U, ring_begin_ + read_state_.size() - 1U);
|
std::min(total_chunks_ - 1U, ring_begin_ + read_state_.size() - 1U);
|
||||||
|
center_ring();
|
||||||
chunk_notify_.notify_all();
|
|
||||||
}
|
}
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
@@ -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,
|
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
|
||||||
provider, 8U);
|
provider, 8U);
|
||||||
|
|
||||||
file.set(0U, 3U);
|
file.set(0U, 3U);
|
||||||
file.forward(4U);
|
file.forward(4U);
|
||||||
|
|
||||||
EXPECT_EQ(std::size_t(7U), file.get_current_chunk());
|
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(3U), file.get_first_chunk());
|
||||||
EXPECT_EQ(std::size_t(7U), file.get_last_chunk());
|
EXPECT_EQ(std::size_t(10U), file.get_last_chunk());
|
||||||
for (std::size_t chunk = 0U; chunk < 8U; chunk++) {
|
|
||||||
|
for (std::size_t chunk = 3U; chunk <= 7U; ++chunk) {
|
||||||
EXPECT_TRUE(file.get_read_state(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,
|
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
|
||||||
provider, 8U);
|
provider, 8U);
|
||||||
|
|
||||||
file.set(0U, 3U);
|
file.set(0U, 3U);
|
||||||
file.forward(5U);
|
file.forward(5U);
|
||||||
|
|
||||||
EXPECT_EQ(std::size_t(8U), file.get_current_chunk());
|
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(4U), file.get_first_chunk());
|
||||||
EXPECT_EQ(std::size_t(8U), file.get_last_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));
|
EXPECT_FALSE(file.get_read_state(8U));
|
||||||
for (std::size_t chunk = 1U; chunk < 8U; chunk++) {
|
EXPECT_FALSE(file.get_read_state(9U));
|
||||||
EXPECT_TRUE(file.get_read_state(chunk));
|
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,
|
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
|
||||||
provider, 8U);
|
provider, 8U);
|
||||||
|
|
||||||
file.set(16U, 20U);
|
file.set(16U, 20U);
|
||||||
file.forward(8U);
|
file.forward(8U);
|
||||||
|
|
||||||
EXPECT_EQ(std::size_t(28U), file.get_current_chunk());
|
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(24U), file.get_first_chunk());
|
||||||
EXPECT_EQ(std::size_t(28U), file.get_last_chunk());
|
EXPECT_EQ(std::size_t(31U), file.get_last_chunk());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user