Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:47:14

0001 // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
0002 // Distributed under the MIT License (http://opensource.org/licenses/MIT)
0003 
0004 // circular q view of std::vector.
0005 #pragma once
0006 
0007 #include <cassert>
0008 #include <vector>
0009 
0010 #include "spdlog/common.h"
0011 
0012 namespace spdlog {
0013 namespace details {
0014 template <typename T>
0015 class circular_q {
0016     size_t max_items_ = 0;
0017     typename std::vector<T>::size_type head_ = 0;
0018     typename std::vector<T>::size_type tail_ = 0;
0019     size_t overrun_counter_ = 0;
0020     std::vector<T> v_;
0021 
0022 public:
0023     using value_type = T;
0024 
0025     // empty ctor - create a disabled queue with no elements allocated at all
0026     circular_q() = default;
0027 
0028     explicit circular_q(size_t max_items)
0029         : max_items_(max_items + 1)  // one item is reserved as marker for full q
0030           ,
0031           v_(max_items_) {}
0032 
0033     circular_q(const circular_q &) = default;
0034     circular_q &operator=(const circular_q &) = default;
0035 
0036     // move cannot be default,
0037     // since we need to reset head_, tail_, etc to zero in the moved object
0038     circular_q(circular_q &&other) SPDLOG_NOEXCEPT { copy_moveable(std::move(other)); }
0039 
0040     circular_q &operator=(circular_q &&other) SPDLOG_NOEXCEPT {
0041         copy_moveable(std::move(other));
0042         return *this;
0043     }
0044 
0045     // push back, overrun (oldest) item if no room left
0046     void push_back(T &&item) {
0047         if (max_items_ > 0) {
0048             v_[tail_] = std::move(item);
0049             tail_ = (tail_ + 1) % max_items_;
0050 
0051             if (tail_ == head_)  // overrun last item if full
0052             {
0053                 head_ = (head_ + 1) % max_items_;
0054                 ++overrun_counter_;
0055             }
0056         }
0057     }
0058 
0059     // Return reference to the front item.
0060     // If there are no elements in the container, the behavior is undefined.
0061     const T &front() const { return v_[head_]; }
0062 
0063     T &front() { return v_[head_]; }
0064 
0065     // Return number of elements actually stored
0066     size_t size() const {
0067         if (tail_ >= head_) {
0068             return tail_ - head_;
0069         } else {
0070             return max_items_ - (head_ - tail_);
0071         }
0072     }
0073 
0074     // Return const reference to item by index.
0075     // If index is out of range 0…size()-1, the behavior is undefined.
0076     const T &at(size_t i) const {
0077         assert(i < size());
0078         return v_[(head_ + i) % max_items_];
0079     }
0080 
0081     // Pop item from front.
0082     // If there are no elements in the container, the behavior is undefined.
0083     void pop_front() { head_ = (head_ + 1) % max_items_; }
0084 
0085     bool empty() const { return tail_ == head_; }
0086 
0087     bool full() const {
0088         // head is ahead of the tail by 1
0089         if (max_items_ > 0) {
0090             return ((tail_ + 1) % max_items_) == head_;
0091         }
0092         return false;
0093     }
0094 
0095     size_t overrun_counter() const { return overrun_counter_; }
0096 
0097     void reset_overrun_counter() { overrun_counter_ = 0; }
0098 
0099 private:
0100     // copy from other&& and reset it to disabled state
0101     void copy_moveable(circular_q &&other) SPDLOG_NOEXCEPT {
0102         max_items_ = other.max_items_;
0103         head_ = other.head_;
0104         tail_ = other.tail_;
0105         overrun_counter_ = other.overrun_counter_;
0106         v_ = std::move(other.v_);
0107 
0108         // put &&other in disabled, but valid state
0109         other.max_items_ = 0;
0110         other.head_ = other.tail_ = 0;
0111         other.overrun_counter_ = 0;
0112     }
0113 };
0114 }  // namespace details
0115 }  // namespace spdlog