DABC (Data Acquisition Backbone Core)  2.9.9
Queue.h
Go to the documentation of this file.
1 // $Id: Queue.h 4474 2020-04-15 13:47:01Z linev $
2 
3 /************************************************************
4  * The Data Acquisition Backbone Core (DABC) *
5  ************************************************************
6  * Copyright (C) 2009 - *
7  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
8  * Planckstr. 1, 64291 Darmstadt, Germany *
9  * Contact: http://dabc.gsi.de *
10  ************************************************************
11  * This software can be used under the GPL license *
12  * agreements as stated in LICENSE.txt file *
13  * which is part of the distribution. *
14  ************************************************************/
15 
16 #ifndef DABC_Queue
17 #define DABC_Queue
18 
19 #include <cstring>
20 
21 #include <vector>
22 
23 #ifndef DABC_logging
24 #include "dabc/logging.h"
25 #endif
26 
27 #ifndef DABC_defines
28 #include "dabc/defines.h"
29 #endif
30 
31 
32 namespace dabc {
33 
40  template<class T, bool canexpand = false>
41  class Queue {
42 
43  public:
44  class Iterator {
45 
46  friend class Queue<T,canexpand>;
47 
49  T* item{nullptr};
50  unsigned loop{0};
51 
52  Iterator(Queue<T,canexpand>* _prnt, T* _item, unsigned _loop) : prnt(_prnt), item(_item), loop(_loop) {}
53 
54  public:
55 
56  Iterator() = default;
57  Iterator(const Iterator& src) : prnt(src.prnt), item(src.item), loop(src.loop) {}
58 
59  T* operator()() const { return item; }
60 
61  bool operator==(const Iterator& src) const { return (item == src.item) && (loop == src.loop); }
62  bool operator!=(const Iterator& src) const { return (item != src.item) || (loop != src.loop); }
63 
64  Iterator& operator=(const Iterator& src) { prnt = src.prnt; item = src.item; return *this; }
65 
66  // prefix ++iter
68  {
69  if (++item == prnt->fBorder) { item = prnt->fQueue; loop++; }
70  return *this;
71  }
72 
73  // postfix iter++
74  void operator++(int)
75  {
76  if (++item == prnt->fBorder) { item = prnt->fQueue; loop++; }
77  }
78  };
79 
80 
81  protected:
82 
83  friend class Queue<T,canexpand>::Iterator;
84 
85  T* fQueue{nullptr};
86  T* fBorder{nullptr}; // maximum pointer value
87  unsigned fCapacity{0};
88  unsigned fSize{0};
89  T* fHead{nullptr};
90  T* fTail{nullptr};
91  unsigned fInitSize{0};
92 
93  T* QueueItem(unsigned n) { return fQueue + n; }
94 
95  public:
96  Queue() = default;
97 
98  Queue(unsigned capacity)
99  {
100  Init(capacity);
101  }
102 
103  virtual ~Queue()
104  {
105  delete[] fQueue;
106  fQueue = nullptr;
107  }
108 
109  void Init(unsigned capacity)
110  {
111  fInitSize = capacity;
112  Allocate(capacity);
113  }
114 
115  void Allocate(unsigned capacity)
116  {
117  if (fCapacity>0) {
118  delete[] fQueue;
119  fCapacity = 0;
120  fQueue = nullptr;
121  fBorder = 0;
122  }
123 
124  if (capacity>0) {
125  fCapacity = capacity;
126  fSize = 0;
127  fQueue = new T [fCapacity];
129  fHead = fQueue;
130  fTail = fQueue;
131  }
132  }
133 
136  virtual void CopyTo(T* tgt)
137  {
138  if (fSize>0) {
139  if (fHead>fTail) {
140  memcpy((void *)tgt, (const void *)fTail, (fHead - fTail) * sizeof(T));
141  } else {
142  unsigned sz = fBorder - fTail;
143  memcpy((void *)tgt, (const void *) fTail, sz * sizeof(T));
144  memcpy((void *) (tgt + sz), (const void *) fQueue, (fHead - fQueue) * sizeof(T));
145  }
146  }
147  }
148 
149  // increase capacity of queue without lost of content
150  bool Expand(unsigned newcapacity = 0)
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 
170  bool Remove(T value)
171  {
172  if (Size()==0) return false;
173 
174  T *i_tgt(fTail), *i_src(fTail);
175 
176  do {
177  if (*i_src != value) {
178  if (i_tgt!=i_src) *i_tgt = *i_src;
179  if (++i_tgt == fBorder) i_tgt = fQueue;
180  } else
181  fSize--;
182  if (++i_src == fBorder) i_src = fQueue;
183  } while (i_src != fHead);
184 
185  fHead = i_tgt;
186 
187  return i_tgt != i_src;
188  }
189 
190  bool RemoveItem(unsigned indx)
191  {
192  if (indx>=fSize) return false;
193 
194  T* tgt = fTail + indx;
195  if (tgt>=fBorder) tgt -= fCapacity;
196 
197  while (true) {
198  T* src = tgt + 1;
199  if (src==fBorder) src = fQueue;
200  if (src==fHead) break;
201  *tgt = *src;
202  tgt = src;
203  }
204 
205  fHead = tgt;
206  fSize--;
207  return true;
208  }
209 
211  {
212  return (fSize<fCapacity) || (canexpand && Expand());
213  }
214 
215  void Push(T val)
216  {
217  if (MakePlaceForNext()) {
218  *fHead++ = val;
219  if (fHead==fBorder) fHead = fQueue;
220  fSize++;
221  } else {
222  EOUT("No more space in fixed queue size = %d", fSize);
223  }
224  }
225 
227  {
228  if (MakePlaceForNext()) {
229  T* res = fHead;
230  if (++fHead==fBorder) fHead = fQueue;
231  fSize++;
232  return res;
233  }
234 
235  EOUT("No more space in fixed queue size = %d", fSize);
236  return 0;
237  }
238 
239 
240  void PushRef(const T& val)
241  {
242  if (MakePlaceForNext()) {
243  *fHead++ = val;
244  if (fHead==fBorder) fHead = fQueue;
245  fSize++;
246  } else {
247  EOUT("No more space in fixed queue size = %d", fSize);
248  }
249  }
250 
251  void PopOnly()
252  {
253  if (fSize>0) {
254  fSize--;
255  if (++fTail==fBorder) fTail = fQueue;
256  }
257  }
258 
259  T Pop()
260  {
261  #ifdef DABC_EXTRA_CHECKS
262  if (fSize==0) EOUT("Queue is empty");
263  #endif
264  T* res = fTail++;
265  if (fTail==fBorder) fTail = fQueue;
266  fSize--;
267  return *res;
268  }
269 
270  T& Front() const
271  {
272  #ifdef DABC_EXTRA_CHECKS
273  if (fSize==0) EOUT("Queue is empty");
274  #endif
275  return *fTail;
276  }
277 
278  // TODO: implement iterator to access all items in the queue
279 
280  T& Item(unsigned indx) const
281  {
282  #ifdef DABC_EXTRA_CHECKS
283  if (indx>=fSize)
284  EOUT("Wrong item index %u", indx);
285  #endif
286  T* item = fTail + indx;
287  if (item>=fBorder) item -= fCapacity;
288  return *item;
289  }
290 
291  T* ItemPtr(unsigned indx) const
292  {
293  #ifdef DABC_EXTRA_CHECKS
294  if (indx>=fSize) {
295  EOUT("Wrong item index %u", indx);
296  return 0;
297  }
298  #endif
299  T* item = fTail + indx;
300  if (item>=fBorder) item -= fCapacity;
301  return item;
302  }
303 
304  T& Back() const
305  {
306  #ifdef DABC_EXTRA_CHECKS
307  if (fSize==0) EOUT("Queue is empty");
308  #endif
309  return Item(fSize-1);
310  }
311 
312  void Reset()
313  {
314  fHead = fQueue;
315  fTail = fQueue;
316  fSize = 0;
317  }
318 
319  unsigned Capacity() const { return fCapacity; }
320 
321  unsigned Size() const { return fSize; }
322 
323  bool Full() const { return Capacity() == Size(); }
324 
325  bool Empty() const { return Size() == 0; }
326 
327  Iterator begin() { return Iterator(this, fTail, 0); }
328  Iterator end() { return Iterator(this, fHead, fHead > fTail ? 0 : 1); }
329  };
330 
331  // ___________________________________________________________
332 
340  class PointersVector : public std::vector<void*> {
341  public:
342  PointersVector() : std::vector<void*>() {}
343 
344  void* pop()
345  {
346  if (size()==0) return 0;
347  void* res = back();
348  pop_back();
349  return res;
350  }
351 
352  bool has_ptr(void* item) const
353  {
354  for (unsigned n=0; n<size(); n++)
355  if (at(n)==item) return true;
356  return false;
357  }
358 
359  bool remove_at(unsigned n)
360  {
361  if (n>=size()) return false;
362  erase(begin()+n);
363  return true;
364  }
365 
366  bool remove(void* item)
367  {
368  for (iterator iter = begin(); iter!=end(); iter++)
369  if (*iter == item) {
370  erase(iter);
371  return true;
372  }
373  return false;
374  }
375  };
376 
377 
378  // ___________________________________________________________
379 
401  template<class T, bool canexpand = true>
402  class RecordsQueue : public Queue<T, canexpand> {
404  public:
406 
407  virtual ~RecordsQueue() {}
408 
409  RecordsQueue(unsigned capacity) : Parent(capacity) {}
410 
411  void Allocate(unsigned capacity) { Parent::Allocate(capacity); }
412 
413  bool Empty() const { return Parent::Empty(); }
414 
415  bool Full() const { return Parent::Full(); }
416 
417  unsigned Size() const { return Parent::Size(); }
418 
419  unsigned Capacity() const { return Parent::Capacity(); }
420 
421  T& Item(unsigned n) const { return Parent::Item(n); }
422 
423  void Push(const T& val) { Parent::PushRef(val); }
424 
425  T& Front() const { return Parent::Front(); }
426 
427  T& Back() const { return Parent::Back(); }
428 
429  void PopOnly() { Front().reset(); Parent::PopOnly(); }
430 
431  virtual void CopyTo(T* tgt)
432  {
433  for (unsigned n=0; n<Size(); n++)
434  *tgt++ = Item(n);
435  }
436 
437  T* PushEmpty() { return Parent::PushEmpty(); }
438 
439  void Reset()
440  {
443  else {
444  for (unsigned n=0;n<Size();n++)
445  Item(n).reset();
446  Parent::Reset();
447  }
448  }
449 
450  template<class DDD>
451  T* FindItemWithId(DDD id)
452  {
453  for (unsigned n=0;n<Size();n++) {
454  T* item = &Item(n);
455  if (item->id()==id) return item;
456  }
457  return 0;
458  }
459 
461  void AllocateRecs(unsigned rec_capacity)
462  {
463  for (unsigned n=0;n<Capacity();n++)
464  Parent::QueueItem(n)->allocate(rec_capacity);
465  }
466 
467  };
468 
469 }
470 
471 #endif
472 
Specialized vector with pointers.
Definition: Queue.h:340
bool remove_at(unsigned n)
Definition: Queue.h:359
bool has_ptr(void *item) const
Definition: Queue.h:352
bool remove(void *item)
Definition: Queue.h:366
void * pop()
Definition: Queue.h:344
Queue< T, canexpand > * prnt
Definition: Queue.h:48
void operator++(int)
Definition: Queue.h:74
T * operator()() const
Definition: Queue.h:59
bool operator==(const Iterator &src) const
Definition: Queue.h:61
bool operator!=(const Iterator &src) const
Definition: Queue.h:62
Iterator(const Iterator &src)
Definition: Queue.h:57
Iterator(Queue< T, canexpand > *_prnt, T *_item, unsigned _loop)
Definition: Queue.h:52
Iterator & operator++()
Definition: Queue.h:67
unsigned loop
Definition: Queue.h:50
Iterator & operator=(const Iterator &src)
Definition: Queue.h:64
Template of circular queue.
Definition: Queue.h:41
Queue(unsigned capacity)
Definition: Queue.h:98
bool Expand(unsigned newcapacity=0)
Definition: Queue.h:150
T * fHead
Definition: Queue.h:89
void Init(unsigned capacity)
Definition: Queue.h:109
T * fTail
Definition: Queue.h:90
bool RemoveItem(unsigned indx)
Definition: Queue.h:190
bool Full() const
Definition: Queue.h:323
Iterator begin()
Definition: Queue.h:327
bool Remove(T value)
Definition: Queue.h:170
void PushRef(const T &val)
Definition: Queue.h:240
unsigned Size() const
Definition: Queue.h:321
T & Front() const
Definition: Queue.h:270
Iterator end()
Definition: Queue.h:328
unsigned fCapacity
Definition: Queue.h:87
T * ItemPtr(unsigned indx) const
Definition: Queue.h:291
T * fQueue
Definition: Queue.h:85
unsigned fInitSize
original size of the queue, restored then Reset() method is called
Definition: Queue.h:91
virtual ~Queue()
Definition: Queue.h:103
T Pop()
Definition: Queue.h:259
virtual void CopyTo(T *tgt)
Method can be used to copy content of the queue into externally allocated array.
Definition: Queue.h:136
bool Empty() const
Definition: Queue.h:325
T * PushEmpty()
Definition: Queue.h:226
bool MakePlaceForNext()
Definition: Queue.h:210
void Push(T val)
Definition: Queue.h:215
T & Back() const
Definition: Queue.h:304
void Reset()
Definition: Queue.h:312
unsigned Capacity() const
Definition: Queue.h:319
T * fBorder
Definition: Queue.h:86
T * QueueItem(unsigned n)
Definition: Queue.h:93
unsigned fSize
Definition: Queue.h:88
void Allocate(unsigned capacity)
Definition: Queue.h:115
T & Item(unsigned indx) const
Definition: Queue.h:280
void PopOnly()
Definition: Queue.h:251
Queue()=default
Template of queue with complex objects.
Definition: Queue.h:402
T * FindItemWithId(DDD id)
Definition: Queue.h:451
Queue< T, canexpand > Parent
Definition: Queue.h:403
virtual ~RecordsQueue()
Definition: Queue.h:407
T * PushEmpty()
Definition: Queue.h:437
bool Full() const
Definition: Queue.h:415
virtual void CopyTo(T *tgt)
Method can be used to copy content of the queue into externally allocated array.
Definition: Queue.h:431
void AllocateRecs(unsigned rec_capacity)
Helper methods to preallocate memory in each record in the queue.
Definition: Queue.h:461
void PopOnly()
Definition: Queue.h:429
T & Back() const
Definition: Queue.h:427
bool Empty() const
Definition: Queue.h:413
unsigned Capacity() const
Definition: Queue.h:419
RecordsQueue(unsigned capacity)
Definition: Queue.h:409
unsigned Size() const
Definition: Queue.h:417
T & Front() const
Definition: Queue.h:425
void Reset()
Definition: Queue.h:439
void Allocate(unsigned capacity)
Definition: Queue.h:411
T & Item(unsigned n) const
Definition: Queue.h:421
void Push(const T &val)
Definition: Queue.h:423
#define EOUT(args ...)
Definition: logging.h:150
Event manipulation API.
Definition: api.h:23