SPH
Queue.h
Go to the documentation of this file.
1 #pragma once
2 
7 
8 #include "math/MathUtils.h"
10 #include <mm_malloc.h>
11 
13 
15 template <typename T, typename TCounter = Size>
16 class Queue : public Noncopyable {
17 private:
18  using StorageType = typename WrapReferenceType<T>::Type;
19 
21  StorageType* data = nullptr;
22 
24  TCounter first = 0;
25 
27  TCounter last = 0;
28 
30  TCounter maxSize = 0;
31 
32 public:
34  Queue() = default;
35 
39  Queue(const TCounter size) {
40  this->alloc(size, 0, 0);
41  for (TCounter i = 0; i < maxSize; ++i) {
42  new (data + i) StorageType();
43  }
44  last = maxSize;
45  }
46 
50  Queue(std::initializer_list<StorageType> list) {
51  this->alloc(list.size(), 0, 0);
52  TCounter i = 0;
53  for (auto& l : list) {
54  new (data + i) StorageType(l);
55  i++;
56  }
57  last = maxSize;
58  }
59 
60  Queue(Queue&& other)
61  : data(other.data)
62  , first(other.first)
63  , last(other.last)
64  , maxSize(other.maxSize) {
65  other.data = nullptr;
66  other.first = other.last = other.maxSize = 0;
67  }
68 
69  ~Queue() {
70  for (TCounter i = first; i < last; ++i) {
71  data[i].~StorageType();
72  }
73  if (data) {
74  _mm_free(data);
75  data = nullptr;
76  }
77  }
78 
79  Queue& operator=(Queue&& other) {
80  std::swap(data, other.data);
81  std::swap(first, other.first);
82  std::swap(last, other.last);
83  std::swap(maxSize, other.maxSize);
84  return *this;
85  }
86 
90  INLINE T& operator[](const TCounter idx) {
91  SPH_ASSERT(idx < this->size());
92  return data[first + idx];
93  }
94 
98  INLINE const T& operator[](const TCounter idx) const {
99  SPH_ASSERT(idx < this->size());
100  return data[first + idx];
101  }
102 
106  INLINE T& front() {
107  SPH_ASSERT(!this->empty());
108  return data[first];
109  }
110 
114  INLINE const T& front() const {
115  SPH_ASSERT(!this->empty());
116  return data[first];
117  }
118 
122  INLINE T& back() {
123  SPH_ASSERT(!this->empty());
124  return data[last - 1];
125  }
126 
130  INLINE const T& back() const {
131  SPH_ASSERT(!this->empty());
132  return data[last - 1];
133  }
134 
138  INLINE Size size() const {
139  return last - first;
140  }
141 
145  INLINE bool empty() const {
146  return last == first;
147  }
148 
152  void pushFront(const T& value) {
153  if (first == 0) {
154  // no place for new elements, needs to resize
155  this->reserveFront(1);
156  }
157  SPH_ASSERT(first > 0);
158  --first;
159  new (data + first) StorageType();
160  data[first] = value;
161  }
162 
166  void pushBack(const T& value) {
167  if (last == maxSize) {
168  // no place for new elements, needs to resize
169  this->reserveBack(1);
170  }
171  SPH_ASSERT(last < maxSize);
172  ++last;
173  new (data + last - 1) StorageType();
174  data[last - 1] = value;
175  }
176 
180  T popFront() {
181  SPH_ASSERT(!this->empty());
182  T value = this->front();
183  data[first].~StorageType();
184  ++first;
185  return value;
186  }
187 
191  T popBack() {
192  SPH_ASSERT(!this->empty());
193  T value = this->back();
194  data[last - 1].~StorageType();
195  --last;
196  return value;
197  }
198 
202  void clear() {
203  for (TCounter i = first; i < last; ++i) {
204  data[i].~StorageType();
205  }
206  last = first;
207  }
208 
211  return Iterator<StorageType>(data + first, data + first, data + last);
212  }
213 
216  return Iterator<const StorageType>(data + first, data + first, data + last);
217  }
218 
221  return Iterator<StorageType>(data + last, data + first, data + last);
222  }
223 
226  return Iterator<const StorageType>(data + last, data + first, data + last);
227  }
228 
231  return ArrayView<T, TCounter>(data + first, this->size());
232  }
233 
236  return ArrayView<const T, TCounter>(data + first, this->size());
237  }
238 
239 
240 private:
243  void alloc(const TCounter size, const TCounter extraFront, const TCounter extraBack) {
244  maxSize = size + extraFront + extraBack;
245  first = last = extraFront;
246 
247  data = (StorageType*)_mm_malloc(maxSize * sizeof(StorageType), alignof(StorageType));
248  }
249 
252  void reserveFront(const TCounter num) {
253  if (num > first) {
254  Queue newQueue;
255  newQueue.alloc(this->size(), max(num, this->size()), min(maxSize - last, this->size()));
256  this->moveElements(std::move(newQueue));
257  }
258  SPH_ASSERT(num <= first);
259  }
260 
263  void reserveBack(const TCounter num) {
264  if (num > maxSize - last) {
265  Queue newQueue;
266  newQueue.alloc(this->size(), min(first, this->size()), max(num, this->size()));
267  this->moveElements(std::move(newQueue));
268  }
269  SPH_ASSERT(num <= maxSize - last);
270  }
271 
273  void moveElements(Queue&& newQueue) {
274  newQueue.last = newQueue.first + this->size();
275  SPH_ASSERT(newQueue.last <= newQueue.maxSize);
276 
277  // construct all element in the new queue using move constructor
278  for (TCounter i = 0; i < this->size(); ++i) {
279  new (newQueue.data + newQueue.first + i) StorageType(std::move(data[i + first]));
280  }
281  // replace queues
282  *this = std::move(newQueue);
283  }
284 };
285 
Simple non-owning view of a container.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
NAMESPACE_SPH_BEGIN constexpr INLINE T min(const T &f1, const T &f2)
Minimum & Maximum value.
Definition: MathBasic.h:15
Additional math routines (with more includes).
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
Object providing safe access to continuous memory of data.
Definition: ArrayView.h:17
Simple (forward) iterator over continuous array of objects of type T.
Definition: Iterator.h:18
Container allowing to add and remove elements from both ends.
Definition: Queue.h:16
void pushFront(const T &value)
Adds a new element to the front of the queue.
Definition: Queue.h:152
INLINE Iterator< StorageType > end()
Returns an iterator pointing to the one-past-last element of the queue.
Definition: Queue.h:220
Queue()=default
Constructs an empty queue.
T popBack()
Removes an element from the back of the queue.
Definition: Queue.h:191
INLINE bool empty() const
Returns true if the queue contains no elements.
Definition: Queue.h:145
INLINE T & operator[](const TCounter idx)
Returns a reference to idx-th element in the queue.
Definition: Queue.h:90
Queue(const TCounter size)
Constructs a queue with given number of elements.
Definition: Queue.h:39
INLINE Iterator< const StorageType > end() const
Returns a const iterator pointing to the one-past-last element of the queue.
Definition: Queue.h:225
INLINE T & back()
Returns a reference to the last element in the queue.
Definition: Queue.h:122
INLINE const T & operator[](const TCounter idx) const
Returns a const reference to idx-th element in the queue.
Definition: Queue.h:98
INLINE Size size() const
Returns the number of elements in the queue.
Definition: Queue.h:138
~Queue()
Definition: Queue.h:69
Queue(Queue &&other)
Definition: Queue.h:60
INLINE const T & back() const
Returns a const reference to the last element in the queue.
Definition: Queue.h:130
INLINE Iterator< StorageType > begin()
Returns an iterator pointing to the first element of the queue.
Definition: Queue.h:210
INLINE const T & front() const
Returns a const reference to the first element in the queue.
Definition: Queue.h:114
INLINE Iterator< const StorageType > begin() const
Returns a const iterator pointing to the first element of the queue.
Definition: Queue.h:215
void clear()
Removes all elements from the queue.
Definition: Queue.h:202
Queue & operator=(Queue &&other)
Definition: Queue.h:79
Queue(std::initializer_list< StorageType > list)
Constructs a queue from initializer list.
Definition: Queue.h:50
INLINE T & front()
Returns a reference to the first element in the queue.
Definition: Queue.h:106
T popFront()
Removes an element from the front of the queue.
Definition: Queue.h:180
void pushBack(const T &value)
Adds a new element to the back of the queue.
Definition: Queue.h:166
void swap(Sph::Array< T, TCounter > &ar1, Sph::Array< T, TCounter > &ar2)
Definition: Array.h:580
Object with deleted copy constructor and copy operator.
Definition: Object.h:54