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>
49 class queue_lockable_base
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
253 typedef queue_lockable_base<VMemory_Model> base_t;
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 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 if ETL_IF_CONSTEXPR(etl::is_trivially_destructible<T>::value)
555 {
556 this->write_index = 0;
557 this->read_index = 0;
558 this->current_size = 0;
559 }
560 else
561 {
562 while (pop_implementation())
563 {
564 // Do nothing.
565 }
566 }
567
568 this->unlock();
569 }
570
571 protected:
572
573 //*************************************************************************
575 //*************************************************************************
576 iqueue_lockable(T* p_buffer_, size_type max_size_)
577 : base_t(max_size_)
578 , p_buffer(p_buffer_)
579 {
580 }
581
582 private:
583
584 //*************************************************************************
586 //*************************************************************************
587 bool push_implementation(const_reference value)
588 {
589 if (this->current_size != this->Max_Size)
590 {
591 ::new (&p_buffer[this->write_index]) T(value);
592
593 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
594
595 ++this->current_size;
596
597 return true;
598 }
599
600 // Queue is full.
601 return false;
602 }
603
604#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
605 //*************************************************************************
607 //*************************************************************************
608 bool push_implementation(rvalue_reference value)
609 {
610 if (this->current_size != this->Max_Size)
611 {
612 ::new (&p_buffer[this->write_index]) T(etl::move(value));
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#endif
625
626#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
627 //*************************************************************************
629 //*************************************************************************
630 template <typename ... Args>
631 bool emplace_implementation(Args&&... args)
632 {
633 if (this->current_size != this->Max_Size)
634 {
635 ::new (&p_buffer[this->write_index]) T(etl::forward<Args>(args)...);
636
637 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
638
639 ++this->current_size;
640
641 return true;
642 }
643
644 // Queue is full.
645 return false;
646 }
647#else
648 //*************************************************************************
650 //*************************************************************************
651 template <typename T1>
652 bool emplace_implementation(const T1& value1)
653 {
654 if (this->current_size != this->Max_Size)
655 {
656 ::new (&p_buffer[this->write_index]) T(value1);
657
658 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
659
660 ++this->current_size;
661
662 return true;
663 }
664
665 // Queue is full.
666 return false;
667 }
668
669 //*************************************************************************
671 //*************************************************************************
672 template <typename T1, typename T2>
673 bool emplace_implementation(const T1& value1, const T2& value2)
674 {
675 if (this->current_size != this->Max_Size)
676 {
677 ::new (&p_buffer[this->write_index]) T(value1, value2);
678
679 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
680
681 ++this->current_size;
682
683 return true;
684 }
685
686 // Queue is full.
687 return false;
688 }
689
690 //*************************************************************************
692 //*************************************************************************
693 template <typename T1, typename T2, typename T3>
694 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3)
695 {
696 if (this->current_size != this->Max_Size)
697 {
698 ::new (&p_buffer[this->write_index]) T(value1, value2, value3);
699
700 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
701
702 ++this->current_size;
703
704 return true;
705 }
706
707 // Queue is full.
708 return false;
709 }
710
711 //*************************************************************************
713 //*************************************************************************
714 template <typename T1, typename T2, typename T3, typename T4>
715 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
716 {
717 if (this->current_size != this->Max_Size)
718 {
719 ::new (&p_buffer[this->write_index]) T(value1, value2, value3, value4);
720
721 this->write_index = this->get_next_index(this->write_index, this->Max_Size);
722
723 ++this->current_size;
724
725 return true;
726 }
727
728 // Queue is full.
729 return false;
730 }
731#endif
732
733 //*************************************************************************
735 //*************************************************************************
736 bool pop_implementation()
737 {
738 if (this->current_size == 0)
739 {
740 // Queue is empty
741 return false;
742 }
743
744 p_buffer[this->read_index].~T();
745
746 this->read_index = this->get_next_index(this->read_index, this->Max_Size);
747
748 --this->current_size;
749
750 return true;
751 }
752
753 //*************************************************************************
755 //*************************************************************************
756 bool pop_implementation(reference value)
757 {
758 if (this->current_size == 0)
759 {
760 // Queue is empty
761 return false;
762 }
763
764#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
765 value = etl::move(p_buffer[this->read_index]);
766#else
767 value = p_buffer[this->read_index];
768#endif
769
770 p_buffer[this->read_index].~T();
771
772 this->read_index = this->get_next_index(this->read_index, this->Max_Size);
773
774 --this->current_size;
775
776 return true;
777 }
778
779 //*************************************************************************
781 //*************************************************************************
782 reference front_implementation()
783 {
784 return p_buffer[this->read_index];;
785 }
786
787 //*************************************************************************
789 //*************************************************************************
790 const_reference front_implementation() const
791 {
792 return p_buffer[this->read_index];;
793 }
794
795 // Disable copy construction and assignment.
796 iqueue_lockable(const iqueue_lockable&) ETL_DELETE;
797 iqueue_lockable& operator =(const iqueue_lockable&) ETL_DELETE;
798
799#if ETL_USING_CPP11
801 iqueue_lockable& operator =(iqueue_lockable&&) = delete;
802#endif
803
804 T* p_buffer;
805 };
806
807 //***************************************************************************
813 //***************************************************************************
814 template <typename T, size_t VSize, size_t VMemory_Model = etl::memory_model::MEMORY_MODEL_LARGE>
815 class queue_lockable : public etl::iqueue_lockable<T, VMemory_Model>
816 {
817 private:
818
820
821 public:
822
823 typedef typename base_t::size_type size_type;
824
825 ETL_STATIC_ASSERT((VSize <= etl::integral_limits<size_type>::max), "Size too large for memory model");
826
827 static ETL_CONSTANT size_type Max_Size = size_type(VSize);
828 static ETL_CONSTANT size_type Memory_Model = size_type(VMemory_Model);
829
830 //*************************************************************************
832 //*************************************************************************
833
835 : base_t(reinterpret_cast<T*>(buffer.raw), Max_Size)
836 {
837 }
838
839 //*************************************************************************
841 //*************************************************************************
843 {
844 while (this->pop_unlocked())
845 {
846 // Do nothing.
847 }
848 }
849
850 private:
851
852 queue_lockable(const queue_lockable&) ETL_DELETE;
853 queue_lockable& operator = (const queue_lockable&) ETL_DELETE;
854
855#if ETL_USING_CPP11
856 queue_lockable(queue_lockable&&) = delete;
857 queue_lockable& operator =(queue_lockable&&) = delete;
858#endif
859
862 };
863
864 template <typename T, size_t VSize, size_t VMemory_Model>
866
867 template <typename T, size_t VSize, size_t VMemory_Model>
868 ETL_CONSTANT typename queue_lockable<T, VSize, VMemory_Model>::size_type queue_lockable<T, VSize, VMemory_Model>::Memory_Model;
869}
870
871#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:576
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
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:816
~queue_lockable()
Destructor.
Definition queue_lockable.h:842
queue_lockable()
Default constructor.
Definition queue_lockable.h:834
Definition memory.h:2183
Definition integral_limits.h:516
bitset_ext
Definition absolute.h:39
Definition memory_model.h:50