| 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.
|
2/6fifo_buffer<CanRxMessage, 8ul>::put(CanRxMessage):
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
fifo_buffer<unsigned char, 76ul>::put(unsigned char):
✓ Decision 'true' taken 282 times.
✗ 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/6fifo_buffer<CanRxMessage, 8ul>::get():
✗ Branch 1 not taken.
✗ Branch 2 not taken.
fifo_buffer<CANTxFrame, 1024ul>::get():
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
fifo_buffer<unsigned char, 76ul>::get():
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
2/6fifo_buffer<CanRxMessage, 8ul>::get():
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
fifo_buffer<CANTxFrame, 1024ul>::get():
✓ Decision 'true' taken 15 times.
✗ Decision 'false' not taken.
fifo_buffer<unsigned char, 76ul>::get():
✓ Decision 'true' taken 24 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 |