Embedded Template Library 1.0
Loading...
Searching...
No Matches
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),
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 //*************************************************************************
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 bool emplace()
376 {
377 this->lock();
378
379 bool result = emplace_implementation();
380
381 this->unlock();
382
383 return result;
384 }
385
386 //*************************************************************************
388 //*************************************************************************
389 template <typename T1>
390 bool emplace(const T1& value1)
391 {
392 this->lock();
393
394 bool result = emplace_implementation(value1);
395
396 this->unlock();
397
398 return result;
399 }
400
401 //*************************************************************************
403 //*************************************************************************
404 template <typename T1, typename T2>
405 bool emplace(const T1& value1, const T2& value2)
406 {
407 this->lock();
408
409 bool result = emplace_implementation(value1, value2);
410
411 this->unlock();
412
413 return result;
414 }
415
416 //*************************************************************************
418 //*************************************************************************
419 template <typename T1, typename T2, typename T3>
420 bool emplace(const T1& value1, const T2& value2, const T3& value3)
421 {
422 this->lock();
423
424 bool result = emplace_implementation(value1, value2, value3);
425
426 this->unlock();
427
428 return result;
429 }
430
431 //*************************************************************************
433 //*************************************************************************
434 template <typename T1, typename T2, typename T3, typename T4>
435 bool emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
436 {
437 this->lock();
438
439 bool result = emplace_implementation(value1, value2, value3, value4);
440
441 this->unlock();
442
443 return result;
444 }
445#endif
446
447 //*************************************************************************
449 //*************************************************************************
451 {
452 return pop_implementation();
453 }
454
455
456 //*************************************************************************
458 //*************************************************************************
459 bool pop()
460 {
461 this->lock();
462
463 bool result = pop_implementation();
464
465 this->unlock();
466
467 return result;
468 }
469
470 //*************************************************************************
472 //*************************************************************************
474 {
475 return pop_implementation(value);
476 }
477
478 //*************************************************************************
480 //*************************************************************************
481 bool pop(reference value)
482 {
483 this->lock();
484
485 bool result = pop_implementation(value);
486
487 this->unlock();
488
489 return result;
490 }
491
492 //*************************************************************************
494 //*************************************************************************
496 {
497 return front_implementation();
498 }
499
500 //*************************************************************************
502 //*************************************************************************
504 {
505 return front_implementation();
506 }
507
508 //*************************************************************************
510 //*************************************************************************
512 {
513 this->lock();
514
515 reference result = front_implementation();
516
517 this->unlock();
518
519 return result;
520 }
521
522 //*************************************************************************
524 //*************************************************************************
526 {
527 this->lock();
528
529 const_reference result = front_implementation();
530
531 this->unlock();
532
533 return result;
534 }
535
536 //*************************************************************************
538 //*************************************************************************
540 {
541 while (pop_implementation())
542 {
543 // Do nothing.
544 }
545 }
546
547 //*************************************************************************
549 //*************************************************************************
550 void clear()
551 {
552 this->lock();
553
554 while (pop_implementation())
555 {
556 // Do nothing.
557 }
558
559 this->unlock();
560 }
561
562 protected:
563
564 //*************************************************************************
566 //*************************************************************************
572
573 private:
574
575 //*************************************************************************
577 //*************************************************************************
578 bool push_implementation(const_reference value)
579 {
580 if (this->current_size != this->Max_Size)
581 {
582 ::new (&p_buffer[this->write_index]) T(value);
583
584 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
585
586 ++this->current_size;
587
588 return true;
589 }
590
591 // Queue is full.
592 return false;
593 }
594
595#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
596 //*************************************************************************
598 //*************************************************************************
599 bool push_implementation(rvalue_reference value)
600 {
601 if (this->current_size != this->Max_Size)
602 {
603 ::new (&p_buffer[this->write_index]) T(etl::move(value));
604
605 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
606
607 ++this->current_size;
608
609 return true;
610 }
611
612 // Queue is full.
613 return false;
614 }
615#endif
616
617#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
618 //*************************************************************************
620 //*************************************************************************
621 template <typename ... Args>
622 bool emplace_implementation(Args&&... args)
623 {
624 if (this->current_size != this->Max_Size)
625 {
626 ::new (&p_buffer[this->write_index]) T(etl::forward<Args>(args)...);
627
628 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
629
630 ++this->current_size;
631
632 return true;
633 }
634
635 // Queue is full.
636 return false;
637 }
638#else
639 //*************************************************************************
641 //*************************************************************************
642 template <typename T1>
643 bool emplace_implementation(const T1& value1)
644 {
645 if (this->current_size != this->Max_Size)
646 {
647 ::new (&p_buffer[this->write_index]) T(value1);
648
649 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
650
651 ++this->current_size;
652
653 return true;
654 }
655
656 // Queue is full.
657 return false;
658 }
659
660 //*************************************************************************
662 //*************************************************************************
663 template <typename T1, typename T2>
664 bool emplace_implementation(const T1& value1, const T2& value2)
665 {
666 if (this->current_size != this->Max_Size)
667 {
668 ::new (&p_buffer[this->write_index]) T(value1, value2);
669
670 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
671
672 ++this->current_size;
673
674 return true;
675 }
676
677 // Queue is full.
678 return false;
679 }
680
681 //*************************************************************************
683 //*************************************************************************
684 template <typename T1, typename T2, typename T3>
685 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3)
686 {
687 if (this->current_size != this->Max_Size)
688 {
689 ::new (&p_buffer[this->write_index]) T(value1, value2, value3);
690
691 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
692
693 ++this->current_size;
694
695 return true;
696 }
697
698 // Queue is full.
699 return false;
700 }
701
702 //*************************************************************************
704 //*************************************************************************
705 template <typename T1, typename T2, typename T3, typename T4>
706 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
707 {
708 if (this->current_size != this->Max_Size)
709 {
710 ::new (&p_buffer[this->write_index]) T(value1, value2, value3, value4);
711
712 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
713
714 ++this->current_size;
715
716 return true;
717 }
718
719 // Queue is full.
720 return false;
721 }
722#endif
723
724 //*************************************************************************
726 //*************************************************************************
727 bool pop_implementation()
728 {
729 if (this->current_size == 0)
730 {
731 // Queue is empty
732 return false;
733 }
734
735 p_buffer[this->read_index].~T();
736
737 this->read_index = this->get_next_index(this->read_index, this->Max_Size);
738
739 --this->current_size;
740
741 return true;
742 }
743
744 //*************************************************************************
746 //*************************************************************************
747 bool pop_implementation(reference value)
748 {
749 if (this->current_size == 0)
750 {
751 // Queue is empty
752 return false;
753 }
754
755#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
756 value = etl::move(p_buffer[this->read_index]);
757#else
758 value = p_buffer[this->read_index];
759#endif
760
761 p_buffer[this->read_index].~T();
762
763 this->read_index = this->get_next_index(this->read_index, this->Max_Size);
764
765 --this->current_size;
766
767 return true;
768 }
769
770 //*************************************************************************
772 //*************************************************************************
773 reference front_implementation()
774 {
775 return p_buffer[this->read_index];;
776 }
777
778 //*************************************************************************
780 //*************************************************************************
781 const_reference front_implementation() const
782 {
783 return p_buffer[this->read_index];;
784 }
785
786 // Disable copy construction and assignment.
787 iqueue_lockable(const iqueue_lockable&) ETL_DELETE;
788 iqueue_lockable& operator =(const iqueue_lockable&) ETL_DELETE;
789
790#if ETL_USING_CPP11
791 iqueue_lockable(iqueue_lockable&&) = delete;
792 iqueue_lockable& operator =(iqueue_lockable&&) = delete;
793#endif
794
795 T* p_buffer;
796 };
797
798 //***************************************************************************
804 //***************************************************************************
805 template <typename T, size_t VSize, size_t VMemory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
806 class queue_lockable : public etl::iqueue_lockable<T, VMemory_Model>
807 {
808 private:
809
811
812 public:
813
814 typedef typename base_t::size_type size_type;
815
816 ETL_STATIC_ASSERT((VSize <= etl::integral_limits<size_type>::max), "Size too large for memory model");
817
818 static ETL_CONSTANT size_type Max_Size = size_type(VSize);
819 static ETL_CONSTANT size_type Memory_Model = size_type(VMemory_Model);
820
821 //*************************************************************************
823 //*************************************************************************
824
826 : base_t(reinterpret_cast<T*>(buffer.raw), Max_Size)
827 {
828 }
829
830 //*************************************************************************
832 //*************************************************************************
834 {
835 while (this->pop_unlocked())
836 {
837 // Do nothing.
838 }
839 }
840
841 private:
842
843 queue_lockable(const queue_lockable&) ETL_DELETE;
844 queue_lockable& operator = (const queue_lockable&) ETL_DELETE;
845
846#if ETL_USING_CPP11
847 queue_lockable(queue_lockable&&) = delete;
849#endif
850
853 };
854
855 template <typename T, size_t VSize, size_t VMemory_Model>
856 ETL_CONSTANT typename queue_lockable<T, VSize, VMemory_Model>::size_type queue_lockable<T, VSize, VMemory_Model>::Max_Size;
857
858 template <typename T, size_t VSize, size_t VMemory_Model>
859 ETL_CONSTANT typename queue_lockable<T, VSize, VMemory_Model>::size_type queue_lockable<T, VSize, VMemory_Model>::Memory_Model;
860}
861
862#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:481
reference front_unlocked()
Peek a value at the front of the queue without locking.
Definition queue_lockable.h:495
bool pop_unlocked(reference value)
Pop a value from the queue without locking.
Definition queue_lockable.h:473
bool pop()
Pop a value from the queue and discard.
Definition queue_lockable.h:459
reference front()
Peek a value at the front of the queue.
Definition queue_lockable.h:511
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:435
bool emplace(const T1 &value1)
Constructs a value in the queue 'in place'.
Definition queue_lockable.h:390
void clear()
Clear the queue.
Definition queue_lockable.h:550
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:503
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:450
bool emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Constructs a value in the queue 'in place'.
Definition queue_lockable.h:420
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:567
bool emplace(const T1 &value1, const T2 &value2)
Constructs a value in the queue 'in place'.
Definition queue_lockable.h:405
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:525
bool emplace()
Constructs a value in the queue 'in place'.
Definition queue_lockable.h:375
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:539
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:807
~queue_lockable()
Destructor.
Definition queue_lockable.h:833
queue_lockable()
Default constructor.
Definition queue_lockable.h:825
Definition integral_limits.h:516
bitset_ext
Definition absolute.h:38
pair holds two objects of arbitrary type
Definition utility.h:164
Definition memory_model.h:50