Merge branch 'developer' of github.com:slsdetectorgroup/slsDetectorPackage into developer

This commit is contained in:
maliakal_d 2020-02-03 12:25:40 +01:00
commit 56484daf18
2 changed files with 77 additions and 29 deletions

View File

@ -4,7 +4,7 @@
* published at http://www.kjellkod.cc/threadsafecircularqueue * published at http://www.kjellkod.cc/threadsafecircularqueue
* 2009-11-02 * 2009-11-02
* @author Kjell Hedstr<EFBFBD>m, hedstrom@kjellkod.cc * @author Kjell Hedstr<EFBFBD>m, hedstrom@kjellkod.cc
* modified by the sls detetor group * modified by the sls detector group
* */ * */
#include <iostream> #include <iostream>
@ -15,28 +15,31 @@
* Thread safe for one reader, and one writer */ * Thread safe for one reader, and one writer */
template <typename Element> class CircularFifo { template <typename Element> class CircularFifo {
private: private:
std::vector<Element *> array; size_t tail{0};
unsigned int tail; // input index size_t head{0};
unsigned int head; // output index size_t capacity;
unsigned int Capacity; std::vector<Element *> data;
mutable sem_t data_mutex; mutable sem_t data_mutex;
mutable sem_t free_mutex; mutable sem_t free_mutex;
unsigned int increment(unsigned int idx_) const; size_t increment(size_t i) const;
public: public:
CircularFifo(unsigned int Size) : tail(0), head(0) { explicit CircularFifo(size_t size) : capacity(size + 1), data(capacity) {
Capacity = Size + 1;
array.resize(Capacity);
sem_init(&data_mutex, 0, 0); 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() { virtual ~CircularFifo() {
sem_destroy(&data_mutex); sem_destroy(&data_mutex);
sem_destroy(&free_mutex); sem_destroy(&free_mutex);
} }
bool push(Element *&item_, bool no_block = false); bool push(Element *&item, bool no_block = false);
bool pop(Element *&item_, bool no_block = false); bool pop(Element *&item, bool no_block = false);
bool isEmpty() const; bool isEmpty() const;
bool isFull() const; bool isFull() const;
@ -65,13 +68,13 @@ template <typename Element> int CircularFifo<Element>::getFreeValue() const {
* \param no_block if true, return immediately if fifo is full * \param no_block if true, return immediately if fifo is full
* \return whether operation was successful or not */ * \return whether operation was successful or not */
template <typename Element> template <typename Element>
bool CircularFifo<Element>::push(Element *&item_, bool no_block) { bool CircularFifo<Element>::push(Element *&item, bool no_block) {
// check for fifo full // check for fifo full
if (no_block && isFull()) if (no_block && isFull())
return false; return false;
sem_wait(&free_mutex); sem_wait(&free_mutex);
array[tail] = item_; data[tail] = item;
tail = increment(tail); tail = increment(tail);
sem_post(&data_mutex); sem_post(&data_mutex);
return true; return true;
@ -85,21 +88,21 @@ bool CircularFifo<Element>::push(Element *&item_, bool no_block) {
* \param no_block if true, return immediately if fifo is full * \param no_block if true, return immediately if fifo is full
* \return whether operation was successful or not */ * \return whether operation was successful or not */
template <typename Element> template <typename Element>
bool CircularFifo<Element>::pop(Element *&item_, bool no_block) { bool CircularFifo<Element>::pop(Element *&item, bool no_block) {
// check for fifo empty // check for fifo empty
if (no_block && isEmpty()) if (no_block && isEmpty())
return false; return false;
sem_wait(&data_mutex); sem_wait(&data_mutex);
item_ = array[head]; item = data[head];
head = increment(head); head = increment(head);
sem_post(&free_mutex); sem_post(&free_mutex);
return true; 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 * 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 */ * \return true if circular buffer is empty */
template <typename Element> bool CircularFifo<Element>::isEmpty() const { template <typename Element> bool CircularFifo<Element>::isEmpty() const {
@ -116,19 +119,12 @@ template <typename Element> bool CircularFifo<Element>::isFull() const {
} }
/** Increment helper function for index of the circular queue /** 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 * \param idx_ the index to the incremented/wrapped
* \return new value for the index */ * \return new value for the index */
template <typename Element> template <typename Element>
unsigned int CircularFifo<Element>::increment(unsigned int idx_) const { size_t CircularFifo<Element>::increment(size_t i) const {
// increment or wrap i = (i + 1) % capacity;
// ================= return i;
// index++;
// if(index == array.lenght) -> index = 0;
//
// or as written below:
// index = (index+1) % array.length
idx_ = (idx_ + 1) % Capacity;
return idx_;
} }

View File

@ -0,0 +1,52 @@
#include "catch.hpp"
#include "CircularFifo.h"
#include <vector>
TEST_CASE("Empty buffer"){
CircularFifo<char> 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<int> fifo(5);
std::vector<int> 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);
}