Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | /** | |||
2 | * @file fifo_buffer.h | |||
3 | * @brief A FIFO buffer (base on cyclic_buffer) | |||
4 | * | |||
5 | * https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics) | |||
6 | * | |||
7 | * @date Aug 6, 2020 | |||
8 | * @author andreika <prometheus.pcb@gmail.com> | |||
9 | * @author Andrey Belomutskiy | |||
10 | * | |||
11 | */ | |||
12 | ||||
13 | #pragma once | |||
14 | ||||
15 | #include "cyclic_buffer.h" | |||
16 | ||||
17 | #if EFI_UNIT_TEST | |||
18 | #include "global.h" | |||
19 | #endif // EFI_UNIT_TEST | |||
20 | ||||
21 | // todo: this is not a thread-safe version! | |||
22 | template<typename T, size_t maxSize = CB_MAX_SIZE> | |||
23 | class fifo_buffer : public cyclic_buffer<T, maxSize> { | |||
24 | using cyclic_buffer<T, maxSize>::add; | |||
25 | using cyclic_buffer<T, maxSize>::getSize; | |||
26 | using cyclic_buffer<T, maxSize>::elements; | |||
27 | using cyclic_buffer<T, maxSize>::size, cyclic_buffer<T, maxSize>::count; | |||
28 | ||||
29 | public: | |||
30 | 27 | fifo_buffer() : currentIndexRead(0) { | ||
31 | 27 | } | ||
32 | ||||
33 | virtual bool put(T item); | |||
34 | T get(); | |||
35 | void clear() /*override*/; | |||
36 | ||||
37 | virtual bool put(const T *items, int numItems); | |||
38 | ||||
39 | 96 | bool isEmpty() const { | ||
40 | 96 | return getCount() == 0; | ||
41 | } | |||
42 | ||||
43 | 355 | bool isFull() const { | ||
44 | 355 | return getCount() >= getSize(); | ||
45 | } | |||
46 | ||||
47 | 564 | int getCount() const { | ||
48 | 564 | return cyclic_buffer<T, maxSize>::getCount(); | ||
49 | } | |||
50 | ||||
51 | 378 | int getSize() const { | ||
52 | 378 | return cyclic_buffer<T, maxSize>::getSize(); | ||
53 | } | |||
54 | ||||
55 | 13 | const volatile T* getElements() const { | ||
56 | 13 | return elements; | ||
57 | } | |||
58 | ||||
59 | public: | |||
60 | int currentIndexRead; // FIFO "tail" | |||
61 | }; | |||
62 | ||||
63 | template<typename T, size_t maxSize> | |||
64 | 355 | bool fifo_buffer<T, maxSize>::put(T item) { | ||
65 | // check if full | |||
66 |
2/6fifo_buffer<CanRxMessage, 8ul>::put(CanRxMessage):
✗ Branch 1 not taken.
✗ Branch 2 not taken.
fifo_buffer<unsigned char, 76ul>::put(unsigned char):
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
fifo_buffer<CANTxFrame, 1024ul>::put(CANTxFrame):
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
|
1/4fifo_buffer<unsigned char, 76ul>::put(unsigned char):
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
fifo_buffer<CANTxFrame, 1024ul>::put(CANTxFrame):
✓ Decision 'true' taken 73 times.
✗ Decision 'false' not taken.
|
355 | if (!isFull()) { |
67 | 355 | add(item); | ||
68 | 355 | return true; | ||
69 | } | |||
70 | ✗ | return false; | ||
71 | } | |||
72 | ||||
73 | template<typename T, size_t maxSize> | |||
74 | 23 | bool fifo_buffer<T, maxSize>::put(const T *items, int numItems) { | ||
75 |
2/4fifo_buffer<unsigned char, 76ul>::put(unsigned char const*, int):
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 23 times.
fifo_buffer<CANTxFrame, 1024ul>::put(CANTxFrame const*, int):
✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
2/4fifo_buffer<unsigned char, 76ul>::put(unsigned char const*, int):
✓ Decision 'true' taken 258 times.
✓ Decision 'false' taken 23 times.
fifo_buffer<CANTxFrame, 1024ul>::put(CANTxFrame const*, int):
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
281 | for (int i = 0; i < numItems; i++) { |
76 |
1/4fifo_buffer<unsigned char, 76ul>::put(unsigned char const*, int):
✗ Branch 1 not taken.
✓ Branch 2 taken 258 times.
fifo_buffer<CANTxFrame, 1024ul>::put(CANTxFrame const*, int):
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
1/4fifo_buffer<unsigned char, 76ul>::put(unsigned char const*, int):
✗ Decision 'true' not taken.
✓ Decision 'false' taken 258 times.
fifo_buffer<CANTxFrame, 1024ul>::put(CANTxFrame const*, int):
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
|
258 | if (!put(items[i])) |
77 | ✗ | return false; | ||
78 | } | |||
79 | 23 | return true; | ||
80 | } | |||
81 | ||||
82 | template<typename T, size_t maxSize> | |||
83 | 39 | T fifo_buffer<T, maxSize>::get() { | ||
84 | 39 | T &ret = (T &)elements[currentIndexRead]; | ||
85 |
2/4fifo_buffer<unsigned char, 76ul>::get():
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
fifo_buffer<CANTxFrame, 1024ul>::get():
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
2/4fifo_buffer<unsigned char, 76ul>::get():
✓ Decision 'true' taken 24 times.
✗ Decision 'false' not taken.
fifo_buffer<CANTxFrame, 1024ul>::get():
✓ Decision 'true' taken 15 times.
✗ Decision 'false' not taken.
|
39 | if (!isEmpty()) { |
86 | 39 | currentIndexRead = (currentIndexRead + 1) % size; | ||
87 | 39 | count--; | ||
88 | } | |||
89 | 39 | return ret; | ||
90 | } | |||
91 | ||||
92 | template<typename T, size_t maxSize> | |||
93 | 40 | void fifo_buffer<T, maxSize>::clear() { | ||
94 | 40 | cyclic_buffer<T, maxSize>::clear(); | ||
95 | 40 | currentIndexRead = 0; | ||
96 | 40 | } | ||
97 | ||||
98 | template<typename T, size_t maxSize = CB_MAX_SIZE> | |||
99 | class fifo_buffer_sync : public fifo_buffer<T, maxSize> { | |||
100 | public: | |||
101 | fifo_buffer_sync() { | |||
102 | #if !EFI_UNIT_TEST | |||
103 | osalThreadQueueObjectInit(&q_waiting); | |||
104 | #endif // EFI_UNIT_TEST | |||
105 | } | |||
106 | ||||
107 | ✗ | bool put(T item) override { | ||
108 | chSysLock(); | |||
109 | ✗ | if (fifo_buffer<T, maxSize>::isFull()) { | ||
110 | chSysUnlock(); | |||
111 | ✗ | return false; | ||
112 | } | |||
113 | ✗ | fifo_buffer<T, maxSize>::put(item); | ||
114 | osalThreadDequeueNextI(&q_waiting, MSG_OK); | |||
115 | chSysUnlock(); | |||
116 | ✗ | return true; | ||
117 | } | |||
118 | ||||
119 | bool put(const T *items, int numItems) override { | |||
120 | for (int i = 0; i < numItems; i++) { | |||
121 | if (!put(items[i])) | |||
122 | return false; | |||
123 | } | |||
124 | return true; | |||
125 | } | |||
126 | ||||
127 | bool get(T &item, int timeout) { | |||
128 | chSysLock(); | |||
129 | #if !EFI_UNIT_TEST | |||
130 | while (fifo_buffer<T, maxSize>::isEmpty()) { | |||
131 | msg_t msg = osalThreadEnqueueTimeoutS(&q_waiting, timeout); | |||
132 | if (msg != MSG_OK) { | |||
133 | chSysUnlock(); | |||
134 | return false; | |||
135 | } | |||
136 | } | |||
137 | #endif // EFI_UNIT_TEST | |||
138 | item = fifo_buffer<T, maxSize>::get(); | |||
139 | chSysUnlock(); | |||
140 | return true; | |||
141 | } | |||
142 | ||||
143 | void clear() { | |||
144 | chSysLock(); | |||
145 | fifo_buffer<T, maxSize>::clear(); | |||
146 | #if !EFI_UNIT_TEST | |||
147 | osalThreadDequeueAllI(&q_waiting, MSG_RESET); | |||
148 | #endif // EFI_UNIT_TEST | |||
149 | chSysUnlock(); | |||
150 | } | |||
151 | ||||
152 | protected: | |||
153 | #if !EFI_UNIT_TEST | |||
154 | threads_queue_t q_waiting; | |||
155 | #endif // EFI_UNIT_TEST | |||
156 | }; | |||
157 |