Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15ab437b authored by Jack He's avatar Jack He
Browse files

GD-Common: Add CircularBuffer::Drain() method

* Drain() allows a circular buffer to return and clear
  its content so that one can clear a circular buffer
  in-place
* Moreover, Drain() uses move semantic to avoid copying
  its content and hence is more efficient
* Modify Pull() to use range-based initialization to do
  blocked copy that tends to be more efficient
* Add circular buffer unit test to compilation target
  and presubmit

Bug: 180569201
Test: gd/cert/run
Test: bluetooth_test_gd
Tag: #gd-refactor
Change-Id: Ic94f70fc862f244dcdc6b9d5f2526c45d0b8eb52
parent 1adbba45
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ filegroup {
        "blocking_queue_unittest.cc",
        "bidi_queue_unittest.cc",
        "byte_array_test.cc",
        "circular_buffer_test.cc",
        "observer_registry_test.cc",
        "init_flags_test.cc",
        "list_map_test.cc",
+20 −6
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@

#pragma once

#include <stddef.h>

#include <cstddef>
#include <iterator>
#include <mutex>
#include <queue>

@@ -29,8 +29,12 @@ class CircularBuffer {
 public:
  explicit CircularBuffer(size_t size);

  // Push one item to the circular buffer
  void Push(T item);
  // Take a snapshot of the circular buffer and return it as a vector
  std::vector<T> Pull() const;
  // Drain everything from the circular buffer and return them as a vector
  std::vector<T> Drain();

 private:
  const size_t size_;
@@ -67,6 +71,7 @@ class TimestampedCircularBuffer : public CircularBuffer<TimestampedEntry<T>> {

  void Push(T item);
  std::vector<TimestampedEntry<T>> Pull() const;
  std::vector<TimestampedEntry<T>> Drain();

 private:
  std::unique_ptr<Timestamper> timestamper_{std::make_unique<TimestamperInMilliseconds>()};
@@ -90,10 +95,14 @@ void bluetooth::common::CircularBuffer<T>::Push(const T item) {
template <typename T>
std::vector<T> bluetooth::common::CircularBuffer<T>::Pull() const {
  std::unique_lock<std::mutex> lock(mutex_);
  std::vector<T> items;
  for (auto it = queue_.cbegin(); it != queue_.cend(); ++it) {
    items.push_back(*it);
  return std::vector<T>(queue_.cbegin(), queue_.cend());
}

template <typename T>
std::vector<T> bluetooth::common::CircularBuffer<T>::Drain() {
  std::unique_lock<std::mutex> lock(mutex_);
  std::vector<T> items(std::make_move_iterator(queue_.begin()), std::make_move_iterator(queue_.end()));
  queue_.clear();
  return items;
}

@@ -113,3 +122,8 @@ std::vector<struct bluetooth::common::TimestampedEntry<T>> bluetooth::common::Ti
    const {
  return bluetooth::common::CircularBuffer<TimestampedEntry<T>>::Pull();
}

template <typename T>
std::vector<struct bluetooth::common::TimestampedEntry<T>> bluetooth::common::TimestampedCircularBuffer<T>::Drain() {
  return bluetooth::common::CircularBuffer<TimestampedEntry<T>>::Drain();
}
+22 −0
Original line number Diff line number Diff line
@@ -43,6 +43,28 @@ TEST(CircularBufferTest, simple) {
  ASSERT_STREQ("One", vec[0].entry.c_str());
  ASSERT_STREQ("Two", vec[1].entry.c_str());
  ASSERT_STREQ("Three", vec[2].entry.c_str());

  auto vec2 = buffer.Pull();

  ASSERT_FALSE(vec2.empty());
}

TEST(CircularBufferTest, simple_drain) {
  bluetooth::common::TimestampedCircularBuffer<std::string> buffer(10);

  buffer.Push(std::string("One"));
  buffer.Push(std::string("Two"));
  buffer.Push(std::string("Three"));

  auto vec = buffer.Drain();

  ASSERT_STREQ("One", vec[0].entry.c_str());
  ASSERT_STREQ("Two", vec[1].entry.c_str());
  ASSERT_STREQ("Three", vec[2].entry.c_str());

  auto vec2 = buffer.Pull();

  ASSERT_TRUE(vec2.empty());
}

TEST(CircularBufferTest, test_timestamps) {