12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CC_DEBUG_RING_BUFFER_H_ 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CC_DEBUG_RING_BUFFER_H_ 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc { 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)template<typename T, size_t kSize> 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RingBuffer { 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit RingBuffer() 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : current_index_(0) { 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t BufferSize() const { 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return kSize; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t CurrentIndex() const { 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return current_index_; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // tests if a value was saved to this index 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool IsFilledIndex(size_t n) const { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BufferIndex(n) < current_index_; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // n = 0 returns the oldest value and 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // n = bufferSize() - 1 returns the most recent value. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const T& ReadBuffer(size_t n) const { 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(IsFilledIndex(n)); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return buffer_[BufferIndex(n)]; 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) T* MutableReadBuffer(size_t n) { 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(IsFilledIndex(n)); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return &buffer_[BufferIndex(n)]; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SaveToBuffer(const T& value) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer_[BufferIndex(0)] = value; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_index_++; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Clear() { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_index_ = 0; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Iterator has const access to the RingBuffer it got retrieved from. 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) class Iterator { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t index() const { return index_; } 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const T* operator->() const { return &buffer_.ReadBuffer(index_); } 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const T* operator*() const { return &buffer_.ReadBuffer(index_); } 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Iterator& operator++() { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) index_++; 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (index_ == kSize) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_of_range_ = true; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *this; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Iterator& operator--() { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (index_ == 0) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_of_range_ = true; 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) index_--; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *this; 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) operator bool() const { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return buffer_.IsFilledIndex(index_) && !out_of_range_; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Iterator(const RingBuffer<T, kSize>& buffer, size_t index) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : buffer_(buffer), 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) index_(index), 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) out_of_range_(false) { 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const RingBuffer<T, kSize>& buffer_; 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t index_; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool out_of_range_; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) friend class RingBuffer<T, kSize>; 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns an Iterator pointing to the oldest value in the buffer. 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Example usage (iterate from oldest to newest value): 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.Begin(); it; ++it) {} 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Iterator Begin() const { 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (current_index_ < kSize) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Iterator(*this, kSize - current_index_); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Iterator(*this, 0); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns an Iterator pointing to the newest value in the buffer. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Example usage (iterate backwards from newest to oldest value): 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.End(); it; --it) {} 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Iterator End() const { 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Iterator(*this, kSize - 1); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) inline size_t BufferIndex(size_t n) const { 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (current_index_ + n) % kSize; 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) T buffer_[kSize]; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t current_index_; 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(RingBuffer); 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace cc 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // CC_DEBUG_RING_BUFFER_H_ 123