• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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