blob: f9a6749e11622b0cd5a29ff92f69a962c5b762e0 [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CC_DEBUG_RING_BUFFER_H_
6#define CC_DEBUG_RING_BUFFER_H_
7
8#include "base/logging.h"
9
10namespace cc {
11
12template<typename T, size_t kSize>
13class RingBuffer {
14 public:
Benjamin Lerman57998902014-11-18 16:06:02 +010015 RingBuffer() : current_index_(0) {}
James Robinson646469d2014-10-03 15:33:28 -070016
17 size_t BufferSize() const {
18 return kSize;
19 }
20
21 size_t CurrentIndex() const {
22 return current_index_;
23 }
24
25 // tests if a value was saved to this index
26 bool IsFilledIndex(size_t n) const {
27 return BufferIndex(n) < current_index_;
28 }
29
30 // n = 0 returns the oldest value and
31 // n = bufferSize() - 1 returns the most recent value.
32 const T& ReadBuffer(size_t n) const {
33 DCHECK(IsFilledIndex(n));
34 return buffer_[BufferIndex(n)];
35 }
36
37 T* MutableReadBuffer(size_t n) {
38 DCHECK(IsFilledIndex(n));
39 return &buffer_[BufferIndex(n)];
40 }
41
42 void SaveToBuffer(const T& value) {
43 buffer_[BufferIndex(0)] = value;
44 current_index_++;
45 }
46
47 void Clear() {
48 current_index_ = 0;
49 }
50
51 // Iterator has const access to the RingBuffer it got retrieved from.
52 class Iterator {
53 public:
54 size_t index() const { return index_; }
55
56 const T* operator->() const { return &buffer_.ReadBuffer(index_); }
57 const T* operator*() const { return &buffer_.ReadBuffer(index_); }
58
59 Iterator& operator++() {
60 index_++;
61 if (index_ == kSize)
62 out_of_range_ = true;
63 return *this;
64 }
65
66 Iterator& operator--() {
67 if (index_ == 0)
68 out_of_range_ = true;
69 index_--;
70 return *this;
71 }
72
73 operator bool() const {
74 return buffer_.IsFilledIndex(index_) && !out_of_range_;
75 }
76
77 private:
78 Iterator(const RingBuffer<T, kSize>& buffer, size_t index)
79 : buffer_(buffer),
80 index_(index),
81 out_of_range_(false) {
82 }
83
84 const RingBuffer<T, kSize>& buffer_;
85 size_t index_;
86 bool out_of_range_;
87
88 friend class RingBuffer<T, kSize>;
89 };
90
91 // Returns an Iterator pointing to the oldest value in the buffer.
92 // Example usage (iterate from oldest to newest value):
93 // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.Begin(); it; ++it) {}
94 Iterator Begin() const {
95 if (current_index_ < kSize)
96 return Iterator(*this, kSize - current_index_);
97 return Iterator(*this, 0);
98 }
99
100 // Returns an Iterator pointing to the newest value in the buffer.
101 // Example usage (iterate backwards from newest to oldest value):
102 // for (RingBuffer<T, kSize>::Iterator it = ring_buffer.End(); it; --it) {}
103 Iterator End() const {
104 return Iterator(*this, kSize - 1);
105 }
106
107 private:
108 inline size_t BufferIndex(size_t n) const {
109 return (current_index_ + n) % kSize;
110 }
111
112 T buffer_[kSize];
113 size_t current_index_;
114
115 DISALLOW_COPY_AND_ASSIGN(RingBuffer);
116};
117
118} // namespace cc
119
120#endif // CC_DEBUG_RING_BUFFER_H_