Evo C++ Library v0.5.1
buffer_queue.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_evo_buffer_queue_h
9 #define INCL_evo_buffer_queue_h
10 
11 #include "type.h"
12 
13 namespace evo {
16 
18 
58 template<class T, class TSize=SizeT>
59 class BufferQueue {
60 public:
62  typedef TSize Size;
63  typedef T Item;
64 
65  static const Size MIN_SIZE = 2;
66  static const Size DEFAULT_SIZE = 128;
67 
71  BufferQueue(Size size=DEFAULT_SIZE) {
72  size = adjust_size(size);
73  buf_ = new T[size];
74  size_ = size;
75  size_mask_ = size - 1;
76  used_ = 0;
77  start_ = 0;
78  }
79 
85  BufferQueue(const This& src) {
86  buf_ = new T[src.size_];
87  size_ = src.size_;
88  size_mask_ = src.size_mask_;
89  used_ = src.used_;
90  start_ = src.start_;
91  copydata(src);
92  }
93 
96  delete [] buf_;
97  }
98 
102  Size size() const {
103  return size_;
104  }
105 
109  Size used() const {
110  return used_;
111  }
112 
116  bool empty() const {
117  return (used_ == 0);
118  }
119 
123  bool full() const {
124  return (used_ >= size_);
125  }
126 
128  void clear() {
129  used_ = 0;
130  start_ = 0;
131  }
132 
140  bool add(const T& item, bool force=false) {
141  if (used_ < size_) {
142  buf_[((uint64)start_ + used_) & size_mask_] = item;
143  ++used_;
144  return true;
145  } else if (force) {
146  buf_[start_] = item;
147  start_ = (start_ + 1) & size_mask_;
148  }
149  return false;
150  }
151 
159  T* advAdd(bool force=false) {
160  if (used_ < size_) {
161  return buf_ + (((uint64)start_ + used_++) & size_mask_);
162  } else if (force) {
163  T* item = buf_ + start_;
164  start_ = (start_ + 1) & size_mask_;
165  return item;
166  }
167  return NULL;
168  }
169 
175  const T& peek() const {
176  return buf_[start_];
177  }
178 
187  const T* peek(Size& size) const {
188  if (used_ > 0) {
189  size = size_ - start_;
190  if (size > used_)
191  size = used_;
192  return buf_ + start_;
193  }
194  size = 0;
195  return NULL;
196  }
197 
205  bool pop(T& item) {
206  if (used_ > 0) {
207  item = buf_[start_];
208  start_ = (start_ + 1) & size_mask_;
209  --used_;
210  return true;
211  }
212  return false;
213  }
214 
221  bool pop() {
222  if (used_ > 0) {
223  start_ = (start_ + 1) & size_mask_;
224  --used_;
225  return true;
226  }
227  return false;
228  }
229 
237  Size pop_size(Size size) {
238  if (used_ > 0) {
239  if (size > used_)
240  size = used_;
241  start_ = (Size)(((uint64)start_ + size) & size_mask_);
242  used_ -= size;
243  return size;
244  }
245  return 0;
246  }
247 
254  This& operator=(const This& src) {
255  if (size_ != src.size_) {
256  delete [] buf_;
257  buf_ = new T[src.size_];
258  size_mask_ = src.size_mask_;
259  size_ = src.size_;
260  }
261  used_ = src.used_;
262  start_ = src.start_;
263  copydata(src);
264  return *this;
265  }
266 
267 private:
268  T* buf_;
269  Size size_;
270  Size size_mask_;
271  Size used_;
272  Size start_;
273 
274  // This assumes buf_ is allocated and everything but buf_ data has been copied
275  void copydata(const This& src) {
276  if (used_ > 0) {
277  Size copysize = size_ - start_;
278  DataInit<T>::copy(buf_ + start_, src.buf_ + start_, copysize);
279  if (copysize < used_) {
280  copysize = used_ - copysize;
281  DataInit<T>::copy(buf_, src.buf_, copysize);
282  }
283  }
284  }
285 
286  // Make sure size is a power of 2
287  static Size adjust_size(Size size) {
288  assert( !IntegerT<Size>::SIGN );
289  const Size MAX_SIZE = (IntegerT<Size>::MAX >> 1) + 1;
290  if (size <= MIN_SIZE) {
291  size = MIN_SIZE;
292  } else if (size >= MAX_SIZE) {
293  size = MAX_SIZE;
294  } else {
295  const Size targetsize = size;
296  size = MIN_SIZE;
297  while (size < targetsize)
298  size <<= 1;
299  }
300  return size;
301  }
302 };
303 
305 
306 }
307 #endif
static void copy(Item *dest, const Item *src, ulong size)
Copy already initialized data (assignment operator).
Definition: container.h:297
T * advAdd(bool force=false)
Advanced: Add new item to queue and get pointer to it.
Definition: buffer_queue.h:159
Size used() const
Get used item count.
Definition: buffer_queue.h:109
BufferQueue(const This &src)
Copy constructor.
Definition: buffer_queue.h:85
bool full() const
Get whether queue is full.
Definition: buffer_queue.h:123
This & operator=(const This &src)
Assignment operator.
Definition: buffer_queue.h:254
Fast buffer-based queue, implemented with a ring-buffer.
Definition: buffer_queue.h:59
TSize Size
Queue size integer type (always unsigned)
Definition: buffer_queue.h:62
Basic integer type.
Definition: type.h:980
static const Size MIN_SIZE
Minimum size to use.
Definition: buffer_queue.h:65
const T & peek() const
Peek at oldest item in queue.
Definition: buffer_queue.h:175
static const Size DEFAULT_SIZE
Default size to use.
Definition: buffer_queue.h:66
bool add(const T &item, bool force=false)
Add item to queue.
Definition: buffer_queue.h:140
Size pop_size(Size size)
Pop oldest items from queue in bulk.
Definition: buffer_queue.h:237
bool pop()
Pop oldest item from queue without returning it.
Definition: buffer_queue.h:221
BufferQueue(Size size=DEFAULT_SIZE)
Constructor, sets buffer size.
Definition: buffer_queue.h:71
BufferQueue< T, TSize > This
This type
Definition: buffer_queue.h:61
Evo C++ Library namespace.
Definition: alg.h:11
Size size() const
Get buffer size.
Definition: buffer_queue.h:102
bool pop(T &item)
Pop oldest item from queue.
Definition: buffer_queue.h:205
const T * peek(Size &size) const
Peek at oldest items in queue.
Definition: buffer_queue.h:187
bool empty() const
Get whether queue is empty.
Definition: buffer_queue.h:116
~BufferQueue()
Destructor.
Definition: buffer_queue.h:95
T Item
Item type.
Definition: buffer_queue.h:63
void clear()
Clear all items from queue, making it empty.
Definition: buffer_queue.h:128
Evo basic types and traits.