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>
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 //*************************************************************************
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 {
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
192 write_index(0),
193 read_index(0),
194 current_size(0),
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 //*************************************************************************
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
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 while (this->pop_implementation())
696 {
697 // Do nothing.
698 }
699
700 TAccess::unlock();
701 }
702
703 //*************************************************************************
705 //*************************************************************************
706 bool empty() const
707 {
708 TAccess::lock();
709
710 size_type result = (this->current_size == 0);
711
712 TAccess::unlock();
713
714 return result;
715 }
716
717 //*************************************************************************
719 //*************************************************************************
720 bool full() const
721 {
722 TAccess::lock();
723
724 size_type result = (this->current_size == this->MAX_SIZE);
725
726 TAccess::unlock();
727
728 return result;
729 }
730
731 //*************************************************************************
733 //*************************************************************************
735 {
736 TAccess::lock();
737
738 size_type result = this->current_size;
739
740 TAccess::unlock();
741
742 return result;
743 }
744
745 //*************************************************************************
747 //*************************************************************************
749 {
750 TAccess::lock();
751
752 size_type result = this->MAX_SIZE - this->current_size;
753
754 TAccess::unlock();
755
756 return result;
757 }
758
759 protected:
760
761 //*************************************************************************
763 //*************************************************************************
768
769 private:
770
771 // Disable copy construction and assignment.
772 iqueue_spsc_isr(const iqueue_spsc_isr&) ETL_DELETE;
773 iqueue_spsc_isr& operator =(const iqueue_spsc_isr&) ETL_DELETE;
774
775#if ETL_USING_CPP11
778#endif
779
780 TAccess access;
781 };
782
783 //***************************************************************************
791 //***************************************************************************
792 template <typename T, size_t SIZE, typename TAccess, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
793 class queue_spsc_isr : public etl::iqueue_spsc_isr<T, TAccess, MEMORY_MODEL>
794 {
795 private:
796
798
799 public:
800
801 typedef typename base_t::size_type size_type;
802
803 ETL_STATIC_ASSERT((SIZE <= etl::integral_limits<size_type>::max), "Size too large for memory model");
804
805 static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
806
807 //*************************************************************************
809 //*************************************************************************
811 : base_t(reinterpret_cast<T*>(&buffer[0]), MAX_SIZE)
812 {
813 }
814
815 //*************************************************************************
817 //*************************************************************************
819 {
820 base_t::clear();
821 }
822
823 private:
824
827
828#if ETL_USING_CPP11
829 queue_spsc_isr(queue_spsc_isr&&) = delete;
831#endif
832
834 typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type buffer[MAX_SIZE];
835 };
836
837 template <typename T, size_t SIZE, typename TAccess, const size_t MEMORY_MODEL>
838 ETL_CONSTANT typename queue_spsc_isr<T, SIZE, TAccess, MEMORY_MODEL>::size_type queue_spsc_isr<T, SIZE, TAccess, MEMORY_MODEL>::MAX_SIZE;
839}
840
841#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:734
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:748
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:720
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:764
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:706
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
The maximum number of items in the queue.
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
The current size of the queue.
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:794
queue_spsc_isr()
Default constructor.
Definition queue_spsc_isr.h:810
~queue_spsc_isr()
Destructor.
Definition queue_spsc_isr.h:818
Definition alignment.h:231
Definition integral_limits.h:516
add_rvalue_reference
Definition type_traits_generator.h:1322
bitset_ext
Definition absolute.h:38
pair holds two objects of arbitrary type
Definition utility.h:164
Definition memory_model.h:50