diff options
Diffstat (limited to 'chromium/cc/debug/ring_buffer.h')
-rw-r--r-- | chromium/cc/debug/ring_buffer.h | 122 |
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_ |