94 typedef DataT value_type;
97 typedef uint32_t size_type;
101 struct CircularBufferData
103 template<
typename U = value_type>
104 CircularBufferData(U && dat,
105 const uint64_t window_idx) :
106 data(std::forward<U>(dat)),
107 window_idx(window_idx)
109 CircularBufferData(
const uint64_t window_idx) :
110 window_idx(window_idx)
118 using CircularBufferDataStorage = std::list<CircularBufferData>;
119 typedef typename CircularBufferDataStorage::iterator InternalCircularBufferIterator;
120 typedef typename CircularBufferDataStorage::const_iterator InternalCircularBufferConstIterator;
139 template <
bool is_const_iterator = true>
140 class CircularBufferIterator :
145 static constexpr bool is_const_iterator_type = is_const_iterator;
148 typedef typename std::conditional<is_const_iterator,
149 const value_type &, value_type &>::type DataReferenceType;
150 typedef typename std::conditional<is_const_iterator,
154 CircularBufferPointerType attached_circularbuffer_ =
nullptr;
156 typedef typename std::conditional<is_const_iterator,
157 InternalCircularBufferConstIterator,
158 InternalCircularBufferIterator>::type SpecificCircularBufferIterator;
159 SpecificCircularBufferIterator circularbuffer_entry_;
162 uint64_t window_idx_ = std::numeric_limits<uint64_t>::max();
169 CircularBufferIterator(CircularBufferPointerType circularbuffer,
170 SpecificCircularBufferIterator entry,
171 const uint64_t window_idx) :
172 attached_circularbuffer_(circularbuffer),
173 circularbuffer_entry_(entry),
174 window_idx_(window_idx)
179 SpecificCircularBufferIterator getInternalBufferEntry_()
const {
180 return circularbuffer_entry_;
188 CircularBufferIterator() =
default;
194 CircularBufferIterator(
const CircularBufferIterator<false> & iter) :
195 attached_circularbuffer_(iter.attached_circularbuffer_),
196 circularbuffer_entry_(iter.circularbuffer_entry_),
197 window_idx_(iter.window_idx_)
204 CircularBufferIterator(
const CircularBufferIterator<true> & iter) :
205 attached_circularbuffer_(iter.attached_circularbuffer_),
206 circularbuffer_entry_(iter.circularbuffer_entry_),
207 window_idx_(iter.window_idx_)
215 CircularBufferIterator& operator=(
const CircularBufferIterator& rhs) =
default;
218 bool operator<(
const CircularBufferIterator& rhs)
const
220 sparta_assert(attached_circularbuffer_ == rhs.attached_circularbuffer_,
221 "Cannot compare CircularBufferIterators created by different CircularBuffers.");
222 return window_idx_ > rhs.window_idx_;
226 bool operator>(
const CircularBufferIterator& rhs)
const
228 sparta_assert(attached_circularbuffer_ == rhs.attached_circularbuffer_,
229 "Cannot compare CircularBufferIterators created by different CircularBuffers.");
230 return window_idx_ < rhs.window_idx_;
234 bool operator==(
const CircularBufferIterator& rhs)
const
236 sparta_assert(attached_circularbuffer_ == rhs.attached_circularbuffer_,
237 "Cannot compare CircularBufferIterators created by different CircularBuffers.");
238 return (window_idx_ == rhs.window_idx_);
242 bool operator!=(
const CircularBufferIterator& rhs)
const
244 sparta_assert(attached_circularbuffer_ == rhs.attached_circularbuffer_,
245 "Cannot compare CircularBufferIterators created by different CircularBuffers.");
246 return !operator==(rhs);
253 if(attached_circularbuffer_) {
254 return attached_circularbuffer_->isValidIterator_(window_idx_);
260 DataReferenceType operator* () {
262 "This iterator is not attached to a CircularBuffer. Was it initialized?");
263 sparta_assert(isValid(),
"Iterator is not valid for dereferencing");
264 return circularbuffer_entry_->data;
266 value_type* operator->()
269 "This iterator is not attached to a CircularBuffer. Was it initialized?");
270 sparta_assert(isValid(),
"Iterator is not valid for dereferencing");
271 return &circularbuffer_entry_->data;
273 const value_type* operator->()
const
276 "This iterator is not attached to a CircularBuffer. Was it initialized?");
277 sparta_assert(isValid(),
"Iterator is not valid for dereferencing");
278 return &circularbuffer_entry_->data;
283 CircularBufferIterator & operator++() {
285 "This iterator is not attached to a CircularBuffer. Was it initialized?");
288 ++circularbuffer_entry_;
297 CircularBufferIterator operator++ (
int) {
298 CircularBufferIterator buf_iter(*
this);
304 CircularBufferIterator & operator-- ()
306 sparta_assert(attached_circularbuffer_,
"The iterator is not attached to a CircularBuffer. Was it initialized?");
307 if(attached_circularbuffer_->isValidIterator_(window_idx_ - 1)) {
309 --circularbuffer_entry_;
312 sparta_assert(!
"Attempt to decrement an iterator beyond bounds or that is invalid");
318 CircularBufferIterator operator-- (
int) {
319 CircularBufferIterator buf_iter(*
this);
328 friend class CircularBufferIterator<true>;
334 template <
typename iter_type>
335 class CircularBufferReverseIterator :
public std::reverse_iterator<iter_type>
338 typedef typename std::conditional<iter_type::is_const_iterator_type,
339 InternalCircularBufferConstIterator,
340 InternalCircularBufferIterator>::type SpecificCircularBufferIterator;
341 SpecificCircularBufferIterator circularbuffer_entry_;
343 explicit CircularBufferReverseIterator(
const iter_type & it) :
344 std::reverse_iterator<iter_type>(it)
348 CircularBufferReverseIterator(
const std::reverse_iterator<U> & other) :
349 std::reverse_iterator<iter_type>(other)
352 bool isValid()
const {
353 auto it = std::reverse_iterator<iter_type>::base();
355 return (--it).isValid();
364 SpecificCircularBufferIterator getInternalBufferEntry_()
const {
365 auto it = std::reverse_iterator<iter_type>::base();
366 return (--it).circularbuffer_entry_;
421 const uint32_t max_size,
516 push_backImpl_(std::move(dat));
526 return insertEntry_(entry, dat);
536 return insertEntry_(entry, std::move(dat));
546 return insertEntry_(entry, dat);
556 return insertEntry_(entry, std::move(dat));
566 "Cannot erase an entry created by another CircularBuffer");
577 "Cannot erase an entry created by another CircularBuffer");
590 circularbuffer_data_.clear();
592 start_idx_ = end_idx_;
593 updateUtilizationCounters_();
605 circularbuffer_data_.begin(),
606 circularbuffer_data_.begin()->window_idx);
616 return iterator(
this, circularbuffer_data_.end(), end_idx_);
628 circularbuffer_data_.begin(),
629 circularbuffer_data_.begin()->window_idx);
639 return const_iterator(
this, circularbuffer_data_.end(), end_idx_);
683 auto it = this->
begin();
684 std::advance(it, idx);
692 bool isValidIterator_(uint32_t window_idx)
const {
693 return (window_idx >= start_idx_ && window_idx < end_idx_);
696 template<
typename EntryIteratorT>
697 void eraseEntry_(
const EntryIteratorT & entry)
700 circularbuffer_data_.erase(entry.getInternalBufferEntry_());
702 invalidateIndexes_();
706 void push_backImpl_(U&& dat)
708 circularbuffer_data_.emplace(circularbuffer_data_.end(), std::forward<U>(dat), end_idx_);
710 if(num_valid_ == max_size_) {
711 circularbuffer_data_.pop_front();
721 updateUtilizationCounters_();
724 template<
typename EntryIteratorT,
typename U>
725 iterator insertEntry_(
const EntryIteratorT & entry, U&& dat)
729 if(circularbuffer_data_.empty()) {
734 "Cannot insert into Circularbuffer at given iterator");
735 auto it = circularbuffer_data_.insert(entry.getInternalBufferEntry_(),
736 CircularBufferData(std::forward<U>(dat), end_idx_));
738 invalidateIndexes_();
739 return iterator(
this, it, it->window_idx);
742 void invalidateIndexes_() {
748 start_idx_ = ++end_idx_;
749 for(
auto & it : circularbuffer_data_) {
750 it.window_idx = end_idx_;
755 void updateUtilizationCounters_() {
757 if(!utilization_count_.empty()) {
758 if(previous_valid_entry_ != num_valid_) {
759 utilization_count_[previous_valid_entry_]->stopCounting();
760 utilization_count_[num_valid_]->startCounting();
761 previous_valid_entry_ = num_valid_;
763 if (num_valid_ > utilization_max_->get()) {
764 utilization_max_->set(num_valid_);
769 const size_type max_size_;
770 const std::string name_;
771 CircularBufferDataStorage circularbuffer_data_;
773 size_type num_valid_ = 0;
774 uint64_t start_idx_ = 0;
776 uint64_t end_idx_ = 0;
781 std::vector<std::unique_ptr<sparta::CycleCounter>> utilization_count_;
782 std::unique_ptr<StatisticDef> weighted_utilization_avg_;
783 std::unique_ptr<StatisticInstance> avg_instance_;
784 std::unique_ptr<sparta::Counter> utilization_max_;
787 uint32_t previous_valid_entry_ = 0;
791 std::unique_ptr<collection::IterableCollector<CircularBuffer<value_type> > > collector_;