diff --git a/firmware/util/containers/cyclic_buffer.h b/firmware/util/containers/cyclic_buffer.h index 3fabdfb999..1552a70efb 100644 --- a/firmware/util/containers/cyclic_buffer.h +++ b/firmware/util/containers/cyclic_buffer.h @@ -62,7 +62,7 @@ void cyclic_buffer::add(T value) { // become invalid. And yes I did see a crash due to an overrun here. uint16_t idx = currentIndex; - elements[idx] = value; + ((T &)elements[idx]) = value; if (++idx == size) { idx = 0; diff --git a/firmware/util/containers/fifo_buffer.h b/firmware/util/containers/fifo_buffer.h index b51ac7ed77..f411873578 100644 --- a/firmware/util/containers/fifo_buffer.h +++ b/firmware/util/containers/fifo_buffer.h @@ -18,15 +18,20 @@ // todo: this is not a thread-safe version! template class fifo_buffer : public cyclic_buffer { + using cyclic_buffer::add; + using cyclic_buffer::getSize; + using cyclic_buffer::elements; + using cyclic_buffer::size, cyclic_buffer::count; + public: fifo_buffer() : currentIndexRead(0) { } - void put(T item); + virtual bool put(T item); T get(); void clear() /*override*/; - void put(const T *items, int numItems); + virtual bool put(const T *items, int numItems); bool isEmpty() const { return getCount() == 0; @@ -36,28 +41,40 @@ public: return getCount() >= getSize(); } + int getCount() const { + return cyclic_buffer::getCount(); + } + + const volatile T* getElements() const { + return elements; + } + public: volatile int currentIndexRead; // FIFO "tail" }; template -void fifo_buffer::put(T item) { +bool fifo_buffer::put(T item) { // check if full if (!isFull()) { - cyclic_buffer::add(item); + add(item); + return true; } + return false; } template -void fifo_buffer::put(const T *items, int numItems) { +bool fifo_buffer::put(const T *items, int numItems) { for (int i = 0; i < numItems; i++) { - put(items[i]); + if (!put(items[i])) + return false; } + return true; } template T fifo_buffer::get() { - auto ret = elements[currentIndexRead]; + T &ret = (T &)elements[currentIndexRead]; if (!isEmpty()) { currentIndexRead = (currentIndexRead + 1) % size; count--; @@ -67,9 +84,60 @@ T fifo_buffer::get() { template void fifo_buffer::clear() { - cyclic_buffer::clear(); + cyclic_buffer::clear(); currentIndexRead = 0; } +template +class fifo_buffer_sync : public fifo_buffer { +public: + fifo_buffer_sync() { + osalThreadQueueObjectInit(&q_waiting); + } + + bool put(T item) override { + chSysLock(); + if (fifo_buffer::isFull()) { + chSysUnlock(); + return false; + } + fifo_buffer::put(item); + osalThreadDequeueNextI(&q_waiting, MSG_OK); + chSysUnlock(); + return true; + } + + bool put(const T *items, int numItems) override { + for (int i = 0; i < numItems; i++) { + if (!put(items[i])) + return false; + } + return true; + } + + bool get(T &item, int timeout) { + chSysLock(); + while (fifo_buffer::isEmpty()) { + msg_t msg = osalThreadEnqueueTimeoutS(&q_waiting, timeout); + if (msg != MSG_OK) { + chSysUnlock(); + return false; + } + } + item = fifo_buffer::get(); + chSysUnlock(); + return true; + } + + void clear() { + chSysLock(); + fifo_buffer::clear(); + osalThreadDequeueAllI(&q_waiting, MSG_RESET); + chSysUnlock(); + } + +protected: + threads_queue_t q_waiting; +}; #endif /* FIFO_BUFFER_H */ \ No newline at end of file