diff --git a/slsReceiverSoftware/include/CircularFifo.h b/slsReceiverSoftware/include/CircularFifo.h index 28b60a869..4f88de63d 100755 --- a/slsReceiverSoftware/include/CircularFifo.h +++ b/slsReceiverSoftware/include/CircularFifo.h @@ -4,7 +4,7 @@ * published at http://www.kjellkod.cc/threadsafecircularqueue * 2009-11-02 * @author Kjell Hedstr�m, hedstrom@kjellkod.cc - * modified by the sls detetor group + * modified by the sls detector group * */ #include @@ -15,28 +15,31 @@ * Thread safe for one reader, and one writer */ template class CircularFifo { private: - std::vector array; - unsigned int tail; // input index - unsigned int head; // output index - unsigned int Capacity; + size_t tail{0}; + size_t head{0}; + size_t capacity; + std::vector data; mutable sem_t data_mutex; mutable sem_t free_mutex; - unsigned int increment(unsigned int idx_) const; + size_t increment(size_t i) const; public: - CircularFifo(unsigned int Size) : tail(0), head(0) { - Capacity = Size + 1; - array.resize(Capacity); + explicit CircularFifo(size_t size) : capacity(size + 1), data(capacity) { sem_init(&data_mutex, 0, 0); - sem_init(&free_mutex, 0, Size); + sem_init(&free_mutex, 0, size); } + + + CircularFifo(const CircularFifo &) = delete; + CircularFifo(CircularFifo&&) = delete; + virtual ~CircularFifo() { sem_destroy(&data_mutex); sem_destroy(&free_mutex); } - bool push(Element *&item_, bool no_block = false); - bool pop(Element *&item_, bool no_block = false); + bool push(Element *&item, bool no_block = false); + bool pop(Element *&item, bool no_block = false); bool isEmpty() const; bool isFull() const; @@ -65,13 +68,13 @@ template int CircularFifo::getFreeValue() const { * \param no_block if true, return immediately if fifo is full * \return whether operation was successful or not */ template -bool CircularFifo::push(Element *&item_, bool no_block) { +bool CircularFifo::push(Element *&item, bool no_block) { // check for fifo full if (no_block && isFull()) return false; sem_wait(&free_mutex); - array[tail] = item_; + data[tail] = item; tail = increment(tail); sem_post(&data_mutex); return true; @@ -85,21 +88,21 @@ bool CircularFifo::push(Element *&item_, bool no_block) { * \param no_block if true, return immediately if fifo is full * \return whether operation was successful or not */ template -bool CircularFifo::pop(Element *&item_, bool no_block) { +bool CircularFifo::pop(Element *&item, bool no_block) { // check for fifo empty if (no_block && isEmpty()) return false; sem_wait(&data_mutex); - item_ = array[head]; + item = data[head]; head = increment(head); sem_post(&free_mutex); return true; } -/** Useful for testinng and Consumer check of status +/** Useful for testing and Consumer check of status * Remember that the 'empty' status can change quickly - * as the Procuder adds more items. + * as the Producer adds more items. * * \return true if circular buffer is empty */ template bool CircularFifo::isEmpty() const { @@ -116,19 +119,12 @@ template bool CircularFifo::isFull() const { } /** Increment helper function for index of the circular queue - * index is inremented or wrapped + * index is incremented or wrapped * * \param idx_ the index to the incremented/wrapped * \return new value for the index */ template -unsigned int CircularFifo::increment(unsigned int idx_) const { - // increment or wrap - // ================= - // index++; - // if(index == array.lenght) -> index = 0; - // - // or as written below: - // index = (index+1) % array.length - idx_ = (idx_ + 1) % Capacity; - return idx_; +size_t CircularFifo::increment(size_t i) const { + i = (i + 1) % capacity; + return i; } diff --git a/slsReceiverSoftware/tests/test-CircularFifo.cpp b/slsReceiverSoftware/tests/test-CircularFifo.cpp new file mode 100644 index 000000000..0bc376636 --- /dev/null +++ b/slsReceiverSoftware/tests/test-CircularFifo.cpp @@ -0,0 +1,52 @@ +#include "catch.hpp" +#include "CircularFifo.h" +#include + +TEST_CASE("Empty buffer"){ + CircularFifo fifo(0); + + //Since the fifo can hold zero elements + //its both empty and full + CHECK(fifo.isEmpty()== true); + CHECK(fifo.isFull()== true); + + + //push fails + char* c = new char; + *c = 'h'; + CHECK(fifo.push(c, true) == false); + + //pop fails + CHECK(fifo.pop(c, true) == false); + + delete c; + +} + +TEST_CASE("Push pop"){ + CircularFifo fifo(5); + + std::vector vec{3,7,12,3,4}; + int* p = &vec[0]; + + for(size_t i =0; i!=vec.size(); ++i){ + fifo.push(p); + ++p; + CHECK(fifo.getDataValue() == i+1); + CHECK(fifo.getFreeValue() == 4-i); + } + + CHECK(fifo.isEmpty()== false); + CHECK(fifo.isFull()== true); + + for(size_t i = 0; i!= vec.size(); ++i){ + fifo.pop(p); + CHECK(*p == vec[i]); + CHECK(fifo.getDataValue() == 4-i); + CHECK(fifo.getFreeValue() == i+1); + } + + CHECK(fifo.isEmpty()== true); + CHECK(fifo.isFull()== false); + +} \ No newline at end of file