Embedded Template Library 1.0
Loading...
Searching...
No Matches
queue.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2014 John Wellbelove, Mark Kitson
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_QUEUE_INCLUDED
32#define ETL_QUEUE_INCLUDED
33
34#include "platform.h"
35#include "alignment.h"
36#include "debug_count.h"
37#include "error_handler.h"
38#include "exception.h"
39#include "integral_limits.h"
40#include "memory_model.h"
41#include "parameter_type.h"
42#include "placement_new.h"
43#include "type_traits.h"
44#include "utility.h"
45
46#include <stddef.h>
47#include <stdint.h>
48
49//*****************************************************************************
54//*****************************************************************************
55
56namespace etl
57{
58 //***************************************************************************
61 //***************************************************************************
62 class queue_exception : public exception
63 {
64 public:
65
66 queue_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
67 : exception(reason_, file_name_, line_number_)
68 {
69 }
70 };
71
72 //***************************************************************************
75 //***************************************************************************
76 class queue_full : public queue_exception
77 {
78 public:
79
80 queue_full(string_type file_name_, numeric_type line_number_)
81 : queue_exception(ETL_ERROR_TEXT("queue:full", ETL_QUEUE_FILE_ID"A"), file_name_, line_number_)
82 {
83 }
84 };
85
86 //***************************************************************************
89 //***************************************************************************
90 class queue_empty : public queue_exception
91 {
92 public:
93
94 queue_empty(string_type file_name_, numeric_type line_number_)
95 : queue_exception(ETL_ERROR_TEXT("queue:empty", ETL_QUEUE_FILE_ID"B"), file_name_, line_number_)
96 {
97 }
98 };
99
100 //***************************************************************************
103 //***************************************************************************
104 template <size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
106 {
107 public:
108
111
112 //*************************************************************************
114 //*************************************************************************
116 {
117 return current_size;
118 }
119
120 //*************************************************************************
122 //*************************************************************************
124 {
125 return CAPACITY;
126 }
127
128 //*************************************************************************
130 //*************************************************************************
132 {
133 return CAPACITY;
134 }
135
136 //*************************************************************************
139 //*************************************************************************
140 bool empty() const
141 {
142 return current_size == 0;
143 }
144
145 //*************************************************************************
148 //*************************************************************************
149 bool full() const
150 {
151 return current_size == CAPACITY;
152 }
153
154 //*************************************************************************
157 //*************************************************************************
159 {
160 return max_size() - size();
161 }
162
163 protected:
164
165 //*************************************************************************
167 //*************************************************************************
169 : in(0)
170 , out(0)
171 , current_size(0)
172 , CAPACITY(max_size_)
173 {
174 }
175
176 //*************************************************************************
178 //*************************************************************************
180
181 //*************************************************************************
183 //*************************************************************************
184 void add_in()
185 {
186 if (++in == CAPACITY) ETL_UNLIKELY
187 {
188 in = 0;
189 }
190
191 ++current_size;
192 ETL_INCREMENT_DEBUG_COUNT;
193 }
194
195 //*************************************************************************
197 //*************************************************************************
198 void del_out()
199 {
200 if (++out == CAPACITY) ETL_UNLIKELY
201 {
202 out = 0;
203 }
204 --current_size;
205 ETL_DECREMENT_DEBUG_COUNT;
206 }
207
208 //*************************************************************************
210 //*************************************************************************
212 {
213 in = 0;
214 out = 0;
215 current_size = 0;
216 ETL_RESET_DEBUG_COUNT;
217 }
218
224 };
225
226 //***************************************************************************
236 //***************************************************************************
237 template <typename T, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
238 class iqueue : public etl::queue_base<MEMORY_MODEL>
239 {
240 private:
241
242 typedef typename etl::queue_base<MEMORY_MODEL> base_t;
243
244 public:
245
246 typedef T value_type;
247 typedef T& reference;
248 typedef const T& const_reference;
249#if ETL_USING_CPP11
250 typedef T&& rvalue_reference;
251#endif
252 typedef T* pointer;
253 typedef const T* const_pointer;
254 typedef typename base_t::size_type size_type;
255
256 using base_t::add_in;
257 using base_t::CAPACITY;
259 using base_t::del_out;
260 using base_t::empty;
261 using base_t::full;
262 using base_t::in;
263 using base_t::out;
264
265 //*************************************************************************
270 //*************************************************************************
272 {
273 ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
274 return p_buffer[out];
275 }
276
277 //*************************************************************************
282 //*************************************************************************
284 {
285 ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
286 return p_buffer[out];
287 }
288
289 //*************************************************************************
294 //*************************************************************************
296 {
297 ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
298 return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
299 }
300
301 //*************************************************************************
306 //*************************************************************************
308 {
309 ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
310 return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
311 }
312
313 //*************************************************************************
318 //*************************************************************************
320 {
321 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(queue_full));
322
323 ::new (&p_buffer[in]) T(value);
324 add_in();
325 }
326
327#if ETL_USING_CPP11
328 //*************************************************************************
333 //*************************************************************************
334 void push(rvalue_reference value)
335 {
336 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(queue_full));
337
338 ::new (&p_buffer[in]) T(etl::move(value));
339 add_in();
340 }
341#endif
342
343#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_FORCE_CPP03_IMPLEMENTATION)
344 //*************************************************************************
350 //*************************************************************************
351 template <typename... Args>
352 reference emplace(Args&&... args)
353 {
354 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
355
356 reference value = p_buffer[in];
357 ::new (&value) T(etl::forward<Args>(args)...);
358 add_in();
359 return value;
360 }
361#else
362 //*************************************************************************
366 //*************************************************************************
368 {
369 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
370
371 reference value = p_buffer[in];
372 ::new (&value) T();
373 add_in();
374 return value;
375 }
376
377 //*************************************************************************
383 //*************************************************************************
384 template <typename T1>
385 reference emplace(const T1& value1)
386 {
387 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
388
389 reference value = p_buffer[in];
390 ::new (&value) T(value1);
391 add_in();
392 return value;
393 }
394
395 //*************************************************************************
402 //*************************************************************************
403 template <typename T1, typename T2>
404 reference emplace(const T1& value1, const T2& value2)
405 {
406 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
407
408 reference value = p_buffer[in];
409 ::new (&value) T(value1, value2);
410 add_in();
411 return value;
412 }
413
414 //*************************************************************************
422 //*************************************************************************
423 template <typename T1, typename T2, typename T3>
424 reference emplace(const T1& value1, const T2& value2, const T3& value3)
425 {
426 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
427
428 reference value = p_buffer[in];
429 ::new (&value) T(value1, value2, value3);
430 add_in();
431 return value;
432 }
433
434 //*************************************************************************
443 //*************************************************************************
444 template <typename T1, typename T2, typename T3, typename T4>
445 reference emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
446 {
447 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
448
449 reference value = p_buffer[in];
450 ::new (&value) T(value1, value2, value3, value4);
451 add_in();
452 return value;
453 }
454#endif
455
456 //*************************************************************************
458 //*************************************************************************
459 void clear()
460 {
461 if ETL_IF_CONSTEXPR (etl::is_trivially_destructible<T>::value)
462 {
464 }
465 else
466 {
467 while (current_size > 0)
468 {
469 p_buffer[out].~T();
470 del_out();
471 }
472
473 in = 0;
474 out = 0;
475 }
476 }
477
478 //*************************************************************************
483 //*************************************************************************
484 void pop()
485 {
486 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(queue_empty));
487
488 p_buffer[out].~T();
489 del_out();
490 }
491
492 //*************************************************************************
496 //*************************************************************************
497 void pop_into(reference destination)
498 {
499 destination = ETL_MOVE(front());
500 pop();
501 }
502
503 //*************************************************************************
509 //*************************************************************************
510 template <typename TContainer>
511 void pop_into(TContainer& destination)
512 {
513 destination.push(ETL_MOVE(front()));
514 pop();
515 }
516
517 //*************************************************************************
519 //*************************************************************************
521 {
522 if (&rhs != this)
523 {
524 clear();
525 clone(rhs);
526 }
527
528 return *this;
529 }
530
531#if ETL_USING_CPP11
532 //*************************************************************************
534 //*************************************************************************
535 iqueue& operator=(iqueue&& rhs)
536 {
537 if (&rhs != this)
538 {
539 clear();
540 move_clone(rhs);
541 }
542
543 return *this;
544 }
545#endif
546
547 protected:
548
549 //*************************************************************************
551 //*************************************************************************
552 void clone(const iqueue& other)
553 {
554 clear();
555
556 size_type index = other.out;
557
558 for (size_type i = 0; i < other.size(); ++i)
559 {
560 push(other.p_buffer[index]);
561 index = (index == (CAPACITY - 1)) ? 0 : index + 1;
562 }
563 }
564
565#if ETL_USING_CPP11
566 //*************************************************************************
568 //*************************************************************************
569 void move_clone(iqueue&& other)
570 {
571 clear();
572
573 size_type index = other.out;
574
575 for (size_type i = 0; i < other.size(); ++i)
576 {
577 push(etl::move(other.p_buffer[index]));
578 index = (index == (CAPACITY - 1)) ? 0 : index + 1;
579 }
580 }
581#endif
582
583 //*************************************************************************
585 //*************************************************************************
586 iqueue(T* p_buffer_, size_type max_size_)
587 : base_t(max_size_)
588 , p_buffer(p_buffer_)
589 {
590 }
591
592 private:
593
594 // Disable copy construction.
595 iqueue(const iqueue&);
596
597 T* p_buffer;
598
599 //*************************************************************************
601 //*************************************************************************
602#if defined(ETL_POLYMORPHIC_QUEUE) || defined(ETL_POLYMORPHIC_CONTAINERS)
603
604 public:
605
606 virtual ~iqueue() {}
607#else
608
609 protected:
610
612#endif
613 };
614
615 //***************************************************************************
623 //***************************************************************************
624 template <typename T, const size_t SIZE, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
625 class queue : public etl::iqueue<T, MEMORY_MODEL>
626 {
627 private:
628
629 typedef etl::iqueue<T, MEMORY_MODEL> base_t;
630
631 public:
632
633 typedef typename base_t::size_type size_type;
634 typedef typename etl::aligned_storage< sizeof(T), etl::alignment_of<T>::value>::type container_type;
635
636 ETL_STATIC_ASSERT((SIZE <= etl::integral_limits<size_type>::max), "Size too large for memory model");
637
638 static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
639
640 //*************************************************************************
642 //*************************************************************************
644 : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
645 {
646 }
647
648 //*************************************************************************
650 //*************************************************************************
651 queue(const queue& rhs)
652 : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
653 {
654 base_t::clone(rhs);
655 }
656
657#if ETL_USING_CPP11
658 //*************************************************************************
660 //*************************************************************************
661 queue(queue&& rhs)
662 : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
663 {
664 base_t::move_clone(etl::move(rhs));
665 }
666#endif
667
668 //*************************************************************************
670 //*************************************************************************
672 {
674 }
675
676 //*************************************************************************
678 //*************************************************************************
679 queue& operator=(const queue& rhs)
680 {
681 if (&rhs != this)
682 {
683 base_t::clone(rhs);
684 }
685
686 return *this;
687 }
688
689#if ETL_USING_CPP11
690 //*************************************************************************
692 //*************************************************************************
693 queue& operator=(queue&& rhs)
694 {
695 if (&rhs != this)
696 {
697 base_t::move_clone(etl::move(rhs));
698 }
699
700 return *this;
701 }
702#endif
703
704 private:
705
707 container_type buffer[SIZE];
708 };
709
710 template <typename T, const size_t SIZE, const size_t MEMORY_MODEL>
711 ETL_CONSTANT typename queue<T, SIZE, MEMORY_MODEL>::size_type queue<T, SIZE, MEMORY_MODEL>::MAX_SIZE;
712} // namespace etl
713
714#endif
Definition alignment.h:251
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
Definition integral_limits.h:518
~queue()
Destructor.
Definition queue.h:671
size_type in
Definition queue.h:219
reference emplace(const T1 &value1, const T2 &value2)
Definition queue.h:404
queue & operator=(const queue &rhs)
Assignment operator.
Definition queue.h:679
const_reference front() const
Definition queue.h:283
ETL_DECLARE_DEBUG_COUNT
Definition queue.h:223
const T * const_pointer
A const pointer to the type used in the queue.
Definition queue.h:253
void push(const_reference value)
Definition queue.h:319
reference emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition queue.h:424
const_reference back() const
Definition queue.h:307
reference front()
Definition queue.h:271
size_type current_size
Definition queue.h:221
queue()
Default constructor.
Definition queue.h:643
void pop_into(reference destination)
Definition queue.h:497
etl::size_type_lookup< MEMORY_MODEL >::type size_type
The type used for determining the size of queue.
Definition queue.h:110
iqueue & operator=(const iqueue &rhs)
Assignment operator.
Definition queue.h:520
reference emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition queue.h:445
T value_type
The type stored in the queue.
Definition queue.h:246
void pop()
Definition queue.h:484
void index_clear()
Clears the indexes.
Definition queue.h:211
size_type out
Definition queue.h:220
~queue_base()
Destructor.
Definition queue.h:179
bool full() const
Definition queue.h:149
reference back()
Definition queue.h:295
size_type available() const
Definition queue.h:158
void del_out()
Increments (and wraps) the 'out' index value to record a queue deletion.
Definition queue.h:198
void add_in()
Increments (and wraps) the 'in' index value to record a queue addition.
Definition queue.h:184
~iqueue()
Destructor.
Definition queue.h:611
const size_type CAPACITY
Definition queue.h:222
reference emplace()
Definition queue.h:367
base_t::size_type size_type
The type used for determining the size of the queue.
Definition queue.h:254
iqueue(T *p_buffer_, size_type max_size_)
The constructor that is called from derived classes.
Definition queue.h:586
queue_base(size_type max_size_)
The constructor that is called from derived classes.
Definition queue.h:168
void clone(const iqueue &other)
Make this a clone of the supplied queue.
Definition queue.h:552
queue(const queue &rhs)
Copy constructor.
Definition queue.h:651
size_type size() const
Returns the current number of items in the queue.
Definition queue.h:115
const T & const_reference
A const reference to the type used in the queue.
Definition queue.h:248
void pop_into(TContainer &destination)
Definition queue.h:511
size_type capacity() const
Returns the maximum number of items that can be queued.
Definition queue.h:131
T & reference
A reference to the type used in the queue.
Definition queue.h:247
size_type max_size() const
Returns the maximum number of items that can be queued.
Definition queue.h:123
reference emplace(const T1 &value1)
Definition queue.h:385
bool empty() const
Definition queue.h:140
T * pointer
A pointer to the type used in the queue.
Definition queue.h:252
void clear()
Clears the queue to the empty state.
Definition queue.h:459
This is the base for all queues that contain a particular type.
Definition queue.h:239
Definition queue.h:626
Definition queue.h:106
Definition queue.h:91
Definition queue.h:77
size_type size() const
Definition vector.h:1040
bitset_ext
Definition absolute.h:40
Definition memory_model.h:50