• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <cstddef>
20 #include <iterator>
21 #include <memory>
22 #include <mutex>
23 #include <queue>
24 
25 namespace bluetooth {
26 namespace common {
27 
28 template <typename T>
29 class CircularBuffer {
30  public:
31   explicit CircularBuffer(size_t size);
32 
33   // Push one item to the circular buffer
34   void Push(T item);
35   // Take a snapshot of the circular buffer and return it as a vector
36   std::vector<T> Pull() const;
37   // Drain everything from the circular buffer and return them as a vector
38   std::vector<T> Drain();
39 
40  private:
41   const size_t size_;
42   std::deque<T> queue_;
43   mutable std::mutex mutex_;
44 };
45 
46 class Timestamper {
47  public:
48   virtual long long GetTimestamp() const = 0;
~Timestamper()49   virtual ~Timestamper() {}
50 };
51 
52 class TimestamperInMilliseconds : public Timestamper {
53  public:
GetTimestamp()54   long long GetTimestamp() const override {
55     return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
56         .count();
57   }
~TimestamperInMilliseconds()58   virtual ~TimestamperInMilliseconds() {}
59 };
60 
61 template <typename T>
62 struct TimestampedEntry {
63   long long timestamp;
64   T entry;
65 };
66 
67 template <typename T>
68 class TimestampedCircularBuffer : public CircularBuffer<TimestampedEntry<T>> {
69  public:
70   explicit TimestampedCircularBuffer(
71       size_t size, std::unique_ptr<Timestamper> timestamper = std::make_unique<TimestamperInMilliseconds>());
72 
73   void Push(T item);
74   std::vector<TimestampedEntry<T>> Pull() const;
75   std::vector<TimestampedEntry<T>> Drain();
76 
77  private:
78   std::unique_ptr<Timestamper> timestamper_{std::make_unique<TimestamperInMilliseconds>()};
79 };
80 
81 }  // namespace common
82 }  // namespace bluetooth
83 
84 template <typename T>
CircularBuffer(size_t size)85 bluetooth::common::CircularBuffer<T>::CircularBuffer(size_t size) : size_(size) {}
86 
87 template <typename T>
Push(const T item)88 void bluetooth::common::CircularBuffer<T>::Push(const T item) {
89   std::unique_lock<std::mutex> lock(mutex_);
90   queue_.push_back(item);
91   while (queue_.size() > size_) {
92     queue_.pop_front();
93   }
94 }
95 
96 template <typename T>
Pull()97 std::vector<T> bluetooth::common::CircularBuffer<T>::Pull() const {
98   std::unique_lock<std::mutex> lock(mutex_);
99   return std::vector<T>(queue_.cbegin(), queue_.cend());
100 }
101 
102 template <typename T>
Drain()103 std::vector<T> bluetooth::common::CircularBuffer<T>::Drain() {
104   std::unique_lock<std::mutex> lock(mutex_);
105   std::vector<T> items(std::make_move_iterator(queue_.begin()), std::make_move_iterator(queue_.end()));
106   queue_.clear();
107   return items;
108 }
109 
110 template <typename T>
TimestampedCircularBuffer(size_t size,std::unique_ptr<Timestamper> timestamper)111 bluetooth::common::TimestampedCircularBuffer<T>::TimestampedCircularBuffer(
112     size_t size, std::unique_ptr<Timestamper> timestamper)
113     : CircularBuffer<TimestampedEntry<T>>(size), timestamper_(std::move(timestamper)) {}
114 
115 template <typename T>
Push(const T item)116 void bluetooth::common::TimestampedCircularBuffer<T>::Push(const T item) {
117   TimestampedEntry<T> timestamped_entry{timestamper_->GetTimestamp(), item};
118   bluetooth::common::CircularBuffer<TimestampedEntry<T>>::Push(timestamped_entry);
119 }
120 
121 template <typename T>
Pull()122 std::vector<struct bluetooth::common::TimestampedEntry<T>> bluetooth::common::TimestampedCircularBuffer<T>::Pull()
123     const {
124   return bluetooth::common::CircularBuffer<TimestampedEntry<T>>::Pull();
125 }
126 
127 template <typename T>
Drain()128 std::vector<struct bluetooth::common::TimestampedEntry<T>> bluetooth::common::TimestampedCircularBuffer<T>::Drain() {
129   return bluetooth::common::CircularBuffer<TimestampedEntry<T>>::Drain();
130 }
131