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