1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CC_DEBUG_RING_BUFFER_H_ 6 #define CC_DEBUG_RING_BUFFER_H_ 7 8 #include "base/logging.h" 9 10 namespace cc { 11 12 template<typename T, size_t kSize> 13 class RingBuffer { 14 public: RingBuffer()15 explicit RingBuffer() 16 : current_index_(0) { 17 } 18 BufferSize()19 size_t BufferSize() const { 20 return kSize; 21 } 22 CurrentIndex()23 size_t CurrentIndex() const { 24 return current_index_; 25 } 26 27 // tests if a value was saved to this index IsFilledIndex(size_t n)28 bool IsFilledIndex(size_t n) const { 29 return BufferIndex(n) < current_index_; 30 } 31 32 // n = 0 returns the oldest value and 33 // n = bufferSize() - 1 returns the most recent value. ReadBuffer(size_t n)34 const T& ReadBuffer(size_t n) const { 35 DCHECK(IsFilledIndex(n)); 36 return buffer_[BufferIndex(n)]; 37 } 38 MutableReadBuffer(size_t n)39 T* MutableReadBuffer(size_t n) { 40 DCHECK(IsFilledIndex(n)); 41 return &buffer_[BufferIndex(n)]; 42 } 43 SaveToBuffer(const T & value)44 void SaveToBuffer(const T& value) { 45 buffer_[BufferIndex(0)] = value; 46 current_index_++; 47 } 48 Clear()49 void Clear() { 50 current_index_ = 0; 51 } 52 53 // Iterator has const access to the RingBuffer it got retrieved from. 54 class Iterator { 55 public: index()56 size_t index() const { return index_; } 57 58 const T* operator->() const { return &buffer_.ReadBuffer(index_); } 59 const T* operator*() const { return &buffer_.ReadBuffer(index_); } 60 61 Iterator& operator++() { 62 index_++; 63 if (index_ == kSize) 64 out_of_range_ = true; 65 return *this; 66 } 67 68 Iterator& operator--() { 69 if (index_ == 0) 70 out_of_range_ = true; 71 index_--; 72 return *this; 73 } 74 75 operator bool() const { 76 return buffer_.IsFilledIndex(index_) && !out_of_range_; 77 } 78 79 private: Iterator(const RingBuffer<T,kSize> & buffer,size_t index)80 Iterator(const RingBuffer<T, kSize>& buffer, size_t index) 81 : buffer_(buffer), 82 index_(index), 83 out_of_range_(false) { 84 } 85 86 const RingBuffer<T, kSize>& buffer_; 87 size_t index_; 88 bool out_of_range_; 89 90 friend class RingBuffer<T, kSize>; 91 }; 92 93 // Returns an Iterator pointing to the oldest value in the buffer. 94 // Example usage (iterate from oldest to newest value): 95 // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.Begin(); it; ++it) {} Begin()96 Iterator Begin() const { 97 if (current_index_ < kSize) 98 return Iterator(*this, kSize - current_index_); 99 return Iterator(*this, 0); 100 } 101 102 // Returns an Iterator pointing to the newest value in the buffer. 103 // Example usage (iterate backwards from newest to oldest value): 104 // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.End(); it; --it) {} End()105 Iterator End() const { 106 return Iterator(*this, kSize - 1); 107 } 108 109 private: BufferIndex(size_t n)110 inline size_t BufferIndex(size_t n) const { 111 return (current_index_ + n) % kSize; 112 } 113 114 T buffer_[kSize]; 115 size_t current_index_; 116 117 DISALLOW_COPY_AND_ASSIGN(RingBuffer); 118 }; 119 120 } // namespace cc 121 122 #endif // CC_DEBUG_RING_BUFFER_H_ 123