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
48//*****************************************************************************
53//*****************************************************************************
54
55namespace etl
56{
57 //***************************************************************************
60 //***************************************************************************
61 class queue_exception : public exception
62 {
63 public:
64
65 queue_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
66 : exception(reason_, file_name_, line_number_)
67 {
68 }
69 };
70
71 //***************************************************************************
74 //***************************************************************************
75 class queue_full : public queue_exception
76 {
77 public:
78
79 queue_full(string_type file_name_, numeric_type line_number_)
80 : queue_exception(ETL_ERROR_TEXT("queue:full", ETL_QUEUE_FILE_ID"A"), file_name_, line_number_)
81 {
82 }
83 };
84
85 //***************************************************************************
88 //***************************************************************************
89 class queue_empty : public queue_exception
90 {
91 public:
92
93 queue_empty(string_type file_name_, numeric_type line_number_)
94 : queue_exception(ETL_ERROR_TEXT("queue:empty", ETL_QUEUE_FILE_ID"B"), file_name_, line_number_)
95 {
96 }
97 };
98
99 //***************************************************************************
102 //***************************************************************************
103 template <size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
105 {
106 public:
107
110
111 //*************************************************************************
113 //*************************************************************************
115 {
116 return current_size;
117 }
118
119 //*************************************************************************
121 //*************************************************************************
123 {
124 return CAPACITY;
125 }
126
127 //*************************************************************************
129 //*************************************************************************
131 {
132 return CAPACITY;
133 }
134
135 //*************************************************************************
138 //*************************************************************************
139 bool empty() const
140 {
141 return current_size == 0;
142 }
143
144 //*************************************************************************
147 //*************************************************************************
148 bool full() const
149 {
150 return current_size == CAPACITY;
151 }
152
153 //*************************************************************************
156 //*************************************************************************
158 {
159 return max_size() - size();
160 }
161
162 protected:
163
164 //*************************************************************************
166 //*************************************************************************
168 : in(0)
169 , out(0)
170 , current_size(0)
171 , CAPACITY(max_size_)
172 {
173 }
174
175 //*************************************************************************
177 //*************************************************************************
179
180 //*************************************************************************
182 //*************************************************************************
183 void add_in()
184 {
185 if (++in == CAPACITY) ETL_UNLIKELY
186 {
187 in = 0;
188 }
189
190 ++current_size;
191 ETL_INCREMENT_DEBUG_COUNT;
192 }
193
194 //*************************************************************************
196 //*************************************************************************
197 void del_out()
198 {
199 if (++out == CAPACITY) ETL_UNLIKELY
200 {
201 out = 0;
202 }
203 --current_size;
204 ETL_DECREMENT_DEBUG_COUNT;
205 }
206
207 //*************************************************************************
209 //*************************************************************************
211 {
212 in = 0;
213 out = 0;
214 current_size = 0;
215 ETL_RESET_DEBUG_COUNT;
216 }
217
223 };
224
225 //***************************************************************************
235 //***************************************************************************
236 template <typename T, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
237 class iqueue : public etl::queue_base<MEMORY_MODEL>
238 {
239 private:
240
241 typedef typename etl::queue_base<MEMORY_MODEL> base_t;
242
243 public:
244
245 typedef T value_type;
246 typedef T& reference;
247 typedef const T& const_reference;
248#if ETL_USING_CPP11
249 typedef T&& rvalue_reference;
250#endif
251 typedef T* pointer;
252 typedef const T* const_pointer;
253 typedef typename base_t::size_type size_type;
254
255 using base_t::add_in;
256 using base_t::CAPACITY;
258 using base_t::del_out;
259 using base_t::empty;
260 using base_t::full;
261 using base_t::in;
262 using base_t::out;
263
264 //*************************************************************************
269 //*************************************************************************
271 {
272 ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
273 return p_buffer[out];
274 }
275
276 //*************************************************************************
281 //*************************************************************************
283 {
284 ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
285 return p_buffer[out];
286 }
287
288 //*************************************************************************
293 //*************************************************************************
295 {
296 ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
297 return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
298 }
299
300 //*************************************************************************
305 //*************************************************************************
307 {
308 ETL_ASSERT_CHECK_EXTRA(!empty(), ETL_ERROR(queue_empty));
309 return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
310 }
311
312 //*************************************************************************
317 //*************************************************************************
319 {
320 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(queue_full));
321
322 ::new (&p_buffer[in]) T(value);
323 add_in();
324 }
325
326#if ETL_USING_CPP11
327 //*************************************************************************
332 //*************************************************************************
333 void push(rvalue_reference value)
334 {
335 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(queue_full));
336
337 ::new (&p_buffer[in]) T(etl::move(value));
338 add_in();
339 }
340#endif
341
342#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_FORCE_CPP03_IMPLEMENTATION)
343 //*************************************************************************
349 //*************************************************************************
350 template <typename... Args>
351 reference emplace(Args&&... args)
352 {
353 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
354
355 reference value = p_buffer[in];
356 ::new (&value) T(etl::forward<Args>(args)...);
357 add_in();
358 return value;
359 }
360#else
361 //*************************************************************************
365 //*************************************************************************
367 {
368 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
369
370 reference value = p_buffer[in];
371 ::new (&value) T();
372 add_in();
373 return value;
374 }
375
376 //*************************************************************************
382 //*************************************************************************
383 template <typename T1>
384 reference emplace(const T1& value1)
385 {
386 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
387
388 reference value = p_buffer[in];
389 ::new (&value) T(value1);
390 add_in();
391 return value;
392 }
393
394 //*************************************************************************
401 //*************************************************************************
402 template <typename T1, typename T2>
403 reference emplace(const T1& value1, const T2& value2)
404 {
405 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
406
407 reference value = p_buffer[in];
408 ::new (&value) T(value1, value2);
409 add_in();
410 return value;
411 }
412
413 //*************************************************************************
421 //*************************************************************************
422 template <typename T1, typename T2, typename T3>
423 reference emplace(const T1& value1, const T2& value2, const T3& value3)
424 {
425 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
426
427 reference value = p_buffer[in];
428 ::new (&value) T(value1, value2, value3);
429 add_in();
430 return value;
431 }
432
433 //*************************************************************************
442 //*************************************************************************
443 template <typename T1, typename T2, typename T3, typename T4>
444 reference emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
445 {
446 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
447
448 reference value = p_buffer[in];
449 ::new (&value) T(value1, value2, value3, value4);
450 add_in();
451 return value;
452 }
453#endif
454
455 //*************************************************************************
457 //*************************************************************************
458 void clear()
459 {
460 if ETL_IF_CONSTEXPR (etl::is_trivially_destructible<T>::value)
461 {
463 }
464 else
465 {
466 while (current_size > 0)
467 {
468 p_buffer[out].~T();
469 del_out();
470 }
471
472 in = 0;
473 out = 0;
474 }
475 }
476
477 //*************************************************************************
482 //*************************************************************************
483 void pop()
484 {
485 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(queue_empty));
486
487 p_buffer[out].~T();
488 del_out();
489 }
490
491 //*************************************************************************
495 //*************************************************************************
496 void pop_into(reference destination)
497 {
498 destination = ETL_MOVE(front());
499 pop();
500 }
501
502 //*************************************************************************
508 //*************************************************************************
509 template <typename TContainer>
510 void pop_into(TContainer& destination)
511 {
512 destination.push(ETL_MOVE(front()));
513 pop();
514 }
515
516 //*************************************************************************
518 //*************************************************************************
520 {
521 if (&rhs != this)
522 {
523 clear();
524 clone(rhs);
525 }
526
527 return *this;
528 }
529
530#if ETL_USING_CPP11
531 //*************************************************************************
533 //*************************************************************************
534 iqueue& operator=(iqueue&& rhs)
535 {
536 if (&rhs != this)
537 {
538 clear();
539 move_clone(rhs);
540 }
541
542 return *this;
543 }
544#endif
545
546 protected:
547
548 //*************************************************************************
550 //*************************************************************************
551 void clone(const iqueue& other)
552 {
553 clear();
554
555 size_type index = other.out;
556
557 for (size_type i = 0; i < other.size(); ++i)
558 {
559 push(other.p_buffer[index]);
560 index = (index == (CAPACITY - 1)) ? 0 : index + 1;
561 }
562 }
563
564#if ETL_USING_CPP11
565 //*************************************************************************
567 //*************************************************************************
568 void move_clone(iqueue&& other)
569 {
570 clear();
571
572 size_type index = other.out;
573
574 for (size_type i = 0; i < other.size(); ++i)
575 {
576 push(etl::move(other.p_buffer[index]));
577 index = (index == (CAPACITY - 1)) ? 0 : index + 1;
578 }
579 }
580#endif
581
582 //*************************************************************************
584 //*************************************************************************
585 iqueue(T* p_buffer_, size_type max_size_)
586 : base_t(max_size_)
587 , p_buffer(p_buffer_)
588 {
589 }
590
591 private:
592
593 // Disable copy construction.
594 iqueue(const iqueue&);
595
596 T* p_buffer;
597
598 //*************************************************************************
600 //*************************************************************************
601#if defined(ETL_POLYMORPHIC_QUEUE) || defined(ETL_POLYMORPHIC_CONTAINERS)
602
603 public:
604
605 virtual ~iqueue() {}
606#else
607
608 protected:
609
611#endif
612 };
613
614 //***************************************************************************
622 //***************************************************************************
623 template <typename T, const size_t SIZE, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
624 class queue : public etl::iqueue<T, MEMORY_MODEL>
625 {
626 private:
627
628 typedef etl::iqueue<T, MEMORY_MODEL> base_t;
629
630 public:
631
632 typedef typename base_t::size_type size_type;
633 typedef typename etl::aligned_storage< sizeof(T), etl::alignment_of<T>::value>::type container_type;
634
635 ETL_STATIC_ASSERT((SIZE <= etl::integral_limits<size_type>::max), "Size too large for memory model");
636
637 static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
638
639 //*************************************************************************
641 //*************************************************************************
643 : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
644 {
645 }
646
647 //*************************************************************************
649 //*************************************************************************
650 queue(const queue& rhs)
651 : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
652 {
653 base_t::clone(rhs);
654 }
655
656#if ETL_USING_CPP11
657 //*************************************************************************
659 //*************************************************************************
660 queue(queue&& rhs)
661 : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
662 {
663 base_t::move_clone(etl::move(rhs));
664 }
665#endif
666
667 //*************************************************************************
669 //*************************************************************************
671 {
673 }
674
675 //*************************************************************************
677 //*************************************************************************
678 queue& operator=(const queue& rhs)
679 {
680 if (&rhs != this)
681 {
682 base_t::clone(rhs);
683 }
684
685 return *this;
686 }
687
688#if ETL_USING_CPP11
689 //*************************************************************************
691 //*************************************************************************
692 queue& operator=(queue&& rhs)
693 {
694 if (&rhs != this)
695 {
696 base_t::move_clone(etl::move(rhs));
697 }
698
699 return *this;
700 }
701#endif
702
703 private:
704
706 container_type buffer[SIZE];
707 };
708
709 template <typename T, const size_t SIZE, const size_t MEMORY_MODEL>
710 ETL_CONSTANT typename queue<T, SIZE, MEMORY_MODEL>::size_type queue<T, SIZE, MEMORY_MODEL>::MAX_SIZE;
711} // namespace etl
712
713#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:517
~queue()
Destructor.
Definition queue.h:670
size_type in
Definition queue.h:218
reference emplace(const T1 &value1, const T2 &value2)
Definition queue.h:403
queue & operator=(const queue &rhs)
Assignment operator.
Definition queue.h:678
const_reference front() const
Definition queue.h:282
ETL_DECLARE_DEBUG_COUNT
Definition queue.h:222
const T * const_pointer
A const pointer to the type used in the queue.
Definition queue.h:252
void push(const_reference value)
Definition queue.h:318
reference emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition queue.h:423
const_reference back() const
Definition queue.h:306
reference front()
Definition queue.h:270
size_type current_size
Definition queue.h:220
queue()
Default constructor.
Definition queue.h:642
void pop_into(reference destination)
Definition queue.h:496
etl::size_type_lookup< MEMORY_MODEL >::type size_type
The type used for determining the size of queue.
Definition queue.h:109
iqueue & operator=(const iqueue &rhs)
Assignment operator.
Definition queue.h:519
reference emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition queue.h:444
T value_type
The type stored in the queue.
Definition queue.h:245
void pop()
Definition queue.h:483
void index_clear()
Clears the indexes.
Definition queue.h:210
size_type out
Definition queue.h:219
~queue_base()
Destructor.
Definition queue.h:178
bool full() const
Definition queue.h:148
reference back()
Definition queue.h:294
size_type available() const
Definition queue.h:157
void del_out()
Increments (and wraps) the 'out' index value to record a queue deletion.
Definition queue.h:197
void add_in()
Increments (and wraps) the 'in' index value to record a queue addition.
Definition queue.h:183
~iqueue()
Destructor.
Definition queue.h:610
const size_type CAPACITY
Definition queue.h:221
reference emplace()
Definition queue.h:366
base_t::size_type size_type
The type used for determining the size of the queue.
Definition queue.h:253
iqueue(T *p_buffer_, size_type max_size_)
The constructor that is called from derived classes.
Definition queue.h:585
queue_base(size_type max_size_)
The constructor that is called from derived classes.
Definition queue.h:167
void clone(const iqueue &other)
Make this a clone of the supplied queue.
Definition queue.h:551
queue(const queue &rhs)
Copy constructor.
Definition queue.h:650
size_type size() const
Returns the current number of items in the queue.
Definition queue.h:114
const T & const_reference
A const reference to the type used in the queue.
Definition queue.h:247
void pop_into(TContainer &destination)
Definition queue.h:510
size_type capacity() const
Returns the maximum number of items that can be queued.
Definition queue.h:130
T & reference
A reference to the type used in the queue.
Definition queue.h:246
size_type max_size() const
Returns the maximum number of items that can be queued.
Definition queue.h:122
reference emplace(const T1 &value1)
Definition queue.h:384
bool empty() const
Definition queue.h:139
T * pointer
A pointer to the type used in the queue.
Definition queue.h:251
void clear()
Clears the queue to the empty state.
Definition queue.h:458
This is the base for all queues that contain a particular type.
Definition queue.h:238
Definition queue.h:625
Definition queue.h:105
Definition queue.h:90
Definition queue.h:76
Definition absolute.h:40
Definition memory_model.h:50