stream  0.10.0
stream analysis framework
Queue.h
1 #ifndef BASE_QUEUE_H
2 #define BASE_QUEUE_H
3 
4 #include <cstring>
5 
6 #include <stdexcept>
7 
8 namespace base {
9 
12  template<class T, bool canexpand = false>
13  class Queue {
14 
15  public:
17  class Iterator {
18 
19  friend class Queue<T,canexpand>;
20 
21  Queue<T,canexpand>* prnt;
22  T* item;
23  unsigned loop;
24 
26  Iterator(Queue<T,canexpand>* _prnt, T* _item, unsigned _loop) : prnt(_prnt), item(_item), loop(_loop) {}
27 
28  public:
29 
31  Iterator() : prnt(0), item(0) {}
33  Iterator(const Iterator& src) : prnt(src.prnt), item(src.item), loop(src.loop) {}
34 
36  T* operator()() const { return item; }
37 
39  bool operator==(const Iterator& src) const { return (item == src.item) && (loop == src.loop); }
41  bool operator!=(const Iterator& src) const { return (item != src.item) || (loop != src.loop); }
42 
44  Iterator& operator=(const Iterator& src) { prnt = src.prnt; item = src.item; return *this; }
45 
48  {
49  if (++item == prnt->fBorder) { item = prnt->fQueue; loop++; }
50  return *this;
51  }
52 
54  void operator++(int)
55  {
56  if (++item == prnt->fBorder) { item = prnt->fQueue; loop++; }
57  }
58  };
59 
60  protected:
61 
62  friend class Queue<T,canexpand>::Iterator;
63 
64  T* fQueue;
65  T* fBorder;
66  unsigned fCapacity;
67  unsigned fSize;
68  T* fHead;
69  T* fTail;
70  unsigned fInitSize;
71 
72  public:
74  Queue() :
75  fQueue(0),
76  fBorder(0),
77  fCapacity(0),
78  fSize(0),
79  fHead(0),
80  fTail(0),
81  fInitSize(0)
82  {
83  }
84 
86  Queue(unsigned _capacity) :
87  fQueue(0),
88  fBorder(0),
89  fCapacity(0),
90  fSize(0),
91  fHead(0),
92  fTail(0),
93  fInitSize(_capacity)
94  {
95  Allocate(_capacity);
96  }
97 
99  virtual ~Queue()
100  {
101  delete[] fQueue;
102  fQueue = 0;
103  }
104 
106  void Init(unsigned _capacity)
107  {
108  fInitSize = _capacity;
109  Allocate(_capacity);
110  }
111 
113  void Allocate(unsigned _capacity)
114  {
115  if (fCapacity>0) {
116  delete[] fQueue;
117  fCapacity = 0;
118  fQueue = 0;
119  fBorder = 0;
120  }
121 
122  if (_capacity>0) {
123  fCapacity = _capacity;
124  fSize = 0;
125  fQueue = new T [fCapacity];
127  fHead = fQueue;
128  fTail = fQueue;
129  }
130  }
131 
134  virtual void CopyTo(T* tgt)
135  {
136  if (fSize>0) {
137  if (fHead>fTail) {
138  memcpy((void *) tgt, fTail, (fHead - fTail) * sizeof(T));
139  } else {
140  unsigned sz = fBorder - fTail;
141  memcpy((void *) tgt, fTail, sz * sizeof(T));
142  memcpy((void *) (tgt + sz), fQueue, (fHead - fQueue) * sizeof(T));
143  }
144  }
145  }
146 
148  bool Expand(unsigned newcapacity = 0)
149  {
150  if (!canexpand) return false;
151 
152  if (newcapacity <= fCapacity)
153  newcapacity = fCapacity * 2;
154  if (newcapacity < 16) newcapacity = 16;
155  T* q = new T [newcapacity];
156  if (q==0) return false;
157 
158  CopyTo(q);
159 
160  delete [] fQueue;
161 
162  fCapacity = newcapacity;
163  fQueue = q;
165  fHead = fQueue + fSize; // we are sure that size less than capacity
166  fTail = fQueue;
167  return true;
168  }
169 
171  bool Remove(T value)
172  {
173  if (size()==0) return false;
174 
175  T *i_tgt(fTail), *i_src(fTail);
176 
177  do {
178  if (*i_src != value) {
179  if (i_tgt!=i_src) *i_tgt = *i_src;
180  if (++i_tgt == fBorder) i_tgt = fQueue;
181  } else
182  fSize--;
183  if (++i_src == fBorder) i_src = fQueue;
184  } while (i_src != fHead);
185 
186  fHead = i_tgt;
187 
188  return i_tgt != i_src;
189  }
190 
192  bool erase_item(unsigned indx)
193  {
194  if (indx>=fSize) return false;
195 
196  T* tgt = fTail + indx;
197  if (tgt>=fBorder) tgt -= fCapacity;
198 
199  while (true) {
200  T* src = tgt + 1;
201  if (src==fBorder) src = fQueue;
202  if (src==fHead) break;
203  *tgt = *src;
204  tgt = src;
205  }
206 
207  fHead = tgt;
208  fSize--;
209  return true;
210  }
211 
214  {
215  return (fSize<fCapacity) || Expand();
216  }
217 
219  void push(const T& val)
220  {
221  if ((fSize<fCapacity) || Expand()) {
222  *fHead++ = val;
223  if (fHead==fBorder) fHead = fQueue;
224  fSize++;
225  } else {
226  throw std::runtime_error("No more space in fixed-size queue");
227  }
228  }
229 
232  {
233  if ((fSize<fCapacity) || Expand()) {
234  T* res = fHead;
235  if (++fHead==fBorder) fHead = fQueue;
236  fSize++;
237  return res;
238  }
239 
240  throw std::runtime_error("No more space in fixed queue size");
241  return 0;
242  }
243 
245  void pop()
246  {
247  if (fSize > 0) {
248  fSize--;
249  if (++fTail==fBorder) fTail = fQueue;
250  }
251  }
252 
255  {
256  #ifdef DABC_EXTRA_CHECKS
257  if (fSize==0) EOUT(("Queue is empty"));
258  #endif
259  T* res = fTail++;
260  if (fTail==fBorder) fTail = fQueue;
261  fSize--;
262  return *res;
263  }
264 
266  T& front() const
267  {
268  #ifdef DABC_EXTRA_CHECKS
269  if (fSize==0) EOUT(("Queue is empty"));
270  #endif
271  return *fTail;
272  }
273 
275  T& item(unsigned indx) const
276  {
277  #ifdef DABC_EXTRA_CHECKS
278  if (indx>=fSize)
279  EOUT(("Wrong item index %u", indx));
280  #endif
281  T* _item = fTail + indx;
282  if (_item>=fBorder) _item -= fCapacity;
283  return *_item;
284  }
285 
287  T* item_ptr(unsigned indx) const
288  {
289  #ifdef DABC_EXTRA_CHECKS
290  if (indx>=fSize) {
291  EOUT(("Wrong item index %u", indx));
292  return 0;
293  }
294  #endif
295  T* _item = fTail + indx;
296  if (_item>=fBorder) _item -= fCapacity;
297  return _item;
298  }
299 
301  T& back() const
302  {
303  #ifdef DABC_EXTRA_CHECKS
304  if (fSize==0) EOUT(("Queue is empty"));
305  #endif
306  return item(fSize-1);
307  }
308 
310  void clear()
311  {
312  fHead = fQueue;
313  fTail = fQueue;
314  fSize = 0;
315  }
316 
318  unsigned capacity() const { return fCapacity; }
319 
321  unsigned size() const { return fSize; }
322 
324  bool full() const { return capacity() == size(); }
325 
327  bool empty() const { return size() == 0; }
328 
330  Iterator begin() { return Iterator(this, fTail, 0); }
332  Iterator end() { return Iterator(this, fHead, fHead > fTail ? 0 : 1); }
333  };
334 
335  // ___________________________________________________________
336 
355  template<class T, bool canexpand = true>
356  class RecordsQueue : public Queue<T, canexpand> {
357  typedef Queue<T, canexpand> Parent;
358  public:
361 
363  RecordsQueue(unsigned _capacity) : Parent(_capacity) {}
364 
366  T& front() const { return Parent::front(); }
367 
369  T& back() const { return Parent::back(); }
370 
372  unsigned capacity() const { return Parent::capacity(); }
373 
375  unsigned size() const { return Parent::size(); }
376 
378  bool full() const { return Parent::full(); }
379 
381  bool empty() const { return Parent::empty(); }
382 
384  T& item(unsigned indx) const { return Parent::item(indx); }
385 
387  T* item_ptr(unsigned indx) const { return Parent::item_ptr(indx); }
388 
390  void pop() { front().reset(); Parent::pop(); }
391 
394  {
395  T res = front();
396  pop();
397  return res;
398  }
399 
401  void pop_items(unsigned cnt)
402  {
403  if (cnt>=size()) {
404  clear();
405  } else {
406  while (cnt-->0) pop();
407  }
408  }
409 
411  void clear()
412  {
415  } else {
416  for (unsigned n=0;n<size();n++)
417  item(n).reset();
418  Parent::clear();
419  }
420  }
421 
423  bool erase_item(unsigned indx)
424  {
425  bool res = Parent::erase_item(indx);
426 
427  // after item was removed from inside queue,
428  // head element now pointer on item which was not cleared
429  if (res) Parent::fHead->reset();
430 
431  return res;
432  }
433 
434 
435  };
436 
437 }
438 
439 #endif
440 
iterator over raw data messages
Definition: Iterator.h:10
iterator over queue elements
Definition: Queue.h:17
Iterator(const Iterator &src)
constructor
Definition: Queue.h:33
Iterator & operator++()
prefix ++iter
Definition: Queue.h:47
bool operator!=(const Iterator &src) const
compare operator
Definition: Queue.h:41
bool operator==(const Iterator &src) const
compare operator
Definition: Queue.h:39
Iterator()
constructor
Definition: Queue.h:31
void operator++(int)
postfix iter++
Definition: Queue.h:54
T * operator()() const
get current item
Definition: Queue.h:36
Iterator & operator=(const Iterator &src)
assign operator
Definition: Queue.h:44
queue class
Definition: Queue.h:13
Iterator begin()
begin iterator
Definition: Queue.h:330
T * fTail
tail
Definition: Queue.h:69
bool Expand(unsigned newcapacity=0)
increase capacity of queue without lost of content
Definition: Queue.h:148
void clear()
clear queue
Definition: Queue.h:310
void push(const T &val)
push value
Definition: Queue.h:219
Queue(unsigned _capacity)
constructor with capacity
Definition: Queue.h:86
T * item_ptr(unsigned indx) const
provide item pointer
Definition: Queue.h:287
T * PushEmpty()
push empty, return pointer on place
Definition: Queue.h:231
T pop_front()
pop front element
Definition: Queue.h:254
T & item(unsigned indx) const
access arbitrary item
Definition: Queue.h:275
virtual ~Queue()
destructor
Definition: Queue.h:99
unsigned fCapacity
capacity
Definition: Queue.h:66
T * fQueue
queue
Definition: Queue.h:64
bool Remove(T value)
remove value from queue
Definition: Queue.h:171
Iterator end()
end iterator
Definition: Queue.h:332
T * fBorder
maximum pointer value
Definition: Queue.h:65
T & back() const
access back element
Definition: Queue.h:301
void Init(unsigned _capacity)
init queue
Definition: Queue.h:106
unsigned size() const
return queue size
Definition: Queue.h:321
unsigned fSize
size
Definition: Queue.h:67
void Allocate(unsigned _capacity)
allocate queue
Definition: Queue.h:113
bool erase_item(unsigned indx)
erase item with index
Definition: Queue.h:192
unsigned fInitSize
original size of the queue, restored then clear() method is called
Definition: Queue.h:70
T * fHead
head
Definition: Queue.h:68
virtual void CopyTo(T *tgt)
Method can be used to copy content of the queue into externally allocated array.
Definition: Queue.h:134
void pop()
pop element
Definition: Queue.h:245
bool MakePlaceForNext()
create place for next entry
Definition: Queue.h:213
unsigned capacity() const
return queue capacity
Definition: Queue.h:318
bool full() const
is queue full
Definition: Queue.h:324
T & front() const
access front element
Definition: Queue.h:266
bool empty() const
is queue empty
Definition: Queue.h:327
Special case of the queue when structure or class is used as entry of the queue.
Definition: Queue.h:356
unsigned size() const
size
Definition: Queue.h:375
T * item_ptr(unsigned indx) const
item pointer
Definition: Queue.h:387
RecordsQueue()
default constructor
Definition: Queue.h:360
T & back() const
back element
Definition: Queue.h:369
bool erase_item(unsigned indx)
erase item
Definition: Queue.h:423
RecordsQueue(unsigned _capacity)
construct queue with given capacity
Definition: Queue.h:363
bool empty() const
is queue empty
Definition: Queue.h:381
unsigned capacity() const
capacity
Definition: Queue.h:372
void pop_items(unsigned cnt)
pop several items
Definition: Queue.h:401
T pop_front()
pop item and return it
Definition: Queue.h:393
T & item(unsigned indx) const
item reference
Definition: Queue.h:384
T & front() const
front element
Definition: Queue.h:366
void clear()
clear queue
Definition: Queue.h:411
bool full() const
is queue full
Definition: Queue.h:378
void pop()
pop item
Definition: Queue.h:390