Embedded Template Library 1.0
Loading...
Searching...
No Matches
queue_spsc_isr.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) 2018 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_SPSC_QUEUE_ISR_INCLUDED
32#define ETL_SPSC_QUEUE_ISR_INCLUDED
33
34#include "platform.h"
35#include "alignment.h"
36#include "parameter_type.h"
37#include "memory_model.h"
38#include "integral_limits.h"
39#include "utility.h"
40#include "placement_new.h"
41
42#include <stddef.h>
43#include <stdint.h>
44
45namespace etl
46{
47 template <typename T, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
48 class queue_spsc_isr_base
49 {
50 public:
51
54
55 typedef T value_type;
56 typedef T& reference;
57 typedef const T& const_reference;
58#if ETL_USING_CPP11
59 typedef T&& rvalue_reference;
60#endif
61
62 //*************************************************************************
64 //*************************************************************************
66 {
67 return push_implementation(value);
68 }
69
70#if ETL_USING_CPP11
71 //*************************************************************************
73 //*************************************************************************
74 bool push_from_isr(rvalue_reference value)
75 {
76 return push_implementation(etl::move(value));
77 }
78#endif
79
80 //*************************************************************************
84 //*************************************************************************
85#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_ISR_FORCE_CPP03_IMPLEMENTATION)
86 template <typename ... Args>
87 bool emplace_from_isr(Args&&... args)
88 {
89 return emplace_implementation(etl::forward<Args>(args)...);
90 }
91#endif
92
93 //*************************************************************************
95 //*************************************************************************
97 {
98 return pop_implementation(value);
99 }
100
101 //*************************************************************************
103 //*************************************************************************
105 {
106 return pop_implementation();
107 }
108
109 //*************************************************************************
111 //*************************************************************************
113 {
114 return front_implementation();
115 }
116
117 //*************************************************************************
119 //*************************************************************************
121 {
122 return front_implementation();
123 }
124
125 //*************************************************************************
128 //*************************************************************************
130 {
131 return MAX_SIZE - current_size;
132 }
133
134 //*************************************************************************
136 //*************************************************************************
138 {
139 while (pop_implementation())
140 {
141 // Do nothing.
142 }
143 }
144
145 //*************************************************************************
148 //*************************************************************************
149 bool empty_from_isr() const
150 {
151 return (current_size == 0);
152 }
153
154 //*************************************************************************
157 //*************************************************************************
158 bool full_from_isr() const
159 {
160 return (current_size == MAX_SIZE);
161 }
162
163 //*************************************************************************
166 //*************************************************************************
168 {
169 return current_size;
170 }
171
172 //*************************************************************************
174 //*************************************************************************
176 {
177 return MAX_SIZE;
178 }
179
180 //*************************************************************************
182 //*************************************************************************
184 {
185 return MAX_SIZE;
186 }
187
188 protected:
189
190 queue_spsc_isr_base(T* p_buffer_, size_type max_size_)
191 : p_buffer(p_buffer_),
192 write_index(0),
193 read_index(0),
194 current_size(0),
195 MAX_SIZE(max_size_)
196 {
197 }
198
199 //*************************************************************************
201 //*************************************************************************
203 {
204 if (current_size != MAX_SIZE)
205 {
206 ::new (&p_buffer[write_index]) T(value);
207
209
210 ++current_size;
211
212 return true;
213 }
214
215 // Queue is full.
216 return false;
217 }
218
219#if ETL_USING_CPP11
220 //*************************************************************************
222 //*************************************************************************
223 bool push_implementation(rvalue_reference value)
224 {
225 if (current_size != MAX_SIZE)
226 {
227 ::new (&p_buffer[write_index]) T(etl::move(value));
228
230
231 ++current_size;
232
233 return true;
234 }
235
236 // Queue is full.
237 return false;
238 }
239#endif
240
241#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_ISR_FORCE_CPP03_IMPLEMENTATION)
242 //*************************************************************************
246 //*************************************************************************
247 template <typename ... Args>
248 bool emplace_implementation(Args&&... args)
249 {
250 if (current_size != MAX_SIZE)
251 {
252 ::new (&p_buffer[write_index]) T(etl::forward<Args>(args)...);
253
255
256 ++current_size;
257
258 return true;
259 }
260
261 // Queue is full.
262 return false;
263 }
264#else
265 //*************************************************************************
268 //*************************************************************************
270 {
271 if (current_size != MAX_SIZE)
272 {
273 ::new (&p_buffer[write_index]) T();
274
276
277 ++current_size;
278
279 return true;
280 }
281
282 // Queue is full.
283 return false;
284 }
285
286 //*************************************************************************
289 //*************************************************************************
290 template <typename T1>
291 bool emplace_implementation(const T1& value1)
292 {
293 if (current_size != MAX_SIZE)
294 {
295 ::new (&p_buffer[write_index]) T(value1);
296
298
299 ++current_size;
300
301 return true;
302 }
303
304 // Queue is full.
305 return false;
306 }
307
308 //*************************************************************************
311 //*************************************************************************
312 template <typename T1, typename T2>
313 bool emplace_implementation(const T1& value1, const T2& value2)
314 {
315 if (current_size != MAX_SIZE)
316 {
317 ::new (&p_buffer[write_index]) T(value1, value2);
318
320
321 ++current_size;
322
323 return true;
324 }
325
326 // Queue is full.
327 return false;
328 }
329
330 //*************************************************************************
333 //*************************************************************************
334 template <typename T1, typename T2, typename T3>
335 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3)
336 {
337 if (current_size != MAX_SIZE)
338 {
339 ::new (&p_buffer[write_index]) T(value1, value2, value3);
340
342
343 ++current_size;
344
345 return true;
346 }
347
348 // Queue is full.
349 return false;
350 }
351
352 //*************************************************************************
355 //*************************************************************************
356 template <typename T1, typename T2, typename T3, typename T4>
357 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
358 {
359 if (current_size != MAX_SIZE)
360 {
361 ::new (&p_buffer[write_index]) T(value1, value2, value3, value4);
362
364
365 ++current_size;
366
367 return true;
368 }
369
370 // Queue is full.
371 return false;
372 }
373
374#endif
375
376 //*************************************************************************
378 //*************************************************************************
380 {
381 if (current_size == 0)
382 {
383 // Queue is empty
384 return false;
385 }
386
387#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
388 value = etl::move(p_buffer[read_index]);
389#else
390 value = p_buffer[read_index];
391#endif
392
393 p_buffer[read_index].~T();
394
396
397 --current_size;
398
399 return true;
400 }
401
402 //*************************************************************************
404 //*************************************************************************
409
410 //*************************************************************************
412 //*************************************************************************
414 {
415 return p_buffer[read_index];
416 }
417
418 //*************************************************************************
420 //*************************************************************************
422 {
423 if (current_size == 0)
424 {
425 // Queue is empty
426 return false;
427 }
428
429 p_buffer[read_index].~T();
430
432
433 --current_size;
434
435 return true;
436 }
437
438 //*************************************************************************
440 //*************************************************************************
442 {
443 ++index;
444
445 if (index == maximum) ETL_UNLIKELY
446 {
447 index = 0;
448 }
449
450 return index;
451 }
452
458
459 private:
460
461 //*************************************************************************
463 //*************************************************************************
464#if defined(ETL_POLYMORPHIC_SPSC_QUEUE_ISR) || defined(ETL_POLYMORPHIC_CONTAINERS)
465 public:
466 virtual ~queue_spsc_isr_base()
467 {
468 }
469#else
470 protected:
472 {
473 }
474#endif
475 };
476
477 //***************************************************************************
487 //***************************************************************************
488 template <typename T, typename TAccess, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
489 class iqueue_spsc_isr : public queue_spsc_isr_base<T, MEMORY_MODEL>
490 {
491 private:
492
493 typedef queue_spsc_isr_base<T, MEMORY_MODEL> base_t;
494
495 public:
496
498 typedef typename base_t::reference reference;
500#if ETL_USING_CPP11
501 typedef typename base_t::rvalue_reference rvalue_reference;
502#endif
503 typedef typename base_t::size_type size_type;
504
505 //*************************************************************************
507 //*************************************************************************
509 {
510 TAccess::lock();
511
512 bool result = this->push_implementation(value);
513
514 TAccess::unlock();
515
516 return result;
517 }
518
519#if ETL_USING_CPP11
520 //*************************************************************************
522 //*************************************************************************
523 bool push(rvalue_reference value)
524 {
525 TAccess::lock();
526
527 bool result = this->push_implementation(etl::move(value));
528
529 TAccess::unlock();
530
531 return result;
532 }
533#endif
534
535 //*************************************************************************
538 //*************************************************************************
539#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_ISR_FORCE_CPP03_IMPLEMENTATION)
540 template <typename ... Args>
541 bool emplace(Args&&... args)
542 {
543 TAccess::lock();
544
545 bool result = this->emplace_implementation(etl::forward<Args>(args)...);
546
547 TAccess::unlock();
548
549 return result;
550 }
551#else
552 //*************************************************************************
555 //*************************************************************************
556 bool emplace()
557 {
558 TAccess::lock();
559
560 bool result = this->emplace_implementation();
561
562 TAccess::unlock();
563
564 return result;
565 }
566
567 //*************************************************************************
570 //*************************************************************************
571 template <typename T1>
572 bool emplace(const T1& value1)
573 {
574 TAccess::lock();
575
576 bool result = this->emplace_implementation(value1);
577
578 TAccess::unlock();
579
580 return result;
581 }
582
583 //*************************************************************************
586 //*************************************************************************
587 template <typename T1, typename T2>
588 bool emplace(const T1& value1, const T2& value2)
589 {
590 TAccess::lock();
591
592 bool result = this->emplace_implementation(value1, value2);
593
594 TAccess::unlock();
595
596 return result;
597 }
598
599 //*************************************************************************
602 //*************************************************************************
603 template <typename T1, typename T2, typename T3>
604 bool emplace(const T1& value1, const T2& value2, const T3& value3)
605 {
606 TAccess::lock();
607
608 bool result = this->emplace_implementation(value1, value2, value3);
609
610 TAccess::unlock();
611
612 return result;
613 }
614
615 //*************************************************************************
618 //*************************************************************************
619 template <typename T1, typename T2, typename T3, typename T4>
620 bool emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
621 {
622 TAccess::lock();
623
624 bool result = this->emplace_implementation(value1, value2, value3, value4);
625
626 TAccess::unlock();
627
628 return result;
629 }
630#endif
631
632 //*************************************************************************
634 //*************************************************************************
635 bool pop(reference value)
636 {
637 TAccess::lock();
638
639 bool result = this->pop_implementation(value);
640
641 TAccess::unlock();
642
643 return result;
644 }
645
646 //*************************************************************************
648 //*************************************************************************
649 bool pop()
650 {
651 TAccess::lock();
652
653 bool result = this->pop_implementation();
654
655 TAccess::unlock();
656
657 return result;
658 }
659
660 //*************************************************************************
662 //*************************************************************************
664 {
665 TAccess::lock();
666
667 reference result = this->front_implementation();
668
669 TAccess::unlock();
670
671 return result;
672 }
673
674 //*************************************************************************
676 //*************************************************************************
678 {
679 TAccess::lock();
680
681 const_reference result = this->front_implementation();
682
683 TAccess::unlock();
684
685 return result;
686 }
687
688 //*************************************************************************
690 //*************************************************************************
691 void clear()
692 {
693 TAccess::lock();
694
695 if ETL_IF_CONSTEXPR(etl::is_trivially_destructible<T>::value)
696 {
697 this->write_index = 0;
698 this->read_index = 0;
699 this->current_size = 0;
700 }
701 else
702 {
703 while (pop())
704 {
705 // Do nothing.
706 }
707 }
708
709 TAccess::unlock();
710 }
711
712 //*************************************************************************
714 //*************************************************************************
715 bool empty() const
716 {
717 TAccess::lock();
718
719 size_type result = (this->current_size == 0);
720
721 TAccess::unlock();
722
723 return result;
724 }
725
726 //*************************************************************************
728 //*************************************************************************
729 bool full() const
730 {
731 TAccess::lock();
732
733 size_type result = (this->current_size == this->MAX_SIZE);
734
735 TAccess::unlock();
736
737 return result;
738 }
739
740 //*************************************************************************
742 //*************************************************************************
744 {
745 TAccess::lock();
746
747 size_type result = this->current_size;
748
749 TAccess::unlock();
750
751 return result;
752 }
753
754 //*************************************************************************
756 //*************************************************************************
758 {
759 TAccess::lock();
760
761 size_type result = this->MAX_SIZE - this->current_size;
762
763 TAccess::unlock();
764
765 return result;
766 }
767
768 protected:
769
770 //*************************************************************************
772 //*************************************************************************
773 iqueue_spsc_isr(T* p_buffer_, size_type max_size_)
774 : base_t(p_buffer_, max_size_)
775 {
776 }
777
778 private:
779
780 // Disable copy construction and assignment.
781 iqueue_spsc_isr(const iqueue_spsc_isr&) ETL_DELETE;
782 iqueue_spsc_isr& operator =(const iqueue_spsc_isr&) ETL_DELETE;
783
784#if ETL_USING_CPP11
786 iqueue_spsc_isr& operator =(iqueue_spsc_isr&&) = delete;
787#endif
788
789 TAccess access;
790 };
791
792 //***************************************************************************
800 //***************************************************************************
801 template <typename T, size_t SIZE, typename TAccess, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
802 class queue_spsc_isr : public etl::iqueue_spsc_isr<T, TAccess, MEMORY_MODEL>
803 {
804 private:
805
807
808 public:
809
810 typedef typename base_t::size_type size_type;
811
812 ETL_STATIC_ASSERT((SIZE <= etl::integral_limits<size_type>::max), "Size too large for memory model");
813
814 static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
815
816 //*************************************************************************
818 //*************************************************************************
820 : base_t(reinterpret_cast<T*>(&buffer[0]), MAX_SIZE)
821 {
822 }
823
824 //*************************************************************************
826 //*************************************************************************
828 {
830 }
831
832 private:
833
834 queue_spsc_isr(const queue_spsc_isr&) ETL_DELETE;
835 queue_spsc_isr& operator = (const queue_spsc_isr&) ETL_DELETE;
836
837#if ETL_USING_CPP11
838 queue_spsc_isr(queue_spsc_isr&&) = delete;
839 queue_spsc_isr& operator =(queue_spsc_isr&&) = delete;
840#endif
841
843 typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type buffer[MAX_SIZE];
844 };
845
846 template <typename T, size_t SIZE, typename TAccess, const size_t MEMORY_MODEL>
848}
849
850#endif
This is the base for all queue_spsc_isrs that contain a particular type.
Definition queue_spsc_isr.h:490
bool emplace(const T1 &value1, const T2 &value2)
Definition queue_spsc_isr.h:588
base_t::size_type size_type
The type used for determining the size of the queue.
Definition queue_spsc_isr.h:503
size_type size() const
How many items in the queue?
Definition queue_spsc_isr.h:743
const_reference front() const
Peek a value at the front of the queue.
Definition queue_spsc_isr.h:677
base_t::const_reference const_reference
A const reference to the type used in the queue.
Definition queue_spsc_isr.h:499
bool pop()
Pop a value from the queue and discard.
Definition queue_spsc_isr.h:649
size_type available() const
How much free space available in the queue.
Definition queue_spsc_isr.h:757
reference front()
Peek a value at the front of the queue.
Definition queue_spsc_isr.h:663
bool full() const
Is the queue full?
Definition queue_spsc_isr.h:729
void clear()
Clear the queue.
Definition queue_spsc_isr.h:691
bool push(const_reference value)
Push a value to the queue.
Definition queue_spsc_isr.h:508
bool emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition queue_spsc_isr.h:604
base_t::value_type value_type
The type stored in the queue.
Definition queue_spsc_isr.h:497
iqueue_spsc_isr(T *p_buffer_, size_type max_size_)
The constructor that is called from derived classes.
Definition queue_spsc_isr.h:773
bool pop(reference value)
Pop a value from the queue.
Definition queue_spsc_isr.h:635
bool emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition queue_spsc_isr.h:620
base_t::reference reference
A reference to the type used in the queue.
Definition queue_spsc_isr.h:498
bool emplace(const T1 &value1)
Definition queue_spsc_isr.h:572
bool empty() const
Is the queue empty?
Definition queue_spsc_isr.h:715
bool emplace()
Definition queue_spsc_isr.h:556
Definition queue_spsc_isr.h:49
bool emplace_implementation()
Definition queue_spsc_isr.h:269
bool full_from_isr() const
Definition queue_spsc_isr.h:158
bool pop_implementation(reference value)
Pop a value from the queue.
Definition queue_spsc_isr.h:379
bool push_from_isr(const_reference value)
Push a value to the queue from an ISR.
Definition queue_spsc_isr.h:65
const_reference front_from_isr() const
Peek a value at the front of the queue from an ISR.
Definition queue_spsc_isr.h:120
reference front_from_isr()
Peek a value at the front of the queue from an ISR.
Definition queue_spsc_isr.h:112
bool emplace_implementation(const T1 &value1, const T2 &value2)
Definition queue_spsc_isr.h:313
T value_type
The type stored in the queue.
Definition queue_spsc_isr.h:55
bool emplace_implementation(const T1 &value1, const T2 &value2, const T3 &value3)
Definition queue_spsc_isr.h:335
size_type capacity() const
How many items can the queue hold.
Definition queue_spsc_isr.h:175
bool emplace_implementation(const T1 &value1)
Definition queue_spsc_isr.h:291
void clear_from_isr()
Clear the queue from the ISR.
Definition queue_spsc_isr.h:137
static size_type get_next_index(size_type index, size_type maximum)
Calculate the next index.
Definition queue_spsc_isr.h:441
size_type available_from_isr() const
Definition queue_spsc_isr.h:129
~queue_spsc_isr_base()
Destructor.
Definition queue_spsc_isr.h:471
etl::size_type_lookup< MEMORY_MODEL >::type size_type
The type used for determining the size of queue.
Definition queue_spsc_isr.h:53
size_type read_index
Where to get the oldest data.
Definition queue_spsc_isr.h:455
const_reference front_implementation() const
Peek a value at the front of the queue.
Definition queue_spsc_isr.h:413
bool emplace_implementation(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition queue_spsc_isr.h:357
size_type max_size() const
How many items can the queue hold.
Definition queue_spsc_isr.h:183
bool pop_from_isr()
Pop a value from the queue from an ISR, and discard.
Definition queue_spsc_isr.h:104
bool pop_implementation()
Pop a value from the queue and discard.
Definition queue_spsc_isr.h:421
bool pop_from_isr(reference value)
Pop a value from the queue from an ISR.
Definition queue_spsc_isr.h:96
size_type write_index
Where to input new data.
Definition queue_spsc_isr.h:454
const size_type MAX_SIZE
Definition queue_spsc_isr.h:457
bool empty_from_isr() const
Definition queue_spsc_isr.h:149
T * p_buffer
The internal buffer.
Definition queue_spsc_isr.h:453
size_type current_size
Definition queue_spsc_isr.h:456
T & reference
A reference to the type used in the queue.
Definition queue_spsc_isr.h:56
const T & const_reference
A const reference to the type used in the queue.
Definition queue_spsc_isr.h:57
size_type size_from_isr() const
Definition queue_spsc_isr.h:167
bool push_implementation(const_reference value)
Push a value to the queue.
Definition queue_spsc_isr.h:202
reference front_implementation()
Peek a value at the front of the queue.
Definition queue_spsc_isr.h:405
Definition queue_spsc_isr.h:803
queue_spsc_isr()
Default constructor.
Definition queue_spsc_isr.h:819
~queue_spsc_isr()
Destructor.
Definition queue_spsc_isr.h:827
Definition alignment.h:246
Definition integral_limits.h:516
add_rvalue_reference
Definition type_traits_generator.h:1413
bitset_ext
Definition absolute.h:39
Definition memory_model.h:50