mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-22 14:38:14 +02:00
Merge branch 'developer' of github.com:slsdetectorgroup/slsDetectorPackage into developer
This commit is contained in:
commit
56484daf18
@ -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_;
|
|
||||||
}
|
}
|
||||||
|
52
slsReceiverSoftware/tests/test-CircularFifo.cpp
Normal file
52
slsReceiverSoftware/tests/test-CircularFifo.cpp
Normal 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);
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user