Embedded Template Library 1.0
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 //*************************************************************************
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 //*************************************************************************
269 template <typename T1>
270 bool emplace_implementation(const T1& value1)
271 {
272 if (current_size != MAX_SIZE)
273 {
274 ::new (&p_buffer[write_index]) T(value1);
275
277
278 ++current_size;
279
280 return true;
281 }
282
283 // Queue is full.
284 return false;
285 }
286
287 //*************************************************************************
290 //*************************************************************************
291 template <typename T1, typename T2>
292 bool emplace_implementation(const T1& value1, const T2& value2)
293 {
294 if (current_size != MAX_SIZE)
295 {
296 ::new (&p_buffer[write_index]) T(value1, value2);
297
299
300 ++current_size;
301
302 return true;
303 }
304
305 // Queue is full.
306 return false;
307 }
308
309 //*************************************************************************
312 //*************************************************************************
313 template <typename T1, typename T2, typename T3>
314 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3)
315 {
316 if (current_size != MAX_SIZE)
317 {
318 ::new (&p_buffer[write_index]) T(value1, value2, value3);
319
321
322 ++current_size;
323
324 return true;
325 }
326
327 // Queue is full.
328 return false;
329 }
330
331 //*************************************************************************
334 //*************************************************************************
335 template <typename T1, typename T2, typename T3, typename T4>
336 bool emplace_implementation(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
337 {
338 if (current_size != MAX_SIZE)
339 {
340 ::new (&p_buffer[write_index]) T(value1, value2, value3, value4);
341
343
344 ++current_size;
345
346 return true;
347 }
348
349 // Queue is full.
350 return false;
351 }
352
353#endif
354
355 //*************************************************************************
357 //*************************************************************************
359 {
360 if (current_size == 0)
361 {
362 // Queue is empty
363 return false;
364 }
365
366#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_LOCKABLE_FORCE_CPP03_IMPLEMENTATION)
367 value = etl::move(p_buffer[read_index]);
368#else
369 value = p_buffer[read_index];
370#endif
371
372 p_buffer[read_index].~T();
373
375
376 --current_size;
377
378 return true;
379 }
380
381 //*************************************************************************
383 //*************************************************************************
385 {
386 return p_buffer[read_index];
387 }
388
389 //*************************************************************************
391 //*************************************************************************
393 {
394 return p_buffer[read_index];
395 }
396
397 //*************************************************************************
399 //*************************************************************************
401 {
402 if (current_size == 0)
403 {
404 // Queue is empty
405 return false;
406 }
407
408 p_buffer[read_index].~T();
409
411
412 --current_size;
413
414 return true;
415 }
416
417 //*************************************************************************
419 //*************************************************************************
421 {
422 ++index;
423
424 if (index == maximum) ETL_UNLIKELY
425 {
426 index = 0;
427 }
428
429 return index;
430 }
431
437
438 private:
439
440 //*************************************************************************
442 //*************************************************************************
443#if defined(ETL_POLYMORPHIC_SPSC_QUEUE_ISR) || defined(ETL_POLYMORPHIC_CONTAINERS)
444 public:
445 virtual ~queue_spsc_isr_base()
446 {
447 }
448#else
449 protected:
451 {
452 }
453#endif
454 };
455
456 //***************************************************************************
466 //***************************************************************************
467 template <typename T, typename TAccess, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
468 class iqueue_spsc_isr : public queue_spsc_isr_base<T, MEMORY_MODEL>
469 {
470 private:
471
473
474 public:
475
477 typedef typename base_t::reference reference;
479#if ETL_USING_CPP11
480 typedef typename base_t::rvalue_reference rvalue_reference;
481#endif
482 typedef typename base_t::size_type size_type;
483
484 //*************************************************************************
486 //*************************************************************************
488 {
489 TAccess::lock();
490
491 bool result = this->push_implementation(value);
492
493 TAccess::unlock();
494
495 return result;
496 }
497
498#if ETL_USING_CPP11
499 //*************************************************************************
501 //*************************************************************************
502 bool push(rvalue_reference value)
503 {
504 TAccess::lock();
505
506 bool result = this->push_implementation(etl::move(value));
507
508 TAccess::unlock();
509
510 return result;
511 }
512#endif
513
514 //*************************************************************************
517 //*************************************************************************
518#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_QUEUE_ISR_FORCE_CPP03_IMPLEMENTATION)
519 template <typename ... Args>
520 bool emplace(Args&&... args)
521 {
522 TAccess::lock();
523
524 bool result = this->emplace_implementation(etl::forward<Args>(args)...);
525
526 TAccess::unlock();
527
528 return result;
529 }
530#else
531 //*************************************************************************
534 //*************************************************************************
535 template <typename T1>
536 bool emplace(const T1& value1)
537 {
538 TAccess::lock();
539
540 bool result = this->emplace_implementation(value1);
541
542 TAccess::unlock();
543
544 return result;
545 }
546
547 //*************************************************************************
550 //*************************************************************************
551 template <typename T1, typename T2>
552 bool emplace(const T1& value1, const T2& value2)
553 {
554 TAccess::lock();
555
556 bool result = this->emplace_implementation(value1, value2);
557
558 TAccess::unlock();
559
560 return result;
561 }
562
563 //*************************************************************************
566 //*************************************************************************
567 template <typename T1, typename T2, typename T3>
568 bool emplace(const T1& value1, const T2& value2, const T3& value3)
569 {
570 TAccess::lock();
571
572 bool result = this->emplace_implementation(value1, value2, value3);
573
574 TAccess::unlock();
575
576 return result;
577 }
578
579 //*************************************************************************
582 //*************************************************************************
583 template <typename T1, typename T2, typename T3, typename T4>
584 bool emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
585 {
586 TAccess::lock();
587
588 bool result = this->emplace_implementation(value1, value2, value3, value4);
589
590 TAccess::unlock();
591
592 return result;
593 }
594#endif
595
596 //*************************************************************************
598 //*************************************************************************
599 bool pop(reference value)
600 {
601 TAccess::lock();
602
603 bool result = this->pop_implementation(value);
604
605 TAccess::unlock();
606
607 return result;
608 }
609
610 //*************************************************************************
612 //*************************************************************************
613 bool pop()
614 {
615 TAccess::lock();
616
617 bool result = this->pop_implementation();
618
619 TAccess::unlock();
620
621 return result;
622 }
623
624 //*************************************************************************
626 //*************************************************************************
628 {
629 TAccess::lock();
630
631 reference result = this->front_implementation();
632
633 TAccess::unlock();
634
635 return result;
636 }
637
638 //*************************************************************************
640 //*************************************************************************
642 {
643 TAccess::lock();
644
645 const_reference result = this->front_implementation();
646
647 TAccess::unlock();
648
649 return result;
650 }
651
652 //*************************************************************************
654 //*************************************************************************
655 void clear()
656 {
657 TAccess::lock();
658
659 while (this->pop_implementation())
660 {
661 // Do nothing.
662 }
663
664 TAccess::unlock();
665 }
666
667 //*************************************************************************
669 //*************************************************************************
670 bool empty() const
671 {
672 TAccess::lock();
673
674 size_type result = (this->current_size == 0);
675
676 TAccess::unlock();
677
678 return result;
679 }
680
681 //*************************************************************************
683 //*************************************************************************
684 bool full() const
685 {
686 TAccess::lock();
687
688 size_type result = (this->current_size == this->MAX_SIZE);
689
690 TAccess::unlock();
691
692 return result;
693 }
694
695 //*************************************************************************
697 //*************************************************************************
699 {
700 TAccess::lock();
701
702 size_type result = this->current_size;
703
704 TAccess::unlock();
705
706 return result;
707 }
708
709 //*************************************************************************
711 //*************************************************************************
713 {
714 TAccess::lock();
715
716 size_type result = this->MAX_SIZE - this->current_size;
717
718 TAccess::unlock();
719
720 return result;
721 }
722
723 protected:
724
725 //*************************************************************************
727 //*************************************************************************
728 iqueue_spsc_isr(T* p_buffer_, size_type max_size_)
729 : base_t(p_buffer_, max_size_)
730 {
731 }
732
733 private:
734
735 // Disable copy construction and assignment.
736 iqueue_spsc_isr(const iqueue_spsc_isr&) ETL_DELETE;
737 iqueue_spsc_isr& operator =(const iqueue_spsc_isr&) ETL_DELETE;
738
739#if ETL_USING_CPP11
741 iqueue_spsc_isr& operator =(iqueue_spsc_isr&&) = delete;
742#endif
743
744 TAccess access;
745 };
746
747 //***************************************************************************
755 //***************************************************************************
756 template <typename T, size_t SIZE, typename TAccess, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
757 class queue_spsc_isr : public etl::iqueue_spsc_isr<T, TAccess, MEMORY_MODEL>
758 {
759 private:
760
762
763 public:
764
765 typedef typename base_t::size_type size_type;
766
767 ETL_STATIC_ASSERT((SIZE <= etl::integral_limits<size_type>::max), "Size too large for memory model");
768
769 static ETL_CONSTANT size_type MAX_SIZE = size_type(SIZE);
770
771 //*************************************************************************
773 //*************************************************************************
775 : base_t(reinterpret_cast<T*>(&buffer[0]), MAX_SIZE)
776 {
777 }
778
779 //*************************************************************************
781 //*************************************************************************
783 {
785 }
786
787 private:
788
790 queue_spsc_isr& operator = (const queue_spsc_isr&);
791
792#if ETL_USING_CPP11
793 queue_spsc_isr(queue_spsc_isr&&) = delete;
794 queue_spsc_isr& operator =(queue_spsc_isr&&) = delete;
795#endif
796
798 typename etl::aligned_storage<sizeof(T), etl::alignment_of<T>::value>::type buffer[MAX_SIZE];
799 };
800
801 template <typename T, size_t SIZE, typename TAccess, const size_t MEMORY_MODEL>
802 ETL_CONSTANT typename queue_spsc_isr<T, SIZE, TAccess, MEMORY_MODEL>::size_type queue_spsc_isr<T, SIZE, TAccess, MEMORY_MODEL>::MAX_SIZE;
803}
804
805#endif
This is the base for all queue_spsc_isrs that contain a particular type.
Definition: queue_spsc_isr.h:469
bool emplace(const T1 &value1, const T2 &value2)
Definition: queue_spsc_isr.h:552
base_t::size_type size_type
The type used for determining the size of the queue.
Definition: queue_spsc_isr.h:482
size_type size() const
How many items in the queue?
Definition: queue_spsc_isr.h:698
const_reference front() const
Peek a value at the front of the queue.
Definition: queue_spsc_isr.h:641
base_t::const_reference const_reference
A const reference to the type used in the queue.
Definition: queue_spsc_isr.h:478
bool pop()
Pop a value from the queue and discard.
Definition: queue_spsc_isr.h:613
size_type available() const
How much free space available in the queue.
Definition: queue_spsc_isr.h:712
reference front()
Peek a value at the front of the queue.
Definition: queue_spsc_isr.h:627
bool full() const
Is the queue full?
Definition: queue_spsc_isr.h:684
void clear()
Clear the queue.
Definition: queue_spsc_isr.h:655
bool push(const_reference value)
Push a value to the queue.
Definition: queue_spsc_isr.h:487
bool emplace(const T1 &value1, const T2 &value2, const T3 &value3)
Definition: queue_spsc_isr.h:568
base_t::value_type value_type
The type stored in the queue.
Definition: queue_spsc_isr.h:476
iqueue_spsc_isr(T *p_buffer_, size_type max_size_)
The constructor that is called from derived classes.
Definition: queue_spsc_isr.h:728
bool pop(reference value)
Pop a value from the queue.
Definition: queue_spsc_isr.h:599
bool emplace(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition: queue_spsc_isr.h:584
base_t::reference reference
A reference to the type used in the queue.
Definition: queue_spsc_isr.h:477
bool emplace(const T1 &value1)
Definition: queue_spsc_isr.h:536
bool empty() const
Is the queue empty?
Definition: queue_spsc_isr.h:670
Definition: queue_spsc_isr.h:49
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:358
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:292
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:314
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:270
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:420
size_type available_from_isr() const
Definition: queue_spsc_isr.h:129
~queue_spsc_isr_base()
Destructor.
Definition: queue_spsc_isr.h:450
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:434
const_reference front_implementation() const
Peek a value at the front of the queue.
Definition: queue_spsc_isr.h:392
bool emplace_implementation(const T1 &value1, const T2 &value2, const T3 &value3, const T4 &value4)
Definition: queue_spsc_isr.h:336
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:400
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:433
const size_type MAX_SIZE
The maximum number of items in the queue.
Definition: queue_spsc_isr.h:436
bool empty_from_isr() const
Definition: queue_spsc_isr.h:149
T * p_buffer
The internal buffer.
Definition: queue_spsc_isr.h:432
size_type current_size
The current size of the queue.
Definition: queue_spsc_isr.h:435
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:384
Definition: queue_spsc_isr.h:758
queue_spsc_isr()
Default constructor.
Definition: queue_spsc_isr.h:774
~queue_spsc_isr()
Destructor.
Definition: queue_spsc_isr.h:782
Definition: alignment.h:221
Definition: integral_limits.h:468
add_rvalue_reference
Definition: type_traits_generator.h:1327
bitset_ext
Definition: absolute.h:38
Definition: memory_model.h:50