This commit is contained in:
Erik Frojdh 2020-02-03 11:04:49 +01:00
parent 9f79f132b7
commit a3c686d271
4 changed files with 89 additions and 103 deletions

View File

@ -17,7 +17,7 @@
#include <pthread.h> #include <pthread.h>
#include "analogDetector.h" #include "analogDetector.h"
#include "circularFifo.h" #include "CircularFifo.h"
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -1,79 +1,71 @@
#pragma once #pragma once
/* CircularFifo.h /* CircularFifo.h
* Code & platform dependent issues with it was originally * Code & platform dependent issues with it was originally
* 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 detetor group
* */ * */
#include <iostream>
#include <semaphore.h> #include <semaphore.h>
#include <vector> #include <vector>
#include <iostream>
/** Circular Fifo (a.k.a. Circular Buffer) /** Circular Fifo (a.k.a. Circular Buffer)
* Thread safe for one reader, and one writer */ * Thread safe for one reader, and one writer */
template<typename Element> template <typename Element> class CircularFifo {
class CircularFifo { private:
public: std::vector<Element *> array;
unsigned int tail; // input index
unsigned int head; // output index
unsigned int Capacity;
mutable sem_t data_mutex;
mutable sem_t free_mutex;
unsigned int increment(unsigned int idx_) const;
CircularFifo(unsigned int Size) : tail(0), head(0){ public:
Capacity = Size + 1; CircularFifo(unsigned int Size) : tail(0), head(0) {
array.resize(Capacity); Capacity = Size + 1;
sem_init(&data_mutex,0,0); array.resize(Capacity);
sem_init(&free_mutex,0,Size); sem_init(&data_mutex, 0, 0);
} sem_init(&free_mutex, 0, Size);
virtual ~CircularFifo() { }
sem_destroy(&data_mutex); virtual ~CircularFifo() {
sem_destroy(&free_mutex); sem_destroy(&data_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;
int getDataValue() const; int getDataValue() const;
int getFreeValue() const; int getFreeValue() const;
private:
std::vector <Element*> array;
unsigned int tail; // input index
unsigned int head; // output index
unsigned int Capacity;
mutable sem_t data_mutex;
mutable sem_t free_mutex;
unsigned int increment(unsigned int idx_) const;
}; };
template<typename Element> template <typename Element> int CircularFifo<Element>::getDataValue() const {
int CircularFifo<Element>::getDataValue() const int value;
{ sem_getvalue(&data_mutex, &value);
int value; return value;
sem_getvalue(&data_mutex, &value);
return value;
} }
template<typename Element> template <typename Element> int CircularFifo<Element>::getFreeValue() const {
int CircularFifo<Element>::getFreeValue() const
{
int value; int value;
sem_getvalue(&free_mutex, &value); sem_getvalue(&free_mutex, &value);
return value; return value;
} }
/** Producer only: Adds item to the circular queue. /** Producer only: Adds item to the circular queue.
* If queue is full at 'push' operation no update/overwrite * If queue is full at 'push' operation no update/overwrite
* will happen, it is up to the caller to handle this case * will happen, it is up to the caller to handle this case
* *
* \param item_ copy by reference the input item * \param item_ copy by reference the input item
* \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;
@ -86,64 +78,57 @@ bool CircularFifo<Element>::push(Element*& item_, bool no_block)
} }
/** Consumer only: Removes and returns item from the queue /** Consumer only: Removes and returns item from the queue
* If queue is empty at 'pop' operation no retrieve will happen * If queue is empty at 'pop' operation no retrieve will happen
* It is up to the caller to handle this case * It is up to the caller to handle this case
* *
* \param item_ return by reference the wanted item * \param item_ return by reference the wanted item
* \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_ = array[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 testinng 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 Procuder adds more items.
* *
* \return true if circular buffer is empty */ * \return true if circular buffer is empty */
template<typename Element> template <typename Element> bool CircularFifo<Element>::isEmpty() const {
bool CircularFifo<Element>::isEmpty() const
{
return (getDataValue() == 0); return (getDataValue() == 0);
} }
/** Useful for testing and Producer check of status /** Useful for testing and Producer check of status
* Remember that the 'full' status can change quickly * Remember that the 'full' status can change quickly
* as the Consumer catches up. * as the Consumer catches up.
* *
* \return true if circular buffer is full. */ * \return true if circular buffer is full. */
template<typename Element> template <typename Element> bool CircularFifo<Element>::isFull() const {
bool CircularFifo<Element>::isFull() const
{
return (getFreeValue() == 0); return (getFreeValue() == 0);
} }
/** 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 inremented 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 unsigned int CircularFifo<Element>::increment(unsigned int idx_) const {
{ // increment or wrap
// increment or wrap // =================
// ================= // index++;
// index++; // if(index == array.lenght) -> index = 0;
// if(index == array.lenght) -> index = 0; //
// // or as written below:
//or as written below: // index = (index+1) % array.length
// index = (index+1) % array.length idx_ = (idx_ + 1) % Capacity;
idx_ = (idx_+1) % Capacity; return idx_;
return idx_;
} }

View File

@ -12,7 +12,7 @@
#include "sls_detector_defs.h" #include "sls_detector_defs.h"
#include "logger.h" #include "logger.h"
#include "circularFifo.h" #include "CircularFifo.h"
class Fifo : private virtual slsDetectorDefs { class Fifo : private virtual slsDetectorDefs {

View File

@ -1,4 +1,5 @@
target_sources(tests PRIVATE target_sources(tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/test-GeneralData.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-GeneralData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-FileNames.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-FileNames.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-CircularFifo.cpp
) )