This is Unofficial EPICS BASE Doxygen Site
epicsRingPointer.h
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * Copyright (c) 2012 ITER Organization.
7 * EPICS BASE is distributed subject to a Software License Agreement found
8 * in file LICENSE that is included with this distribution.
9 \*************************************************************************/
27 #ifndef INCepicsRingPointerh
28 #define INCepicsRingPointerh
29 
30 
31 #include "epicsSpin.h"
32 #include "libComAPI.h"
33 
34 #ifdef __cplusplus
35 
40 template <class T>
41 class epicsRingPointer {
42 public: /* Functions */
47  epicsRingPointer(int size, bool locked);
50  ~epicsRingPointer();
54  bool push(T *p);
58  T* pop();
63  void flush();
67  int getFree() const;
71  int getUsed() const;
75  int getSize() const;
79  bool isEmpty() const;
83  bool isFull() const;
91  int getHighWaterMark() const;
96  void resetHighWaterMark();
97 
98 private: /* Prevent compiler-generated member functions */
99  /* default constructor, copy constructor, assignment operator */
100  epicsRingPointer();
101  epicsRingPointer(const epicsRingPointer &);
102  epicsRingPointer& operator=(const epicsRingPointer &);
103  int getUsedNoLock() const;
104 
105 private: /* Data */
107  volatile int nextPush;
108  volatile int nextPop;
109  int size;
110  int highWaterMark;
111  T * volatile * buffer;
112 };
113 
114 extern "C" {
115 #endif /*__cplusplus */
116 
118 typedef void *epicsRingPointerId;
119 typedef void const *epicsRingPointerIdConst;
125 LIBCOM_API epicsRingPointerId epicsStdCall epicsRingPointerCreate(int size);
131 LIBCOM_API epicsRingPointerId epicsStdCall epicsRingPointerLockedCreate(int size);
136 LIBCOM_API void epicsStdCall epicsRingPointerDelete(epicsRingPointerId id);
143 LIBCOM_API int epicsStdCall epicsRingPointerPush(epicsRingPointerId id,void *p);
149 LIBCOM_API void* epicsStdCall epicsRingPointerPop(epicsRingPointerId id) ;
156 LIBCOM_API void epicsStdCall epicsRingPointerFlush(epicsRingPointerId id);
162 LIBCOM_API int epicsStdCall epicsRingPointerGetFree(epicsRingPointerId id);
168 LIBCOM_API int epicsStdCall epicsRingPointerGetUsed(epicsRingPointerId id);
175 LIBCOM_API int epicsStdCall epicsRingPointerGetSize(epicsRingPointerId id);
181 LIBCOM_API int epicsStdCall epicsRingPointerIsEmpty(epicsRingPointerId id);
187 LIBCOM_API int epicsStdCall epicsRingPointerIsFull(epicsRingPointerId id);
197 LIBCOM_API int epicsStdCall epicsRingPointerGetHighWaterMark(epicsRingPointerIdConst id);
204 LIBCOM_API void epicsStdCall epicsRingPointerResetHighWaterMark(epicsRingPointerId id);
205 
206 /* This routine was incorrectly named in previous releases */
207 #define epicsRingPointerSize epicsRingPointerGetSize
208 
209 #ifdef __cplusplus
210 }
211 #endif
212 /* END OF DECLARATIONS */
213 
214 /* INLINE FUNCTIONS */
215 
216 #ifdef __cplusplus
217 
218 template <class T>
219 inline epicsRingPointer<T>::epicsRingPointer(int sz, bool locked) :
220  lock(0), nextPush(0), nextPop(0), size(sz+1), highWaterMark(0),
221  buffer(new T* [sz+1])
222 {
223  if (locked)
224  lock = epicsSpinCreate();
225 }
226 
227 template <class T>
228 inline epicsRingPointer<T>::~epicsRingPointer()
229 {
230  if (lock) epicsSpinDestroy(lock);
231  delete [] buffer;
232 }
233 
234 template <class T>
235 inline bool epicsRingPointer<T>::push(T *p)
236 {
237  if (lock) epicsSpinLock(lock);
238  int next = nextPush;
239  int newNext = next + 1;
240  if(newNext>=size) newNext=0;
241  if (newNext == nextPop) {
242  if (lock) epicsSpinUnlock(lock);
243  return(false);
244  }
245  buffer[next] = p;
246  nextPush = newNext;
247  int used = getUsedNoLock();
248  if (used > highWaterMark) highWaterMark = used;
249  if (lock) epicsSpinUnlock(lock);
250  return(true);
251 }
252 
253 template <class T>
254 inline T* epicsRingPointer<T>::pop()
255 {
256  if (lock) epicsSpinLock(lock);
257  int next = nextPop;
258  if (next == nextPush) {
259  if (lock) epicsSpinUnlock(lock);
260  return(0);
261  }
262  T*p = buffer[next];
263  ++next;
264  if(next >=size) next = 0;
265  nextPop = next;
266  if (lock) epicsSpinUnlock(lock);
267  return(p);
268 }
269 
270 template <class T>
271 inline void epicsRingPointer<T>::flush()
272 {
273  if (lock) epicsSpinLock(lock);
274  nextPop = 0;
275  nextPush = 0;
276  if (lock) epicsSpinUnlock(lock);
277 }
278 
279 template <class T>
280 inline int epicsRingPointer<T>::getFree() const
281 {
282  if (lock) epicsSpinLock(lock);
283  int n = nextPop - nextPush - 1;
284  if (n < 0) n += size;
285  if (lock) epicsSpinUnlock(lock);
286  return n;
287 }
288 
289 template <class T>
290 inline int epicsRingPointer<T>::getUsedNoLock() const
291 {
292  int n = nextPush - nextPop;
293  if (n < 0) n += size;
294  return n;
295 }
296 
297 template <class T>
298 inline int epicsRingPointer<T>::getUsed() const
299 {
300  if (lock) epicsSpinLock(lock);
301  int n = getUsedNoLock();
302  if (lock) epicsSpinUnlock(lock);
303  return n;
304 }
305 
306 template <class T>
307 inline int epicsRingPointer<T>::getSize() const
308 {
309  return(size-1);
310 }
311 
312 template <class T>
313 inline bool epicsRingPointer<T>::isEmpty() const
314 {
315  bool isEmpty;
316  if (lock) epicsSpinLock(lock);
317  isEmpty = (nextPush == nextPop);
318  if (lock) epicsSpinUnlock(lock);
319  return isEmpty;
320 }
321 
322 template <class T>
323 inline bool epicsRingPointer<T>::isFull() const
324 {
325  if (lock) epicsSpinLock(lock);
326  int count = nextPush - nextPop +1;
327  if (lock) epicsSpinUnlock(lock);
328  return((count == 0) || (count == size));
329 }
330 
331 template <class T>
332 inline int epicsRingPointer<T>::getHighWaterMark() const
333 {
334  return highWaterMark;
335 }
336 
337 template <class T>
338 inline void epicsRingPointer<T>::resetHighWaterMark()
339 {
340  if (lock) epicsSpinLock(lock);
341  highWaterMark = getUsedNoLock();
342  if (lock) epicsSpinUnlock(lock);
343 }
344 
345 #endif /* __cplusplus */
346 
347 #endif /* INCepicsRingPointerh */
LIBCOM_API epicsRingPointerId epicsStdCall epicsRingPointerCreate(int size)
Create a new ring buffer.
epicsMutexId lock
Definition: osiClockTime.c:37
LIBCOM_API void epicsStdCall epicsRingPointerResetHighWaterMark(epicsRingPointerId id)
Reset the Highwater mark of the ring buffer.
LIBCOM_API int epicsStdCall epicsRingPointerGetUsed(epicsRingPointerId id)
Return the number of elements stored in the ring buffer.
LIBCOM_API void epicsStdCall epicsRingPointerFlush(epicsRingPointerId id)
Remove all elements from the ring.
LIBCOM_API int epicsStdCall epicsRingPointerPush(epicsRingPointerId id, void *p)
Push pointer into the ring buffer.
LIBCOM_API void *epicsStdCall epicsRingPointerPop(epicsRingPointerId id)
Take an element off the ring.
LIBCOM_API int epicsStdCall epicsRingPointerGetHighWaterMark(epicsRingPointerIdConst id)
Get the Highwater mark of the ring buffer.
LIBCOM_API int epicsStdCall epicsRingPointerIsEmpty(epicsRingPointerId id)
Check if the ring buffer is currently empty.
LIBCOM_API void epicsStdCall epicsRingPointerDelete(epicsRingPointerId id)
Delete the ring buffer and free any associated memory.
LIBCOM_API int epicsStdCall epicsRingPointerIsFull(epicsRingPointerId id)
Check if the ring buffer is currently full.
LIBCOM_API int epicsStdCall epicsRingPointerGetFree(epicsRingPointerId id)
Return the amount of empty space in the ring buffer.
void const * epicsRingPointerIdConst
LIBCOM_API epicsRingPointerId epicsStdCall epicsRingPointerLockedCreate(int size)
Create a new ring buffer, secured by a spinlock.
epicsEventId flush
Definition: errlog.c:70
void * epicsRingPointerId
An identifier for the C API to a ring buffer storing pointers.
LIBCOM_API void epicsSpinDestroy(epicsSpinId)
Definition: osdSpin.c:54
LIBCOM_API int epicsStdCall epicsRingPointerGetSize(epicsRingPointerId id)
Return the size of the ring.
LIBCOM_API void epicsSpinLock(epicsSpinId)
Definition: osdSpin.c:59
LIBCOM_API epicsSpinId epicsSpinCreate(void)
Definition: osdSpin.c:28
LIBCOM_API void epicsSpinUnlock(epicsSpinId)
Definition: osdSpin.c:81