OLD | NEW |
| (Empty) |
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: | |
15 RingBuffer() : current_index_(0) {} | |
16 | |
17 size_t BufferSize() const { | |
18 return kSize; | |
19 } | |
20 | |
21 size_t CurrentIndex() const { | |
22 return current_index_; | |
23 } | |
24 | |
25 // tests if a value was saved to this index | |
26 bool IsFilledIndex(size_t n) const { | |
27 return BufferIndex(n) < current_index_; | |
28 } | |
29 | |
30 // n = 0 returns the oldest value and | |
31 // n = bufferSize() - 1 returns the most recent value. | |
32 const T& ReadBuffer(size_t n) const { | |
33 DCHECK(IsFilledIndex(n)); | |
34 return buffer_[BufferIndex(n)]; | |
35 } | |
36 | |
37 T* MutableReadBuffer(size_t n) { | |
38 DCHECK(IsFilledIndex(n)); | |
39 return &buffer_[BufferIndex(n)]; | |
40 } | |
41 | |
42 void SaveToBuffer(const T& value) { | |
43 buffer_[BufferIndex(0)] = value; | |
44 current_index_++; | |
45 } | |
46 | |
47 void Clear() { | |
48 current_index_ = 0; | |
49 } | |
50 | |
51 // Iterator has const access to the RingBuffer it got retrieved from. | |
52 class Iterator { | |
53 public: | |
54 size_t index() const { return index_; } | |
55 | |
56 const T* operator->() const { return &buffer_.ReadBuffer(index_); } | |
57 const T* operator*() const { return &buffer_.ReadBuffer(index_); } | |
58 | |
59 Iterator& operator++() { | |
60 index_++; | |
61 if (index_ == kSize) | |
62 out_of_range_ = true; | |
63 return *this; | |
64 } | |
65 | |
66 Iterator& operator--() { | |
67 if (index_ == 0) | |
68 out_of_range_ = true; | |
69 index_--; | |
70 return *this; | |
71 } | |
72 | |
73 operator bool() const { | |
74 return buffer_.IsFilledIndex(index_) && !out_of_range_; | |
75 } | |
76 | |
77 private: | |
78 Iterator(const RingBuffer<T, kSize>& buffer, size_t index) | |
79 : buffer_(buffer), | |
80 index_(index), | |
81 out_of_range_(false) { | |
82 } | |
83 | |
84 const RingBuffer<T, kSize>& buffer_; | |
85 size_t index_; | |
86 bool out_of_range_; | |
87 | |
88 friend class RingBuffer<T, kSize>; | |
89 }; | |
90 | |
91 // Returns an Iterator pointing to the oldest value in the buffer. | |
92 // Example usage (iterate from oldest to newest value): | |
93 // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.Begin(); it; ++it) {} | |
94 Iterator Begin() const { | |
95 if (current_index_ < kSize) | |
96 return Iterator(*this, kSize - current_index_); | |
97 return Iterator(*this, 0); | |
98 } | |
99 | |
100 // Returns an Iterator pointing to the newest value in the buffer. | |
101 // Example usage (iterate backwards from newest to oldest value): | |
102 // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.End(); it; --it) {} | |
103 Iterator End() const { | |
104 return Iterator(*this, kSize - 1); | |
105 } | |
106 | |
107 private: | |
108 inline size_t BufferIndex(size_t n) const { | |
109 return (current_index_ + n) % kSize; | |
110 } | |
111 | |
112 T buffer_[kSize]; | |
113 size_t current_index_; | |
114 | |
115 DISALLOW_COPY_AND_ASSIGN(RingBuffer); | |
116 }; | |
117 | |
118 } // namespace cc | |
119 | |
120 #endif // CC_DEBUG_RING_BUFFER_H_ | |
OLD | NEW |