Embedded Template Library 1.0
queue_lockable.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) 2019 John Wellbelove
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_LOCKABLE_INCLUDED
32#define ETL_QUEUE_LOCKABLE_INCLUDED
33
34#include "platform.h"
35#include "memory.h"
36#include "parameter_type.h"
37#include "memory_model.h"
38#include "integral_limits.h"
39#include "function.h"
40#include "utility.h"
41#include "placement_new.h"
42
43#include <stddef.h>
44#include <stdint.h>
45
46namespace etl
47{
48 template <size_t VMemory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
50 {
51 public:
52
55
56 //*************************************************************************
58 //*************************************************************************
60 {
61 }
62
63 //*************************************************************************
66 //*************************************************************************
68 {
69 return available_implementation();
70 }
71
72 //*************************************************************************
74 //*************************************************************************
76 {
77 this->lock();
78
79 size_type result = available_implementation();
80
81 this->unlock();
82
83 return result;
84 }
85
86 //*************************************************************************
89 //*************************************************************************
90 bool empty_unlocked() const
91 {
92 return empty_implementation();
93 }
94
95 //*************************************************************************
97 //*************************************************************************
98 bool empty() const
99 {
100 this->lock();
101
102 size_type result = empty_implementation();
103
104 this->unlock();
105
106 return result;
107 }
108
109 //*************************************************************************
112 //*************************************************************************
113 bool full_unlocked() const
114 {
115 return full_implementation();
116 }
117
118 //*************************************************************************
120 //*************************************************************************
121 bool full() const
122 {
123 this->lock();
124
125 size_type result = full_implementation();
126
127 this->unlock();
128
129 return result;
130 }
131
132 //*************************************************************************
135 //*************************************************************************
137 {
138 return size_implementation();
139 }
140
141 //*************************************************************************
143 //*************************************************************************
145 {
146 this->lock();
147
148 size_type result = size_implementation();
149
150 this->unlock();
151
152 return result;
153 }
154
155 //*************************************************************************
157 //*************************************************************************
159 {
160 return Max_Size;
161 }
162
163 //*************************************************************************
165 //*************************************************************************
167 {
168 return Max_Size;
169 }
170
171 protected:
172
174 : write_index(0),
175 read_index(0),
176 current_size(0),
177 Max_Size(max_size_)
178 {
179 }
180
181 //*************************************************************************
183 //*************************************************************************
185 {
186 ++index;
187
188 if (index == maximum) ETL_UNLIKELY
189 {
190 index = 0;
191 }
192
193 return index;
194 }
195
196 //*************************************************************************
198 //*************************************************************************
199 virtual void lock() const = 0;
200 virtual void unlock() const = 0;
201
206
207 private:
208
209 //*************************************************************************
211 //*************************************************************************
212 size_type available_implementation() const
213 {
214 return Max_Size - current_size;
215 }
216
217 //*************************************************************************
219 //*************************************************************************
220 bool empty_implementation() const
221 {
222 return (current_size == 0);
223 }
224
225 //*************************************************************************
227 //*************************************************************************
228 bool full_implementation() const
229 {
230 return (current_size == Max_Size);;
231 }
232
233 //*************************************************************************
235 //*************************************************************************
236 size_type size_implementation() const
237 {
238 return current_size;
239 }
240 };
241
242 //***************************************************************************
247 //***************************************************************************
248 template <typename T, const size_t VMemory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
249 class iqueue_lockable : public etl::queue_lockable_base<VMemory_Model>
250 {
251 private:
252
254
255 public:
256
257 typedef T value_type;
258 typedef T& reference;
259 typedef const T& const_reference;
260#if ETL_USING_CPP11
261 typedef T&& rvalue_reference;
262#endif
263 typedef typename base_t::size_type size_type;
264
265 //*************************************************************************
267 //*************************************************************************
269 {
270 return push_implementation(value);
271 }
272
273 //*************************************************************************
275 //*************************************************************************
277 {
278 this->lock();
279
280 bool result = push_implementation(value);
281
282 this->unlock();
283
284 return result;
285 }
286
287#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
288 //*************************************************************************
290 //*************************************************************************
291 bool push_unlocked(rvalue_reference value)
292 {
293 return push_implementation(value);
294 }
295
296 //*************************************************************************
298 //*************************************************************************
299 bool push(rvalue_reference value)
300 {
301 this->lock();
302
303 bool result = push_implementation(etl::move(value));
304
305 this->unlock();
306
307 return result;
308 }
309#endif
310
311#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
312 //*************************************************************************
314 //*************************************************************************
315 template <typename ... Args>
316 bool emplace_unlocked(Args&&... args)
317 {
318 return emplace_implementation(etl::forward<Args>(args)...);
319 }
320
321 //*************************************************************************
323 //*************************************************************************
324 template <typename ... Args>
325 bool emplace(Args&&... args)
326 {
327 this->lock();
328
329 bool result = emplace_implementation(etl::forward<Args>(args)...);
330
331 this->unlock();
332
333 return result;
334 }
335#else
336 //*************************************************************************
338 //*************************************************************************
339 template <typename T1>
340 bool emplace_unlocked(const T1& value1)
341 {
342 return emplace_implementation(value1);
343 }
344
345 //*************************************************************************
347 //*************************************************************************
348 template <typename T1, typename T2>
349 bool emplace_unlocked(const T1& value1, const T2& value2)
350 {
351 return emplace_implementation(value1, value2);
352 }
353
354 //*************************************************************************
356 //*************************************************************************
357 template <typename T1, typename T2, typename T3>
358 bool emplace_unlocked(const T1& value1, const T2& value2, const T3& value3)
359 {
360 return emplace_implementation(value1, value2, value3);
361 }
362
363 //*************************************************************************
365 //*************************************************************************
366 template <typename T1, typename T2, typename T3, typename T4>
367 bool emplace_unlocked(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
368 {
369 return emplace_implementation(value1, value2, value3, value4);
370 }
371
372 //*************************************************************************
374 //*************************************************************************
375 template <typename T1>
376 bool emplace(const T1& value1)
377 {
378 this->lock();
379
380 bool result = emplace_implementation(value1);
381
382 this->unlock();
383
384 return result;
385 }
386
387 //*************************************************************************
389 //*************************************************************************
390 template <typename T1, typename T2>
391 bool emplace(const T1& value1, const T2& value2)
392 {
393 this->lock();
394
395 bool result = emplace_implementation(value1, value2);
396
397 this->unlock();
398
399 return result;
400 }
401
402 //*************************************************************************
404 //*************************************************************************
405 template <typename T1, typename T2, typename T3>
406 bool emplace(const T1& value1, const T2& value2, const T3& value3)
407 {
408 this->lock();
409
410 bool result = emplace_implementation(value1, value2, value3);
411
412 this->unlock();
413
414 return result;
415 }
416
417 //*************************************************************************
419 //*************************************************************************
420 template <typename T1, typename T2, typename T3, typename T4>
421 bool emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
422 {
423 this->lock();
424
425 bool result = emplace_implementation(value1, value2, value3, value4);
426
427 this->unlock();
428
429 return result;
430 }
431#endif
432
433 //*************************************************************************
435 //*************************************************************************
437 {
438 return pop_implementation();
439 }
440
441
442 //*************************************************************************
444 //*************************************************************************
445 bool pop()
446 {
447 this->lock();
448
449 bool result = pop_implementation();
450
451 this->unlock();
452
453 return result;
454 }
455
456 //*************************************************************************
458 //*************************************************************************
460 {
461 return pop_implementation(value);
462 }
463
464 //*************************************************************************
466 //*************************************************************************
467 bool pop(reference value)
468 {
469 this->lock();
470
471 bool result = pop_implementation(value);
472
473 this->unlock();
474
475 return result;
476 }
477
478 //*************************************************************************
480 //*************************************************************************
482 {
483 return front_implementation();
484 }
485
486 //*************************************************************************
488 //*************************************************************************
490 {
491 return front_implementation();
492 }
493
494 //*************************************************************************
496 //*************************************************************************
498 {
499 this->lock();
500
501 reference result = front_implementation();
502
503 this->unlock();
504
505 return result;
506 }
507
508 //*************************************************************************
510 //*************************************************************************
512 {
513 this->lock();
514
515 const_reference result = front_implementation();
516
517 this->unlock();
518
519 return result;
520 }
521
522 //*************************************************************************
524 //*************************************************************************
526 {
527 while (pop_implementation())
528 {
529 // Do nothing.
530 }
531 }
532
533 //*************************************************************************
535 //*************************************************************************
536 void clear()
537 {
538 this->lock();
539
540 while (pop_implementation())
541 {
542 // Do nothing.
543 }
544
545 this->unlock();
546 }
547
548 protected:
549
550 //*************************************************************************
552 //*************************************************************************
553 iqueue_lockable(T* p_buffer_, size_type max_size_)
554 : base_t(max_size_)
555 , p_buffer(p_buffer_)
556 {
557 }
558
559 private:
560
561 //*************************************************************************
563 //*************************************************************************
564 bool push_implementation(const_reference value)
565 {
566 if (this->current_size != this->Max_Size)
567 {
568 ::new (&p_buffer[this->write_index]) T(value);
569
570 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
571
572 ++this->current_size;
573
574 return true;
575 }
576
577 // Queue is full.
578 return false;
579 }
580
581#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
582 //*************************************************************************
584 //*************************************************************************
585 bool push_implementation(rvalue_reference value)
586 {
587 if (this->current_size != this->Max_Size)
588 {
589 ::new (&p_buffer[this->write_index]) T(etl::move(value));
590
591 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
592
593 ++this->current_size;
594
595 return true;
596 }
597
598 // Queue is full.
599 return false;
600 }
601#endif
602
603#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
604 //*************************************************************************
606 //*************************************************************************
607 template <typename ... Args>
608 bool emplace_implementation(Args&&... args)
609 {
610 if (this->current_size != this->Max_Size)
611 {
612 ::new (&p_buffer[this->write_index]) T(etl::forward<Args>(args)...);
613
614 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
615
616 ++this->current_size;
617
618 return true;
619 }
620
621 // Queue is full.
622 return false;
623 }
624#else
625 //*************************************************************************
627 //*************************************************************************
628 template <typename T1>
629 bool emplace_implementation(const T1& value1)
630 {
631 if (this->current_size != this->Max_Size)
632 {
633 ::new (&p_buffer[this->write_index]) T(value1);
634
635 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
636
637 ++this->current_size;
638
639 return true;
640 }
641
642 // Queue is full.
643 return false;
644 }
645
646 //*************************************************************************
648 //*************************************************************************
649 template <typename T1, typename T2>
650 bool emplace_implementation(const T1& value1, const T2& value2)
651 {
652 if (this->current_size != this->Max_Size)
653 {
654 ::new (&p_buffer[this->write_index]) T(value1, value2);
655
656 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
657
658 ++this->current_size;
659
660 return true;
661 }
662
663 // Queue is full.
664 return false;
665 }
666
667 //*************************************************************************
669 //*************************************************************************
670 template <typename T1, typename T2, typename T3>
671 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3)
672 {
673 if (this->current_size != this->Max_Size)
674 {
675 ::new (&p_buffer[this->write_index]) T(value1, value2, value3);
676
677 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
678
679 ++this->current_size;
680
681 return true;
682 }
683
684 // Queue is full.
685 return false;
686 }
687
688 //*************************************************************************
690 //*************************************************************************
691 template <typename T1, typename T2, typename T3, typename T4>
692 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
693 {
694 if (this->current_size != this->Max_Size)
695 {
696 ::new (&p_buffer[this->write_index]) T(value1, value2, value3, value4);
697
698 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
699
700 ++this->current_size;
701
702 return true;
703 }
704
705 // Queue is full.
706 return false;
707 }
708#endif
709
710 //*************************************************************************
712 //*************************************************************************
713 bool pop_implementation()
714 {
715 if (this->current_size == 0)
716 {
717 // Queue is empty
718 return false;
719 }
720
721 p_buffer[this->read_index].~T();
722
723 this->read_index = this->get_next_index(this->read_index, this->Max_Size);
724
725 --this->current_size;
726
727 return true;
728 }
729
730 //*************************************************************************
732 //*************************************************************************
733 bool pop_implementation(reference value)
734 {
735 if (this->current_size == 0)
736 {
737 // Queue is empty
738 return false;
739 }
740
741#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
742 value = etl::move(p_buffer[this->read_index]);
743#else
744 value = p_buffer[this->read_index];
745#endif
746
747 p_buffer[this->read_index].~T();
748
749 this->read_index = this->get_next_index(this->read_index, this->Max_Size);
750
751 --this->current_size;
752
753 return true;
754 }
755
756 //*************************************************************************
758 //*************************************************************************
759 reference front_implementation()
760 {
761 return p_buffer[this->read_index];;
762 }
763
764 //*************************************************************************
766 //*************************************************************************
767 const_reference front_implementation() const
768 {
769 return p_buffer[this->read_index];;
770 }
771
772 // Disable copy construction and assignment.
773 iqueue_lockable(const iqueue_lockable&) ETL_DELETE;
774 iqueue_lockable& operator =(const iqueue_lockable&) ETL_DELETE;
775
776#if ETL_USING_CPP11
778 iqueue_lockable& operator =(iqueue_lockable&&) = delete;
779#endif
780
781 T* p_buffer;
782 };
783
784 //***************************************************************************
790 //***************************************************************************
791 template <typename T, size_t VSize, size_t VMemory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
792 class queue_lockable : public etl::iqueue_lockable<T, VMemory_Model>
793 {
794 private:
795
797
798 public:
799
800 typedef typename base_t::size_type size_type;
801
802 ETL_STATIC_ASSERT((VSize <= etl::integral_limits<size_type>::max), "Size too large for memory model");
803
804 static ETL_CONSTANT size_type Max_Size = size_type(VSize);
805 static ETL_CONSTANT size_type Memory_Model = size_type(VMemory_Model);
806
807 //*************************************************************************
809 //*************************************************************************
810
812 : base_t(reinterpret_cast<T*>(buffer.raw), Max_Size)
813 {
814 }
815
816 //*************************************************************************
818 //*************************************************************************
820 {
821 while (this->pop_unlocked())
822 {
823 // Do nothing.
824 }
825 }
826
827 private:
828
829 queue_lockable(const queue_lockable&) ETL_DELETE;
830 queue_lockable& operator = (const queue_lockable&) ETL_DELETE;
831
832#if ETL_USING_CPP11
833 queue_lockable(queue_lockable&&) = delete;
834 queue_lockable& operator =(queue_lockable&&) = delete;
835#endif
836
839 };
840
841 template <typename T, size_t VSize, size_t VMemory_Model>
842 ETL_CONSTANT typename queue_lockable<T, VSize, VMemory_Model>::size_type queue_lockable<T, VSize, VMemory_Model>::Max_Size;
843
844 template <typename T, size_t VSize, size_t VMemory_Model>
845 ETL_CONSTANT typename queue_lockable<T, VSize, VMemory_Model>::size_type queue_lockable<T, VSize, VMemory_Model>::Memory_Model;
846}
847
848#endif
This is the base for all queues that contain a particular type.
Definition: queue_lockable.h:250
bool pop(reference value)
Pop a value from the queue.
Definition: queue_lockable.h:467
reference front_unlocked()
Peek a value at the front of the queue without locking.
Definition: queue_lockable.h:481
bool pop_unlocked(reference value)
Pop a value from the queue without locking.
Definition: queue_lockable.h:459
bool pop()
Pop a value from the queue and discard.
Definition: queue_lockable.h:445
reference front()
Peek a value at the front of the queue.
Definition: queue_lockable.h:497
bool emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Constructs a value in the queue 'in place'.
Definition: queue_lockable.h:421
bool emplace(const T1 &value1)
Constructs a value in the queue 'in place'.
Definition: queue_lockable.h:376
void clear()
Clear the queue.
Definition: queue_lockable.h:536
bool emplace_unlocked(const T1 &value1, const T2 &value2, const T3 &value3)
Constructs a value in the queue 'in place'.
Definition: queue_lockable.h:358
const_reference front_unlocked() const
Peek a value at the front of the queue without locking.
Definition: queue_lockable.h:489
bool emplace_unlocked(const T1 &value1)
Constructs a value in the queue 'in place'.
Definition: queue_lockable.h:340
bool push_unlocked(const_reference value)
Push a value to the queue without locking.
Definition: queue_lockable.h:268
bool pop_unlocked()
Pop a value from the queue without locking, and discard.
Definition: queue_lockable.h:436
bool emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Constructs a value in the queue 'in place'.
Definition: queue_lockable.h:406
bool emplace_unlocked(const T1 &value1, const T2 &value2)
Constructs a value in the queue 'in place'.
Definition: queue_lockable.h:349
iqueue_lockable(T *p_buffer_, size_type max_size_)
The constructor that is called from derived classes.
Definition: queue_lockable.h:553
bool emplace(const T1 &value1, const T2 &value2)
Constructs a value in the queue 'in place'.
Definition: queue_lockable.h:391
base_t::size_type size_type
The type used for determining the size of the queue.
Definition: queue_lockable.h:263
const_reference front() const
Peek a value at the front of the queue.
Definition: queue_lockable.h:511
const T & const_reference
A const reference to the type used in the queue.
Definition: queue_lockable.h:259
T value_type
The type stored in the queue.
Definition: queue_lockable.h:257
bool emplace_unlocked(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Constructs a value in the queue 'in place'.
Definition: queue_lockable.h:367
bool push(const_reference value)
Push a value to the queue.
Definition: queue_lockable.h:276
void clear_unlocked()
Clear the queue, unlocked.
Definition: queue_lockable.h:525
T & reference
A reference to the type used in the queue.
Definition: queue_lockable.h:258
Definition: queue_lockable.h:50
size_type size_unlocked() const
Definition: queue_lockable.h:136
size_type capacity() const
How many items can the queue hold.
Definition: queue_lockable.h:158
size_type max_size() const
How many items can the queue hold.
Definition: queue_lockable.h:166
bool empty() const
Is the queue empty?
Definition: queue_lockable.h:98
bool empty_unlocked() const
Definition: queue_lockable.h:90
const size_type Max_Size
The maximum number of items in the queue.
Definition: queue_lockable.h:205
size_type read_index
Where to get the oldest data.
Definition: queue_lockable.h:203
size_type current_size
The current size of the queue.
Definition: queue_lockable.h:204
size_type available_unlocked() const
Definition: queue_lockable.h:67
etl::size_type_lookup< VMemory_Model >::type size_type
The type used for determining the size of queue.
Definition: queue_lockable.h:54
size_type write_index
Where to input new data.
Definition: queue_lockable.h:202
static size_type get_next_index(size_type index, size_type maximum)
Calculate the next index.
Definition: queue_lockable.h:184
size_type size() const
How many items in the queue?
Definition: queue_lockable.h:144
virtual void lock() const =0
The pure virtual lock and unlock functions.
bool full_unlocked() const
Definition: queue_lockable.h:113
size_type available() const
How much free space available in the queue.
Definition: queue_lockable.h:75
bool full() const
Is the queue full?
Definition: queue_lockable.h:121
virtual ~queue_lockable_base()
Destructor.
Definition: queue_lockable.h:59
Definition: queue_lockable.h:793
~queue_lockable()
Destructor.
Definition: queue_lockable.h:819
queue_lockable()
Default constructor.
Definition: queue_lockable.h:811
Definition: integral_limits.h:468
bitset_ext
Definition: absolute.h:38
Definition: memory_model.h:50