MPD  0.20.15
CircularBuffer.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Max Kellermann <max.kellermann@gmail.com>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20  * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27  * OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef CIRCULAR_BUFFER_HPP
31 #define CIRCULAR_BUFFER_HPP
32 
33 #include "WritableBuffer.hxx"
34 
35 #include <assert.h>
36 #include <stddef.h>
37 
50 template<typename T>
51 class CircularBuffer {
52 public:
55  typedef typename Range::size_type size_type;
56 
57 protected:
62 
67 
70 
71 public:
72  constexpr CircularBuffer(pointer_type _data, size_type _capacity)
73  :head(0), tail(0), capacity(_capacity), data(_data) {}
74 
75  CircularBuffer(const CircularBuffer &other) = delete;
76 
77 protected:
78  constexpr size_type Next(size_type i) const {
79  return i + 1 == capacity
80  ? 0
81  : i + 1;
82  }
83 
84 public:
85  void Clear() {
86  head = tail = 0;
87  }
88 
89  constexpr size_type GetCapacity() const {
90  return capacity;
91  }
92 
93  constexpr bool IsEmpty() const {
94  return head == tail;
95  }
96 
97  constexpr bool IsFull() const {
98  return Next(tail) == head;
99  }
100 
104  constexpr size_type GetSize() const {
105  return head <= tail
106  ? tail - head
107  : capacity - head + tail;
108  }
109 
114  constexpr size_type GetSpace() const {
115  /* space = capacity - size - 1 */
116  return (head <= tail
117  ? capacity - tail + head
118  : head - tail)
119  - 1;
120  }
121 
127  assert(head < capacity);
128  assert(tail < capacity);
129 
130  size_type end = tail < head
131  ? head - 1
132  /* the "head==0" is there so we don't write
133  the last cell, as this situation cannot be
134  represented by head/tail */
135  : capacity - (head == 0);
136 
137  return Range(data + tail, end - tail);
138  }
139 
144  void Append(size_type n) {
145  assert(head < capacity);
146  assert(tail < capacity);
147  assert(n < capacity);
148  assert(tail + n <= capacity);
149  assert(head <= tail || tail + n < head);
150 
151  tail += n;
152 
153  if (tail == capacity) {
154  assert(head > 0);
155  tail = 0;
156  }
157  }
158 
164  assert(head < capacity);
165  assert(tail < capacity);
166 
167  return Range(data + head, (tail < head ? capacity : tail) - head);
168  }
169 
173  void Consume(size_type n) {
174  assert(head < capacity);
175  assert(tail < capacity);
176  assert(n < capacity);
177  assert(head + n <= capacity);
178  assert(tail < head || head + n <= tail);
179 
180  head += n;
181  if (head == capacity)
182  head = 0;
183  }
184 };
185 
186 #endif
size_type head
The next index to be read.
const pointer_type data
Range::pointer_type pointer_type
A reference to a memory area that is writable.
Definition: Silence.hxx:27
WritableBuffer< T > Range
constexpr bool IsFull() const
void Consume(size_type n)
Marks a chunk as consumed.
constexpr size_type GetSize() const
Returns the number of elements stored in this buffer.
constexpr size_type GetSpace() const
Returns the number of elements that can be added to this buffer.
Range Read()
Return a buffer range which may be read.
Range Write()
Prepares writing.
constexpr bool IsEmpty() const
A circular buffer.
void Append(size_type n)
Expands the tail of the buffer, after data has been written to the buffer returned by Write()...
constexpr size_type GetCapacity() const
size_type tail
The next index to be written to.
Range::size_type size_type
constexpr size_type Next(size_type i) const
const size_type capacity
constexpr CircularBuffer(pointer_type _data, size_type _capacity)