/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include namespace bluetooth { namespace common { template 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 Pull() const; // Drain everything from the circular buffer and return them as a vector std::vector Drain(); private: const size_t size_; std::deque queue_; mutable std::mutex mutex_; }; class Timestamper { public: virtual long long GetTimestamp() const = 0; virtual ~Timestamper() {} }; class TimestamperInMilliseconds : public Timestamper { public: long long GetTimestamp() const override { return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) .count(); } virtual ~TimestamperInMilliseconds() {} }; template struct TimestampedEntry { long long timestamp; T entry; }; template class TimestampedCircularBuffer : public CircularBuffer> { public: explicit TimestampedCircularBuffer( size_t size, std::unique_ptr timestamper = std::make_unique()); void Push(T item); std::vector> Pull() const; std::vector> Drain(); private: std::unique_ptr timestamper_{std::make_unique()}; }; } // namespace common } // namespace bluetooth template bluetooth::common::CircularBuffer::CircularBuffer(size_t size) : size_(size) {} template void bluetooth::common::CircularBuffer::Push(const T item) { std::unique_lock lock(mutex_); queue_.push_back(item); while (queue_.size() > size_) { queue_.pop_front(); } } template std::vector bluetooth::common::CircularBuffer::Pull() const { std::unique_lock lock(mutex_); return std::vector(queue_.cbegin(), queue_.cend()); } template std::vector bluetooth::common::CircularBuffer::Drain() { std::unique_lock lock(mutex_); std::vector items(std::make_move_iterator(queue_.begin()), std::make_move_iterator(queue_.end())); queue_.clear(); return items; } template bluetooth::common::TimestampedCircularBuffer::TimestampedCircularBuffer( size_t size, std::unique_ptr timestamper) : CircularBuffer>(size), timestamper_(std::move(timestamper)) {} template void bluetooth::common::TimestampedCircularBuffer::Push(const T item) { TimestampedEntry timestamped_entry{timestamper_->GetTimestamp(), item}; bluetooth::common::CircularBuffer>::Push(timestamped_entry); } template std::vector> bluetooth::common::TimestampedCircularBuffer::Pull() const { return bluetooth::common::CircularBuffer>::Pull(); } template std::vector> bluetooth::common::TimestampedCircularBuffer::Drain() { return bluetooth::common::CircularBuffer>::Drain(); }