Index: cc/debug/ring_buffer.h |
diff --git a/cc/debug/ring_buffer.h b/cc/debug/ring_buffer.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f9a6749e11622b0cd5a29ff92f69a962c5b762e0 |
--- /dev/null |
+++ b/cc/debug/ring_buffer.h |
@@ -0,0 +1,120 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef CC_DEBUG_RING_BUFFER_H_ |
+#define CC_DEBUG_RING_BUFFER_H_ |
+ |
+#include "base/logging.h" |
+ |
+namespace cc { |
+ |
+template<typename T, size_t kSize> |
+class RingBuffer { |
+ public: |
+ RingBuffer() : current_index_(0) {} |
+ |
+ size_t BufferSize() const { |
+ return kSize; |
+ } |
+ |
+ size_t CurrentIndex() const { |
+ return current_index_; |
+ } |
+ |
+ // tests if a value was saved to this index |
+ bool IsFilledIndex(size_t n) const { |
+ return BufferIndex(n) < current_index_; |
+ } |
+ |
+ // n = 0 returns the oldest value and |
+ // n = bufferSize() - 1 returns the most recent value. |
+ const T& ReadBuffer(size_t n) const { |
+ DCHECK(IsFilledIndex(n)); |
+ return buffer_[BufferIndex(n)]; |
+ } |
+ |
+ T* MutableReadBuffer(size_t n) { |
+ DCHECK(IsFilledIndex(n)); |
+ return &buffer_[BufferIndex(n)]; |
+ } |
+ |
+ void SaveToBuffer(const T& value) { |
+ buffer_[BufferIndex(0)] = value; |
+ current_index_++; |
+ } |
+ |
+ void Clear() { |
+ current_index_ = 0; |
+ } |
+ |
+ // Iterator has const access to the RingBuffer it got retrieved from. |
+ class Iterator { |
+ public: |
+ size_t index() const { return index_; } |
+ |
+ const T* operator->() const { return &buffer_.ReadBuffer(index_); } |
+ const T* operator*() const { return &buffer_.ReadBuffer(index_); } |
+ |
+ Iterator& operator++() { |
+ index_++; |
+ if (index_ == kSize) |
+ out_of_range_ = true; |
+ return *this; |
+ } |
+ |
+ Iterator& operator--() { |
+ if (index_ == 0) |
+ out_of_range_ = true; |
+ index_--; |
+ return *this; |
+ } |
+ |
+ operator bool() const { |
+ return buffer_.IsFilledIndex(index_) && !out_of_range_; |
+ } |
+ |
+ private: |
+ Iterator(const RingBuffer<T, kSize>& buffer, size_t index) |
+ : buffer_(buffer), |
+ index_(index), |
+ out_of_range_(false) { |
+ } |
+ |
+ const RingBuffer<T, kSize>& buffer_; |
+ size_t index_; |
+ bool out_of_range_; |
+ |
+ friend class RingBuffer<T, kSize>; |
+ }; |
+ |
+ // Returns an Iterator pointing to the oldest value in the buffer. |
+ // Example usage (iterate from oldest to newest value): |
+ // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.Begin(); it; ++it) {} |
+ Iterator Begin() const { |
+ if (current_index_ < kSize) |
+ return Iterator(*this, kSize - current_index_); |
+ return Iterator(*this, 0); |
+ } |
+ |
+ // Returns an Iterator pointing to the newest value in the buffer. |
+ // Example usage (iterate backwards from newest to oldest value): |
+ // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.End(); it; --it) {} |
+ Iterator End() const { |
+ return Iterator(*this, kSize - 1); |
+ } |
+ |
+ private: |
+ inline size_t BufferIndex(size_t n) const { |
+ return (current_index_ + n) % kSize; |
+ } |
+ |
+ T buffer_[kSize]; |
+ size_t current_index_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(RingBuffer); |
+}; |
+ |
+} // namespace cc |
+ |
+#endif // CC_DEBUG_RING_BUFFER_H_ |