Embedded Template Library  1.0
queue.h
Go to the documentation of this file.
1 
3 /******************************************************************************
4 The MIT License(MIT)
5 
6 Embedded Template Library.
7 https://github.com/ETLCPP/etl
8 https://www.etlcpp.com
9 
10 Copyright(c) 2014 jwellbelove, Mark Kitson
11 
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files(the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions :
18 
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21 
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29 ******************************************************************************/
30 
31 #ifndef ETL_QUEUE_INCLUDED
32 #define ETL_QUEUE_INCLUDED
33 
34 #include <stddef.h>
35 #include <stdint.h>
36 
37 #include "platform.h"
38 #include "container.h"
39 #include "alignment.h"
40 #include "array.h"
41 #include "exception.h"
42 #include "error_handler.h"
43 #include "debug_count.h"
44 #include "type_traits.h"
45 #include "parameter_type.h"
46 #include "memory_model.h"
47 #include "integral_limits.h"
48 #include "utility.h"
49 #include "placement_new.h"
50 
51 #undef ETL_FILE
52 #define ETL_FILE "13"
53 
54 //*****************************************************************************
59 //*****************************************************************************
60 
61 namespace etl
62 {
63  //***************************************************************************
66  //***************************************************************************
67  class queue_exception : public exception
68  {
69  public:
70 
71  queue_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
72  : exception(reason_, file_name_, line_number_)
73  {
74  }
75  };
76 
77  //***************************************************************************
80  //***************************************************************************
81  class queue_full : public queue_exception
82  {
83  public:
84 
85  queue_full(string_type file_name_, numeric_type line_number_)
86  : queue_exception(ETL_ERROR_TEXT("queue:full", ETL_FILE"A"), file_name_, line_number_)
87  {
88  }
89  };
90 
91  //***************************************************************************
94  //***************************************************************************
96  {
97  public:
98 
99  queue_empty(string_type file_name_, numeric_type line_number_)
100  : queue_exception(ETL_ERROR_TEXT("queue:empty", ETL_FILE"B"), file_name_, line_number_)
101  {
102  }
103  };
104 
105  //***************************************************************************
108  //***************************************************************************
109  template <const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
111  {
112  public:
113 
116 
117  //*************************************************************************
119  //*************************************************************************
120  size_type size() const
121  {
122  return current_size;
123  }
124 
125  //*************************************************************************
127  //*************************************************************************
129  {
130  return CAPACITY;
131  }
132 
133  //*************************************************************************
135  //*************************************************************************
137  {
138  return CAPACITY;
139  }
140 
141  //*************************************************************************
144  //*************************************************************************
145  bool empty() const
146  {
147  return current_size == 0;
148  }
149 
150  //*************************************************************************
153  //*************************************************************************
154  bool full() const
155  {
156  return current_size == CAPACITY;
157  }
158 
159  //*************************************************************************
162  //*************************************************************************
164  {
165  return max_size() - size();
166  }
167 
168  protected:
169 
170  //*************************************************************************
172  //*************************************************************************
174  : in(0),
175  out(0),
176  current_size(0),
177  CAPACITY(max_size_)
178  {
179  }
180 
181  //*************************************************************************
183  //*************************************************************************
185  {
186  }
187 
188  //*************************************************************************
190  //*************************************************************************
191  void add_in()
192  {
193  if (++in == CAPACITY)
194  {
195  in = 0;
196  }
197 
198  ++current_size;
199  ETL_INCREMENT_DEBUG_COUNT
200  }
201 
202  //*************************************************************************
204  //*************************************************************************
205  void del_out()
206  {
207  if (++out == CAPACITY)
208  {
209  out = 0;
210  }
211  --current_size;
212  ETL_DECREMENT_DEBUG_COUNT
213  }
214 
215  //*************************************************************************
217  //*************************************************************************
218  void index_clear()
219  {
220  in = 0;
221  out = 0;
222  current_size = 0;
223  ETL_RESET_DEBUG_COUNT
224  }
225 
230  ETL_DECLARE_DEBUG_COUNT
231 
232  };
233 
234  //***************************************************************************
244  //***************************************************************************
245  template <typename T, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
246  class iqueue : public etl::queue_base<MEMORY_MODEL>
247  {
248  private:
249 
250  typedef typename etl::queue_base<MEMORY_MODEL> base_t;
251 
252  public:
253 
254  typedef T value_type;
255  typedef T& reference;
256  typedef const T& const_reference;
257 #if ETL_CPP11_SUPPORTED
258  typedef T&& rvalue_reference;
259 #endif
260  typedef T* pointer;
261  typedef const T* const_pointer;
262  typedef typename base_t::size_type size_type;
263 
264  using base_t::in;
265  using base_t::out;
272 
273  //*************************************************************************
276  //*************************************************************************
278  {
279  return p_buffer[out];
280  }
281 
282  //*************************************************************************
285  //*************************************************************************
287  {
288  return p_buffer[out];
289  }
290 
291  //*************************************************************************
294  //*************************************************************************
296  {
297  return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
298  }
299 
300  //*************************************************************************
303  //*************************************************************************
305  {
306  return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
307  }
308 
309  //*************************************************************************
313  //*************************************************************************
314  void push(const_reference value)
315  {
316 #if defined(ETL_CHECK_PUSH_POP)
317  ETL_ASSERT(!full(), ETL_ERROR(queue_full));
318 #endif
319  ::new (&p_buffer[in]) T(value);
320  add_in();
321  }
322 
323 #if ETL_CPP11_SUPPORTED
324  //*************************************************************************
328  //*************************************************************************
329  void push(rvalue_reference value)
330  {
331 #if defined(ETL_CHECK_PUSH_POP)
332  ETL_ASSERT(!full(), ETL_ERROR(queue_full));
333 #endif
334  ::new (&p_buffer[in]) T(etl::move(value));
335  add_in();
336  }
337 #endif
338 
339 #if ETL_CPP11_SUPPORTED && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_FORCE_CPP03)
340  //*************************************************************************
344  //*************************************************************************
345  template <typename ... Args>
346  void emplace(Args && ... args)
347  {
348 #if defined(ETL_CHECK_PUSH_POP)
349  ETL_ASSERT(!full(), ETL_ERROR(queue_full));
350 #endif
351  ::new (&p_buffer[in]) T(etl::forward<Args>(args)...);
352  add_in();
353  }
354 #else
355  //*************************************************************************
359  //*************************************************************************
360  template <typename T1>
361  void emplace(const T1& value1)
362  {
363 #if defined(ETL_CHECK_PUSH_POP)
364  ETL_ASSERT(!full(), ETL_ERROR(queue_full));
365 #endif
366  ::new (&p_buffer[in]) T(value1);
367  add_in();
368  }
369 
370  //*************************************************************************
374  //*************************************************************************
375  template <typename T1, typename T2>
376  void emplace(const T1& value1, const T2& value2)
377  {
378 #if defined(ETL_CHECK_PUSH_POP)
379  ETL_ASSERT(!full(), ETL_ERROR(queue_full));
380 #endif
381  ::new (&p_buffer[in]) T(value1, value2);
382  add_in();
383  }
384 
385  //*************************************************************************
389  //*************************************************************************
390  template <typename T1, typename T2, typename T3>
391  void emplace(const T1& value1, const T2& value2, const T3& value3)
392  {
393 #if defined(ETL_CHECK_PUSH_POP)
394  ETL_ASSERT(!full(), ETL_ERROR(queue_full));
395 #endif
396  ::new (&p_buffer[in]) T(value1, value2, value3);
397  add_in();
398  }
399 
400  //*************************************************************************
404  //*************************************************************************
405  template <typename T1, typename T2, typename T3, typename T4>
406  void emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
407  {
408 #if defined(ETL_CHECK_PUSH_POP)
409  ETL_ASSERT(!full(), ETL_ERROR(queue_full));
410 #endif
411  ::new (&p_buffer[in]) T(value1, value2, value3, value4);
412  add_in();
413  }
414 #endif
415 
416  //*************************************************************************
418  //*************************************************************************
419  void clear()
420  {
421  if ETL_IF_CONSTEXPR(etl::is_trivially_destructible<T>::value)
422  {
424  }
425  else
426  {
427  while (current_size > 0)
428  {
429  p_buffer[out].~T();
430  del_out();
431  }
432 
433  in = 0;
434  out = 0;
435  }
436  }
437 
438  //*************************************************************************
442  //*************************************************************************
443  void pop()
444  {
445 #if defined(ETL_CHECK_PUSH_POP)
446  ETL_ASSERT(!empty(), ETL_ERROR(queue_empty));
447 #endif
448  p_buffer[out].~T();
449  del_out();
450  }
451 
452  //*************************************************************************
455  //*************************************************************************
456  void pop_into(reference destination)
457  {
458  destination = front();
459  pop();
460  }
461 
462  //*************************************************************************
467  //*************************************************************************
468  template <typename TContainer>
469  void pop_into(TContainer& destination)
470  {
471  destination.push(front());
472  pop();
473  }
474 
475  //*************************************************************************
477  //*************************************************************************
478  iqueue& operator = (const iqueue& rhs)
479  {
480  if (&rhs != this)
481  {
482  clear();
483  clone(rhs);
484  }
485 
486  return *this;
487  }
488 
489 #if ETL_CPP11_SUPPORTED
490  //*************************************************************************
492  //*************************************************************************
493  iqueue& operator = (iqueue&& rhs)
494  {
495  if (&rhs != this)
496  {
497  clear();
498  move_clone(rhs);
499  }
500 
501  return *this;
502  }
503 #endif
504 
505  protected:
506 
507  //*************************************************************************
509  //*************************************************************************
510  void clone(const iqueue& other)
511  {
512  clear();
513 
514  size_type index = other.out;
515 
516  for (size_type i = 0; i < other.size(); ++i)
517  {
518  push(other.p_buffer[index]);
519  index = (index == (CAPACITY - 1)) ? 0 : index + 1;
520  }
521  }
522 
523 #if ETL_CPP11_SUPPORTED
524  //*************************************************************************
526  //*************************************************************************
527  void move_clone(iqueue&& other)
528  {
529  clear();
530 
531  size_type index = other.out;
532 
533  for (size_type i = 0; i < other.size(); ++i)
534  {
535  push(etl::move(other.p_buffer[index]));
536  index = (index == (CAPACITY - 1)) ? 0 : index + 1;
537  }
538  }
539 #endif
540 
541  //*************************************************************************
543  //*************************************************************************
544  iqueue(T* p_buffer_, size_type max_size_)
545  : base_t(max_size_),
546  p_buffer(p_buffer_)
547  {
548  }
549 
550  private:
551 
552  // Disable copy construction.
553  iqueue(const iqueue&);
554 
555  T* p_buffer;
556 
557  //*************************************************************************
559  //*************************************************************************
560 #if defined(ETL_POLYMORPHIC_QUEUE) || defined(ETL_POLYMORPHIC_CONTAINERS)
561  public:
562  virtual ~iqueue()
563  {
564  }
565 #else
566  protected:
568  {
569  }
570 #endif
571  };
572 
573  //***************************************************************************
580  //***************************************************************************
581  template <typename T, const size_t SIZE, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
582  class queue : public etl::iqueue<T, MEMORY_MODEL>
583  {
584  private:
585 
587 
588  public:
589 
590  typedef typename base_t::size_type size_type;
591 
592  ETL_STATIC_ASSERT((SIZE <= etl::integral_limits<size_type>::max), "Size too large for memory model");
593 
594  static const size_type MAX_SIZE = size_type(SIZE);
595 
596  //*************************************************************************
598  //*************************************************************************
600  : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
601  {
602  }
603 
604  //*************************************************************************
606  //*************************************************************************
607  queue(const queue& rhs)
608  : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
609  {
610  base_t::clone(rhs);
611  }
612 
613 #if ETL_CPP11_SUPPORTED
614  //*************************************************************************
616  //*************************************************************************
617  queue(queue&& rhs)
618  : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
619  {
620  base_t::move_clone(etl::move(rhs));
621  }
622 #endif
623 
624  //*************************************************************************
626  //*************************************************************************
628  {
629  base_t::clear();
630  }
631 
632  //*************************************************************************
634  //*************************************************************************
635  queue& operator = (const queue& rhs)
636  {
637  if (&rhs != this)
638  {
639  base_t::clone(rhs);
640  }
641 
642  return *this;
643  }
644 
645 #if ETL_CPP11_SUPPORTED
646  //*************************************************************************
648  //*************************************************************************
649  queue& operator = (queue&& rhs)
650  {
651  if (&rhs != this)
652  {
653  base_t::move_clone(rhs);
654  }
655 
656  return *this;
657  }
658 #endif
659 
660  private:
661 
663  typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type buffer[SIZE];
664  };
665 }
666 
667 #undef ETL_FILE
668 
669 #endif
Definition: alignment.h:116
#define ETL_ASSERT(b, e)
Definition: error_handler.h:290
exception(string_type reason_, string_type file_, numeric_type line_)
Constructor.
Definition: exception.h:67
Definition: exception.h:47
Definition: integral_limits.h:54
~queue()
Destructor.
Definition: queue.h:627
size_type in
Where to input new data.
Definition: queue.h:226
void emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition: queue.h:391
const_reference front() const
Definition: queue.h:286
const T * const_pointer
A const pointer to the type used in the queue.
Definition: queue.h:261
void push(const_reference value)
Definition: queue.h:314
const_reference back() const
Definition: queue.h:304
void emplace(const T1 &value1)
Definition: queue.h:361
reference front()
Definition: queue.h:277
iqueue & operator=(const iqueue &rhs)
Assignment operator.
Definition: queue.h:478
size_type current_size
The number of items in the queue.
Definition: queue.h:228
queue()
Default constructor.
Definition: queue.h:599
void pop_into(reference destination)
Definition: queue.h:456
etl::size_type_lookup< MEMORY_MODEL >::type size_type
The type used for determining the size of queue.
Definition: queue.h:115
T value_type
The type stored in the queue.
Definition: queue.h:254
void pop()
Definition: queue.h:443
void index_clear()
Clears the indexes.
Definition: queue.h:218
size_type out
Where to get the oldest data.
Definition: queue.h:227
~queue_base()
Destructor.
Definition: queue.h:184
bool full() const
Definition: queue.h:154
reference back()
Definition: queue.h:295
size_type available() const
Definition: queue.h:163
void del_out()
Decrements (and wraps) the 'out' index value to record a queue deletion.
Definition: queue.h:205
void add_in()
Increments (and wraps) the 'in' index value to record a queue addition.
Definition: queue.h:191
queue & operator=(const queue &rhs)
Assignment operator.
Definition: queue.h:635
~iqueue()
Destructor.
Definition: queue.h:567
const size_type CAPACITY
The maximum number of items in the queue.
Definition: queue.h:229
base_t::size_type size_type
The type used for determining the size of the queue.
Definition: queue.h:262
iqueue(T *p_buffer_, size_type max_size_)
The constructor that is called from derived classes.
Definition: queue.h:544
queue_base(size_type max_size_)
The constructor that is called from derived classes.
Definition: queue.h:173
void clone(const iqueue &other)
Make this a clone of the supplied queue.
Definition: queue.h:510
queue(const queue &rhs)
Copy constructor.
Definition: queue.h:607
size_type size() const
Returns the current number of items in the queue.
Definition: queue.h:120
const T & const_reference
A const reference to the type used in the queue.
Definition: queue.h:256
void pop_into(TContainer &destination)
Definition: queue.h:469
size_type capacity() const
Returns the maximum number of items that can be queued.
Definition: queue.h:136
T & reference
A reference to the type used in the queue.
Definition: queue.h:255
size_type max_size() const
Returns the maximum number of items that can be queued.
Definition: queue.h:128
bool empty() const
Definition: queue.h:145
T * pointer
A pointer to the type used in the queue.
Definition: queue.h:260
void emplace(const T1 &value1, const T2 &value2)
Definition: queue.h:376
void clear()
Clears the queue to the empty state.
Definition: queue.h:419
void emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition: queue.h:406
This is the base for all queues that contain a particular type.
Definition: queue.h:247
Definition: queue.h:583
Definition: queue.h:111
Definition: queue.h:96
Definition: queue.h:68
Definition: queue.h:82
add_rvalue_reference
Definition: type_traits_generator.h:1348
is_trivially_destructible
Definition: type_traits_generator.h:1171
Definition: absolute.h:37
Definition: memory_model.h:48