GCC Code Coverage Report


Directory: ./
File: firmware/libfirmware/util/include/rusefi/containers/fifo_buffer.h
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 69.2% 54 0 78
Functions: 75.0% 18 0 24
Branches: 33.3% 7 0 21
Decisions: 33.3% 6 - 18

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/6
fifo_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/4
fifo_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/4
fifo_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/4
fifo_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/4
fifo_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/4
fifo_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/4
fifo_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/4
fifo_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