Clone of chromium aad1ce808763f59c7a3753e08f1500a104ecc6fd refs/remotes/origin/HEAD
diff --git a/cc/debug/ring_buffer.h b/cc/debug/ring_buffer.h
new file mode 100644
index 0000000..94d8459
--- /dev/null
+++ b/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_