/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /*epicsRingPointer.h */ /* Author: Marty Kraimer Date: 15JUL99 */ #ifndef INCepicsRingPointerh #define INCepicsRingPointerh /* NOTES * If there is only one writer it is not necessary to lock push * If there is a single reader it is not necessary to lock pop */ #include "shareLib.h" #ifdef __cplusplus template class epicsRingPointer { public: /* Functions */ epicsRingPointer(int size); ~epicsRingPointer(); bool push(T *p); T* pop(); void flush(); int getFree() const; int getUsed() const; int getSize() const; bool isEmpty() const; bool isFull() const; private: /* Prevent compiler-generated member functions */ /* default constructor, copy constructor, assignment operator */ epicsRingPointer(); epicsRingPointer(const epicsRingPointer &); epicsRingPointer& operator=(const epicsRingPointer &); private: /* Data */ volatile int nextPush; volatile int nextPop; int size; T * volatile * buffer; }; extern "C" { #endif /*__cplusplus */ typedef void *epicsRingPointerId; epicsShareFunc epicsRingPointerId epicsShareAPI epicsRingPointerCreate(int size); epicsShareFunc void epicsShareAPI epicsRingPointerDelete(epicsRingPointerId id); /*ringPointerPush returns (0,1) if p (was not, was) put on ring*/ epicsShareFunc int epicsShareAPI epicsRingPointerPush(epicsRingPointerId id,void *p); /*ringPointerPop returns 0 if ring is empty*/ epicsShareFunc void* epicsShareAPI epicsRingPointerPop(epicsRingPointerId id) ; epicsShareFunc void epicsShareAPI epicsRingPointerFlush(epicsRingPointerId id); epicsShareFunc int epicsShareAPI epicsRingPointerGetFree(epicsRingPointerId id); epicsShareFunc int epicsShareAPI epicsRingPointerGetUsed(epicsRingPointerId id); epicsShareFunc int epicsShareAPI epicsRingPointerGetSize(epicsRingPointerId id); epicsShareFunc int epicsShareAPI epicsRingPointerIsEmpty(epicsRingPointerId id); epicsShareFunc int epicsShareAPI epicsRingPointerIsFull(epicsRingPointerId id); #ifdef __cplusplus } #endif /* END OF DECLARATIONS */ /* INLINE FUNCTIONS */ /* Algorithm note * Space is allocated for one additional element. * A put request is rejected if the it would cause nextPush to equal nextPop * The algorithm does not require locking puts for a single writer * or locking of gets for a single reader */ #ifdef __cplusplus template inline epicsRingPointer::epicsRingPointer(int sz) : nextPush(0), nextPop(0), size(sz+1), buffer(new T* [sz+1]) {} template inline epicsRingPointer::~epicsRingPointer() { delete [] buffer;} template inline bool epicsRingPointer::push(T *p) { int next = nextPush; int newNext = next + 1; if(newNext>=size) newNext=0; if(newNext==nextPop) return(false); buffer[next] = p; nextPush = newNext; return(true); } template inline T* epicsRingPointer::pop() { int next = nextPop; if(next == nextPush) return(0); T*p = buffer[next]; ++next; if(next >=size) next = 0; nextPop = next; return(p); } template inline void epicsRingPointer::flush() { nextPop = 0; nextPush = 0; } template inline int epicsRingPointer::getFree() const { int n = nextPop - nextPush - 1; if (n < 0) n += size; return n; } template inline int epicsRingPointer::getUsed() const { int n = nextPush - nextPop; if (n < 0) n += size; return n; } template inline int epicsRingPointer::getSize() const { return(size-1);} template inline bool epicsRingPointer::isEmpty() const { return(nextPush==nextPop);} template inline bool epicsRingPointer::isFull() const { int count = nextPush - nextPop +1; return((count == 0) || (count == size)); } #endif /* __cplusplus */ #endif /* INCepicsRingPointerh */