1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2010 Couchbase, Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 
18 #ifndef SRC_RINGBUFFER_H_
19 #define SRC_RINGBUFFER_H_ 1
20 
21 #include "config.h"
22 
23 #include <algorithm>
24 #include <vector>
25 
26 #include "common.h"
27 
28 /**
29  * A RingBuffer holds a fixed number of elements of type T.
30  */
31 template <typename T>
32 class RingBuffer {
33 public:
34 
35     /**
36      * Construct a RingBuffer to hold the given number of elements.
37      */
RingBuffer(size_t s)38     explicit RingBuffer(size_t s) : pos(0), max(s), wrapped(false) {
39         storage = new T[max];
40     }
41 
~RingBuffer()42     ~RingBuffer() {
43         delete[] storage;
44     }
45 
46     /**
47      * How many elements are currently stored in this ring buffer?
48      */
size()49     size_t size() {
50         return wrapped ? max : pos;
51     }
52 
53     /**
54      * Add an object to the RingBuffer.
55      */
add(T ob)56     void add(T ob) {
57         if (pos == max) {
58             wrapped = true;
59             pos = 0;
60         }
61         storage[pos++] = ob;
62     }
63 
64     /**
65      * Remove all items.
66      */
reset()67     void reset() {
68         pos = 0;
69         wrapped = 0;
70     }
71 
72     /**
73      * Copy out the contents of this RingBuffer into the a vector.
74      */
contents()75     std::vector<T> contents() {
76         std::vector<T> rv;
77         size_t lpos = pos; // snapshot the position, wrapped for consistency
78         size_t lwrapped = wrapped;
79         size_t lsize = lwrapped ? max : lpos;
80         rv.resize(lsize);
81         size_t copied(0);
82         if (lwrapped && lpos != max) {
83             std::copy(storage + lpos, storage + max, rv.begin());
84             copied = max - lpos;
85         }
86         std::copy(storage, storage + lpos, rv.begin() + copied);
87         return rv;
88     }
89 
90 private:
91     T *storage;
92     size_t pos;
93     size_t max;
94     bool wrapped;
95 
96     DISALLOW_COPY_AND_ASSIGN(RingBuffer);
97 };
98 
99 #endif  // SRC_RINGBUFFER_H_
100