116 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
 | |
| // Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | |
| 
 | |
| // circular q view of std::vector.
 | |
| #pragma once
 | |
| 
 | |
| #include <cassert>
 | |
| #include <vector>
 | |
| 
 | |
| #include "spdlog/common.h"
 | |
| 
 | |
| namespace spdlog {
 | |
| namespace details {
 | |
| template <typename T>
 | |
| class circular_q {
 | |
|     size_t max_items_ = 0;
 | |
|     typename std::vector<T>::size_type head_ = 0;
 | |
|     typename std::vector<T>::size_type tail_ = 0;
 | |
|     size_t overrun_counter_ = 0;
 | |
|     std::vector<T> v_;
 | |
| 
 | |
| public:
 | |
|     using value_type = T;
 | |
| 
 | |
|     // empty ctor - create a disabled queue with no elements allocated at all
 | |
|     circular_q() = default;
 | |
| 
 | |
|     explicit circular_q(size_t max_items)
 | |
|         : max_items_(max_items + 1)  // one item is reserved as marker for full q
 | |
|           ,
 | |
|           v_(max_items_) {}
 | |
| 
 | |
|     circular_q(const circular_q &) = default;
 | |
|     circular_q &operator=(const circular_q &) = default;
 | |
| 
 | |
|     // move cannot be default,
 | |
|     // since we need to reset head_, tail_, etc to zero in the moved object
 | |
|     circular_q(circular_q &&other) SPDLOG_NOEXCEPT { copy_moveable(std::move(other)); }
 | |
| 
 | |
|     circular_q &operator=(circular_q &&other) SPDLOG_NOEXCEPT {
 | |
|         copy_moveable(std::move(other));
 | |
|         return *this;
 | |
|     }
 | |
| 
 | |
|     // push back, overrun (oldest) item if no room left
 | |
|     void push_back(T &&item) {
 | |
|         if (max_items_ > 0) {
 | |
|             v_[tail_] = std::move(item);
 | |
|             tail_ = (tail_ + 1) % max_items_;
 | |
| 
 | |
|             if (tail_ == head_)  // overrun last item if full
 | |
|             {
 | |
|                 head_ = (head_ + 1) % max_items_;
 | |
|                 ++overrun_counter_;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Return reference to the front item.
 | |
|     // If there are no elements in the container, the behavior is undefined.
 | |
|     const T &front() const { return v_[head_]; }
 | |
| 
 | |
|     T &front() { return v_[head_]; }
 | |
| 
 | |
|     // Return number of elements actually stored
 | |
|     size_t size() const {
 | |
|         if (tail_ >= head_) {
 | |
|             return tail_ - head_;
 | |
|         } else {
 | |
|             return max_items_ - (head_ - tail_);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Return const reference to item by index.
 | |
|     // If index is out of range 0…size()-1, the behavior is undefined.
 | |
|     const T &at(size_t i) const {
 | |
|         assert(i < size());
 | |
|         return v_[(head_ + i) % max_items_];
 | |
|     }
 | |
| 
 | |
|     // Pop item from front.
 | |
|     // If there are no elements in the container, the behavior is undefined.
 | |
|     void pop_front() { head_ = (head_ + 1) % max_items_; }
 | |
| 
 | |
|     bool empty() const { return tail_ == head_; }
 | |
| 
 | |
|     bool full() const {
 | |
|         // head is ahead of the tail by 1
 | |
|         if (max_items_ > 0) {
 | |
|             return ((tail_ + 1) % max_items_) == head_;
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     size_t overrun_counter() const { return overrun_counter_; }
 | |
| 
 | |
|     void reset_overrun_counter() { overrun_counter_ = 0; }
 | |
| 
 | |
| private:
 | |
|     // copy from other&& and reset it to disabled state
 | |
|     void copy_moveable(circular_q &&other) SPDLOG_NOEXCEPT {
 | |
|         max_items_ = other.max_items_;
 | |
|         head_ = other.head_;
 | |
|         tail_ = other.tail_;
 | |
|         overrun_counter_ = other.overrun_counter_;
 | |
|         v_ = std::move(other.v_);
 | |
| 
 | |
|         // put &&other in disabled, but valid state
 | |
|         other.max_items_ = 0;
 | |
|         other.head_ = other.tail_ = 0;
 | |
|         other.overrun_counter_ = 0;
 | |
|     }
 | |
| };
 | |
| }  // namespace details
 | |
| }  // namespace spdlog
 |