diff --git a/src/shared/utils/collections/CircularBuffer.h b/src/shared/utils/collections/CircularBuffer.h index ea8e77bf51d155650f094e34edcde78deb484b15..8dfb8385efc639a3b12a097aad9f895dc32ed414 100644 --- a/src/shared/utils/collections/CircularBuffer.h +++ b/src/shared/utils/collections/CircularBuffer.h @@ -1,5 +1,5 @@ /* Copyright (c) 2015-2018 Skyward Experimental Rocketry - * Author: Luca Erbetta + * Author: Luca Erbetta, Davide Mor * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -50,7 +50,7 @@ public: * @param elem Element to be added to the queue. * @return The element added. */ - virtual T& put(const T& elem) + T& put(const T& elem) { buffer[writePtr] = elem; T& added = buffer[writePtr]; @@ -78,7 +78,7 @@ public: * @param i Index of the element to get, starting from the oldest. * @return The element. */ - virtual T& get(unsigned int i = 0) + T& get(unsigned int i = 0) { // Here we need to explicitly specify the name of this class because we // DO NOT want to call the version of count() overridden by a derived @@ -102,7 +102,7 @@ public: * @throw range_error if buffer is empty. * @return The element. */ - virtual T& last() { return get(count() - 1); } + T& last() { return get(count() - 1); } /** * @brief Pops the first element in the buffer. @@ -111,7 +111,7 @@ public: * @throw range_error if buffer is empty. * @return The element that has been popped. */ - virtual const T& pop() + const T& pop() { if (!empty) { @@ -131,7 +131,7 @@ public: * * @return Number of elements in the buffer. */ - virtual size_t count() const + size_t count() const { if (empty) return 0; @@ -145,9 +145,9 @@ public: } } - virtual bool isEmpty() const { return empty; } + bool isEmpty() const { return empty; } - virtual bool isFull() const + bool isFull() const { // Same as in get(): explicitly specify the name of the class to avoid // deadlocks! diff --git a/src/shared/utils/collections/IRQCircularBuffer.h b/src/shared/utils/collections/IRQCircularBuffer.h index e27d15e2a37652df6e822d29fd8d3ff0cd3af104..276182957972a3a73b1afa070f82a0cfba1bea64 100644 --- a/src/shared/utils/collections/IRQCircularBuffer.h +++ b/src/shared/utils/collections/IRQCircularBuffer.h @@ -1,5 +1,5 @@ /* Copyright (c) 2015-2018 Skyward Experimental Rocketry - * Author: Luca Erbetta + * Author: Luca Erbetta, Davide Mor * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,6 +24,8 @@ #include <miosix.h> +#include <type_traits> + #include "CircularBuffer.h" using miosix::FastInterruptDisableLock; @@ -38,20 +40,20 @@ namespace Boardcore * interrupt service routines. */ template <typename T, unsigned int Size> -class IRQCircularBuffer : public CircularBuffer<T, Size> +class IRQCircularBuffer { - - using Super = CircularBuffer<T, Size>; + static_assert(std::is_trivially_copy_constructible<T>::value, + "T must be trivially copy constructible!"); public: /** * @brief Puts a copy of the element in the buffer. */ - T& put(const T& elem) override + T& put(const T& elem) { FastInterruptDisableLock d; IRQwakeWaitingThread(); - return Super::put(elem); + return buffer.put(elem); } /** @@ -65,10 +67,23 @@ public: * @param i Index of the element to get, starting from the oldest. * @return The element. */ - T& get(unsigned int i = 0) override + T get(unsigned int i = 0) + { + FastInterruptDisableLock d; + return buffer.get(i); + } + + /** + * @brief Returns the last element added in the buffer. + * + * @warning Remember to catch the exception! + * @throw range_error if buffer is empty. + * @return The element. + */ + T last() { FastInterruptDisableLock d; - return Super::get(i); + return buffer.last(); } /** @@ -78,10 +93,10 @@ public: * @throw range_error if buffer is empty. * @return The element that has been popped. */ - const T& pop() override + T pop() { FastInterruptDisableLock d; - return Super::pop(); + return buffer.pop(); } /** @@ -89,22 +104,22 @@ public: * * @return Number of elements in the buffer. */ - size_t count() const override + size_t count() const { FastInterruptDisableLock d; - return Super::count(); + return buffer.count(); } - bool isEmpty() const override + bool isEmpty() const { FastInterruptDisableLock d; - return Super::isEmpty(); + return buffer.isEmpty(); } - bool isFull() const override + bool isFull() const { FastInterruptDisableLock d; - return Super::isFull(); + return buffer.isFull(); } /** @@ -112,10 +127,10 @@ public: * * @warning Only to be called inside an ISR or with interrupts disabled. */ - T& IRQput(const T& elem) + void IRQput(const T& elem) { IRQwakeWaitingThread(); - return Super::put(elem); + buffer.put(elem); } /** @@ -127,14 +142,14 @@ public: * @param hppw Set to true if the woken thread is higher priority than the * current one, unchanged otherwise */ - T& IRQput(const T& elem, bool& hppw) + void IRQput(const T& elem, bool& hppw) { if (waiting && (waiting->IRQgetPriority() > Thread::IRQgetCurrentThread()->IRQgetPriority())) hppw = true; IRQwakeWaitingThread(); - return Super::put(elem); + buffer.put(elem); } /** @@ -150,7 +165,7 @@ public: * @param i Index of the element to get, starting from the oldest. * @return The element. */ - T& IRQget(unsigned int i = 0) { return Super::get(i); } + T IRQget(unsigned int i = 0) { return buffer.get(i); } /** * @brief Pops the first element in the buffer. @@ -161,7 +176,7 @@ public: * @throw range_error if buffer is empty. * @return The element that has been popped. */ - const T& IRQpop() { return Super::pop(); } + T IRQpop() { return buffer.pop(); } /** * @brief Counts the elements in the buffer. @@ -170,17 +185,17 @@ public: * * @return Number of elements in the buffer. */ - size_t IRQcount() const { return Super::count(); } + size_t IRQcount() const { return buffer.count(); } /** * @warning Only to be called inside an ISR or with interrupts disabled. */ - bool IRQisEmpty() const { return Super::isEmpty(); } + bool IRQisEmpty() const { return buffer.isEmpty(); } /** * @warning Only to be called inside an ISR or with interrupts disabled. */ - bool IRQisFull() const { return Super::isFull(); } + bool IRQisFull() const { return buffer.isFull(); } /** * @brief Waits until the buffer contains at least one element. @@ -188,7 +203,7 @@ public: void waitUntilNotEmpty() { FastInterruptDisableLock d; - while (Super::isEmpty()) + while (buffer.isEmpty()) { IRQwakeWaitingThread(); waiting = Thread::IRQgetCurrentThread(); @@ -201,6 +216,14 @@ public: } } + /** + * @brief Returns the maximum number of elements that can be stored in the + * buffer. + * + * @return Buffer size. + */ + size_t getSize() const { return Size; } + private: void IRQwakeWaitingThread() { @@ -212,6 +235,7 @@ private: } Thread* waiting = nullptr; + CircularBuffer<T, Size> buffer; }; } // namespace Boardcore diff --git a/src/shared/utils/collections/SyncCircularBuffer.h b/src/shared/utils/collections/SyncCircularBuffer.h index 27f757cd1fb03cc745f192f1940157b094149af1..eb2eeeb7d4c059d49b631a166eb90c69fbcd1cd3 100644 --- a/src/shared/utils/collections/SyncCircularBuffer.h +++ b/src/shared/utils/collections/SyncCircularBuffer.h @@ -1,5 +1,5 @@ /* Copyright (c) 2015-2018 Skyward Experimental Rocketry - * Author: Luca Erbetta + * Author: Luca Erbetta, Davide Mor * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,6 +24,8 @@ #include <miosix.h> +#include <type_traits> + #include "CircularBuffer.h" using miosix::ConditionVariable; @@ -37,21 +39,18 @@ namespace Boardcore * Implementation of a synchronized circular buffer */ template <typename T, unsigned int Size> -class SyncCircularBuffer : public CircularBuffer<T, Size> +class SyncCircularBuffer { - - using Super = CircularBuffer<T, Size>; - public: /** * Puts a copy of the element in the buffer * @param elem element */ - T& put(const T& elem) override + void put(const T& elem) { Lock<FastMutex> l(mutex); cv.signal(); - return Super::put(elem); + buffer.put(elem); } /** @@ -65,10 +64,23 @@ public: * @param i Index of the element to get, starting from the oldest. * @return The element. */ - T& get(unsigned int i = 0) override + T get(unsigned int i = 0) + { + Lock<FastMutex> l(mutex); + return buffer.get(i); + } + + /** + * @brief Returns the last element added in the buffer. + * + * @warning Remember to catch the exception! + * @throw range_error if buffer is empty. + * @return The element. + */ + T last() { Lock<FastMutex> l(mutex); - return Super::get(i); + return buffer.last(); } /** @@ -78,10 +90,10 @@ public: * @throw range_error if buffer is empty. * @return The element that has been popped. */ - const T& pop() override + T pop() { Lock<FastMutex> l(mutex); - return Super::pop(); + return buffer.pop(); } /** @@ -89,22 +101,22 @@ public: * * @return Number of elements in the buffer. */ - size_t count() const override + size_t count() const { Lock<FastMutex> l(mutex); - return Super::count(); + return buffer.count(); } - bool isEmpty() const override + bool isEmpty() const { Lock<FastMutex> l(mutex); - return Super::isEmpty(); + return buffer.isEmpty(); } - bool isFull() const override + bool isFull() const { Lock<FastMutex> l(mutex); - return Super::isFull(); + return buffer.isFull(); } /** @@ -113,15 +125,25 @@ public: void waitUntilNotEmpty() { Lock<FastMutex> l(mutex); - while (Super::isEmpty()) + while (buffer.isEmpty()) { cv.wait(l); } } + /** + * @brief Returns the maximum number of elements that can be stored in the + * buffer. + * + * @return Buffer size. + */ + size_t getSize() const { return Size; } + private: mutable FastMutex mutex; mutable ConditionVariable cv; + + CircularBuffer<T, Size> buffer; }; } // namespace Boardcore diff --git a/src/shared/utils/collections/SyncPacketQueue.h b/src/shared/utils/collections/SyncPacketQueue.h index 4a28254b2d2803c5f79dad9f3feb3a115abde7a3..b786f7f2916d27401446d351ff0a0c3011f8cfe0 100644 --- a/src/shared/utils/collections/SyncPacketQueue.h +++ b/src/shared/utils/collections/SyncPacketQueue.h @@ -271,7 +271,7 @@ public: /** * @return The oldest packet, without removing it from the queue. */ - const Packet<pktLen>& get() + const Packet<pktLen> get() { Lock<FastMutex> l(mutex); return buffer.get(); @@ -280,7 +280,7 @@ public: /** * @return The oldest packet, removing it from the queue. */ - const Packet<pktLen>& pop() + const Packet<pktLen> pop() { Lock<FastMutex> l(mutex); return buffer.pop();