summaryrefslogtreecommitdiff
path: root/chromium/cc/debug/ring_buffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/cc/debug/ring_buffer.h')
-rw-r--r--chromium/cc/debug/ring_buffer.h122
1 files changed, 122 insertions, 0 deletions
diff --git a/chromium/cc/debug/ring_buffer.h b/chromium/cc/debug/ring_buffer.h
new file mode 100644
index 00000000000..94d8459acd7
--- /dev/null
+++ b/chromium/cc/debug/ring_buffer.h
@@ -0,0 +1,122 @@
+// 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:
+ explicit 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_