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 "exception.h"
37#include "error_handler.h"
38#include "debug_count.h"
39#include "type_traits.h"
40#include "parameter_type.h"
41#include "memory_model.h"
42#include "integral_limits.h"
43#include "utility.h"
44#include "placement_new.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 }
182
183 //*************************************************************************
185 //*************************************************************************
186 void add_in()
187 {
188 if (++in == CAPACITY) ETL_UNLIKELY
189 {
190 in = 0;
191 }
192
193 ++current_size;
194 ETL_INCREMENT_DEBUG_COUNT;
195 }
196
197 //*************************************************************************
199 //*************************************************************************
200 void del_out()
201 {
202 if (++out == CAPACITY) ETL_UNLIKELY
203 {
204 out = 0;
205 }
206 --current_size;
207 ETL_DECREMENT_DEBUG_COUNT;
208 }
209
210 //*************************************************************************
212 //*************************************************************************
214 {
215 in = 0;
216 out = 0;
217 current_size = 0;
218 ETL_RESET_DEBUG_COUNT;
219 }
220
226
227 };
228
229 //***************************************************************************
239 //***************************************************************************
240 template <typename T, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
241 class iqueue : public etl::queue_base<MEMORY_MODEL>
242 {
243 private:
244
245 typedef typename etl::queue_base<MEMORY_MODEL> base_t;
246
247 public:
248
249 typedef T value_type;
250 typedef T& reference;
251 typedef const T& const_reference;
252#if ETL_USING_CPP11
253 typedef T&& rvalue_reference;
254#endif
255 typedef T* pointer;
256 typedef const T* const_pointer;
257 typedef typename base_t::size_type size_type;
258
259 using base_t::in;
260 using base_t::out;
261 using base_t::CAPACITY;
263 using base_t::full;
264 using base_t::empty;
265 using base_t::add_in;
266 using base_t::del_out;
267
268 //*************************************************************************
271 //*************************************************************************
273 {
274 return p_buffer[out];
275 }
276
277 //*************************************************************************
280 //*************************************************************************
282 {
283 return p_buffer[out];
284 }
285
286 //*************************************************************************
289 //*************************************************************************
291 {
292 return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
293 }
294
295 //*************************************************************************
298 //*************************************************************************
300 {
301 return p_buffer[in == 0 ? CAPACITY - 1 : in - 1];
302 }
303
304 //*************************************************************************
308 //*************************************************************************
310 {
311 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(queue_full));
312
313 ::new (&p_buffer[in]) T(value);
314 add_in();
315 }
316
317#if ETL_USING_CPP11
318 //*************************************************************************
322 //*************************************************************************
323 void push(rvalue_reference value)
324 {
325 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!full(), ETL_ERROR(queue_full));
326
327 ::new (&p_buffer[in]) T(etl::move(value));
328 add_in();
329 }
330#endif
331
332#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_FORCE_CPP03_IMPLEMENTATION)
333 //*************************************************************************
337 //*************************************************************************
338 template <typename ... Args>
339 reference emplace(Args && ... args)
340 {
341 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
342
343 reference value = p_buffer[in];
344 ::new (&value) T(etl::forward<Args>(args)...);
345 add_in();
346 return value;
347 }
348#else
349 //*************************************************************************
352 //*************************************************************************
354 {
355 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
356
357 reference value = p_buffer[in];
358 ::new (&value) T();
359 add_in();
360 return value;
361 }
362
363 //*************************************************************************
367 //*************************************************************************
368 template <typename T1>
369 reference emplace(const T1& value1)
370 {
371 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
372
373 reference value = p_buffer[in];
374 ::new (&value) T(value1);
375 add_in();
376 return value;
377 }
378
379 //*************************************************************************
384 //*************************************************************************
385 template <typename T1, typename T2>
386 reference emplace(const T1& value1, const T2& value2)
387 {
388 ETL_ASSERT_CHECK_PUSH_POP(!full(), ETL_ERROR(queue_full));
389
390 reference value = p_buffer[in];
391 ::new (&value) T(value1, value2);
392 add_in();
393 return value;
394 }
395
396 //*************************************************************************
402 //*************************************************************************
403 template <typename T1, typename T2, typename T3>
404 reference emplace(const T1& value1, const T2& value2, const T3& value3)
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, value3);
410 add_in();
411 return value;
412 }
413
414 //*************************************************************************
421 //*************************************************************************
422 template <typename T1, typename T2, typename T3, typename T4>
423 reference emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
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, value4);
429 add_in();
430 return value;
431 }
432#endif
433
434 //*************************************************************************
436 //*************************************************************************
437 void clear()
438 {
439 if ETL_IF_CONSTEXPR(etl::is_trivially_destructible<T>::value)
440 {
442 }
443 else
444 {
445 while (current_size > 0)
446 {
447 p_buffer[out].~T();
448 del_out();
449 }
450
451 in = 0;
452 out = 0;
453 }
454 }
455
456 //*************************************************************************
460 //*************************************************************************
461 void pop()
462 {
463 ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(queue_empty));
464
465 p_buffer[out].~T();
466 del_out();
467 }
468
469 //*************************************************************************
472 //*************************************************************************
473 void pop_into(reference destination)
474 {
475 destination = ETL_MOVE(front());
476 pop();
477 }
478
479 //*************************************************************************
484 //*************************************************************************
485 template <typename TContainer>
486 void pop_into(TContainer& destination)
487 {
488 destination.push(ETL_MOVE(front()));
489 pop();
490 }
491
492 //*************************************************************************
494 //*************************************************************************
496 {
497 if (&rhs != this)
498 {
499 clear();
500 clone(rhs);
501 }
502
503 return *this;
504 }
505
506#if ETL_USING_CPP11
507 //*************************************************************************
509 //*************************************************************************
511 {
512 if (&rhs != this)
513 {
514 clear();
515 move_clone(rhs);
516 }
517
518 return *this;
519 }
520#endif
521
522 protected:
523
524 //*************************************************************************
526 //*************************************************************************
527 void clone(const 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(other.p_buffer[index]);
536 index = (index == (CAPACITY - 1)) ? 0 : index + 1;
537 }
538 }
539
540#if ETL_USING_CPP11
541 //*************************************************************************
543 //*************************************************************************
544 void move_clone(iqueue&& other)
545 {
546 clear();
547
548 size_type index = other.out;
549
550 for (size_type i = 0; i < other.size(); ++i)
551 {
552 push(etl::move(other.p_buffer[index]));
553 index = (index == (CAPACITY - 1)) ? 0 : index + 1;
554 }
555 }
556#endif
557
558 //*************************************************************************
560 //*************************************************************************
561 iqueue(T* p_buffer_, size_type max_size_)
562 : base_t(max_size_),
563 p_buffer(p_buffer_)
564 {
565 }
566
567 private:
568
569 // Disable copy construction.
570 iqueue(const iqueue&);
571
572 T* p_buffer;
573
574 //*************************************************************************
576 //*************************************************************************
577#if defined(ETL_POLYMORPHIC_QUEUE) || defined(ETL_POLYMORPHIC_CONTAINERS)
578 public:
579 virtual ~iqueue()
580 {
581 }
582#else
583 protected:
585 {
586 }
587#endif
588 };
589
590 //***************************************************************************
597 //***************************************************************************
598 template <typename T, const size_t SIZE, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
599 class queue : public etl::iqueue<T, MEMORY_MODEL>
600 {
601 private:
602
603 typedef etl::iqueue<T, MEMORY_MODEL> base_t;
604
605 public:
606
607 typedef typename base_t::size_type size_type;
608 typedef typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type container_type;
609
610 ETL_STATIC_ASSERT((SIZE <= etl::integral_limits<size_type>::max), "Size too large for memory model");
611
612 static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
613
614 //*************************************************************************
616 //*************************************************************************
618 : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
619 {
620 }
621
622 //*************************************************************************
624 //*************************************************************************
625 queue(const queue& rhs)
626 : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
627 {
628 base_t::clone(rhs);
629 }
630
631#if ETL_USING_CPP11
632 //*************************************************************************
634 //*************************************************************************
635 queue(queue&& rhs)
636 : base_t(reinterpret_cast<T*>(&buffer[0]), SIZE)
637 {
638 base_t::move_clone(etl::move(rhs));
639 }
640#endif
641
642 //*************************************************************************
644 //*************************************************************************
646 {
648 }
649
650 //*************************************************************************
652 //*************************************************************************
654 {
655 if (&rhs != this)
656 {
657 base_t::clone(rhs);
658 }
659
660 return *this;
661 }
662
663#if ETL_USING_CPP11
664 //*************************************************************************
666 //*************************************************************************
667 queue& operator = (queue&& rhs)
668 {
669 if (&rhs != this)
670 {
671 base_t::move_clone(etl::move(rhs));
672 }
673
674 return *this;
675 }
676#endif
677
678 private:
679
681 container_type buffer[SIZE];
682 };
683
684 template <typename T, const size_t SIZE, const size_t MEMORY_MODEL>
685 ETL_CONSTANT typename queue<T, SIZE, MEMORY_MODEL>::size_type queue<T, SIZE, MEMORY_MODEL>::MAX_SIZE;
686}
687
688#endif
Definition alignment.h:246
ETL_CONSTEXPR exception(string_type reason_, string_type, numeric_type line_)
Constructor.
Definition exception.h:69
Definition integral_limits.h:516
~queue()
Destructor.
Definition queue.h:645
size_type in
Definition queue.h:221
reference emplace(const T1 &value1, const T2 &value2)
Definition queue.h:386
queue & operator=(const queue &rhs)
Assignment operator.
Definition queue.h:653
const_reference front() const
Definition queue.h:281
ETL_DECLARE_DEBUG_COUNT
Definition queue.h:225
const T * const_pointer
A const pointer to the type used in the queue.
Definition queue.h:256
void push(const_reference value)
Definition queue.h:309
reference emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition queue.h:404
const_reference back() const
Definition queue.h:299
reference front()
Definition queue.h:272
size_type current_size
Definition queue.h:223
queue()
Default constructor.
Definition queue.h:617
void pop_into(reference destination)
Definition queue.h:473
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:495
reference emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition queue.h:423
T value_type
The type stored in the queue.
Definition queue.h:249
void pop()
Definition queue.h:461
void index_clear()
Clears the indexes.
Definition queue.h:213
size_type out
Definition queue.h:222
~queue_base()
Destructor.
Definition queue.h:179
bool full() const
Definition queue.h:149
reference back()
Definition queue.h:290
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:200
void add_in()
Increments (and wraps) the 'in' index value to record a queue addition.
Definition queue.h:186
~iqueue()
Destructor.
Definition queue.h:584
const size_type CAPACITY
Definition queue.h:224
reference emplace()
Definition queue.h:353
base_t::size_type size_type
The type used for determining the size of the queue.
Definition queue.h:257
iqueue(T *p_buffer_, size_type max_size_)
The constructor that is called from derived classes.
Definition queue.h:561
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:527
queue(const queue &rhs)
Copy constructor.
Definition queue.h:625
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:251
void pop_into(TContainer &destination)
Definition queue.h:486
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:250
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:369
bool empty() const
Definition queue.h:140
T * pointer
A pointer to the type used in the queue.
Definition queue.h:255
void clear()
Clears the queue to the empty state.
Definition queue.h:437
This is the base for all queues that contain a particular type.
Definition queue.h:242
Definition queue.h:600
Definition queue.h:106
Definition queue.h:91
Definition queue.h:77
add_rvalue_reference
Definition type_traits_generator.h:1413
size_type size() const
Definition vector.h:990
bitset_ext
Definition absolute.h:39
Definition memory_model.h:50