This is Unofficial EPICS BASE Doxygen Site
epicsRingBytes.h File Reference

A circular buffer to store bytes. More...

#include "libComAPI.h"
+ Include dependency graph for epicsRingBytes.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef void * epicsRingBytesId
 An identifier for a ring buffer. More...
 
typedef void const * epicsRingBytesIdConst
 

Functions

LIBCOM_API epicsRingBytesId epicsStdCall epicsRingBytesCreate (int nbytes)
 Create a new ring buffer. More...
 
LIBCOM_API epicsRingBytesId epicsStdCall epicsRingBytesLockedCreate (int nbytes)
 Create a new ring buffer, secured by a spinlock. More...
 
LIBCOM_API void epicsStdCall epicsRingBytesDelete (epicsRingBytesId id)
 Delete the ring buffer and free any associated memory. More...
 
LIBCOM_API int epicsStdCall epicsRingBytesGet (epicsRingBytesId id, char *value, int nbytes)
 Read data out of the ring buffer. More...
 
LIBCOM_API int epicsStdCall epicsRingBytesPut (epicsRingBytesId id, char *value, int nbytes)
 Write data into the ring buffer. More...
 
LIBCOM_API void epicsStdCall epicsRingBytesFlush (epicsRingBytesId id)
 Make the ring buffer empty. More...
 
LIBCOM_API int epicsStdCall epicsRingBytesFreeBytes (epicsRingBytesId id)
 Return the number of free bytes in the ring buffer. More...
 
LIBCOM_API int epicsStdCall epicsRingBytesUsedBytes (epicsRingBytesId id)
 Return the number of bytes currently stored in the ring buffer. More...
 
LIBCOM_API int epicsStdCall epicsRingBytesSize (epicsRingBytesId id)
 Return the size of the ring buffer. More...
 
LIBCOM_API int epicsStdCall epicsRingBytesIsEmpty (epicsRingBytesId id)
 Test if the ring buffer is currently empty. More...
 
LIBCOM_API int epicsStdCall epicsRingBytesIsFull (epicsRingBytesId id)
 Test if the ring buffer is currently full. More...
 
LIBCOM_API int epicsStdCall epicsRingBytesHighWaterMark (epicsRingBytesIdConst id)
 See how full a ring buffer has been since it was last checked. More...
 
LIBCOM_API void epicsStdCall epicsRingBytesResetHighWaterMark (epicsRingBytesId id)
 Reset the Highwater mark of the ring buffer. More...
 

Detailed Description

A circular buffer to store bytes.

Author
Marty Kraimer, Eric Norum, Ralph Lange

EpicsRingBytes provides a C API for creating and using ring buffers (first in first out circular buffers) that store bytes. The unlocked variant is designed so that one writer thread and one reader thread can access the ring simultaneously without requiring mutual exclusion. The locked variant uses an epicsSpinLock, and works with any numbers of writer and reader threads.

Note
If there is only one writer it is not necessary to lock for puts. If there is a single reader it is not necessary to lock for gets. epicsRingBytesLocked uses a spinlock.

Definition in file epicsRingBytes.h.

Typedef Documentation

typedef void* epicsRingBytesId

An identifier for a ring buffer.

Definition at line 37 of file epicsRingBytes.h.

typedef void const* epicsRingBytesIdConst

Definition at line 38 of file epicsRingBytes.h.

Function Documentation

LIBCOM_API epicsRingBytesId epicsStdCall epicsRingBytesCreate ( int  nbytes)

Create a new ring buffer.

Parameters
nbytesSize of ring buffer to create
Returns
Ring buffer Id or NULL on failure

Definition at line 44 of file epicsRingBytes.c.

45 {
46  ringPvt *pring = malloc(sizeof(ringPvt) + size + SLOP);
47  if(!pring)
48  return NULL;
49  pring->size = size + SLOP;
50  pring->highWaterMark = 0;
51  pring->nextGet = 0;
52  pring->nextPut = 0;
53  pring->lock = 0;
54  return((void *)pring);
55 }
#define SLOP
#define NULL
Definition: catime.c:38
volatile int nextPut
volatile int nextGet
epicsSpinId lock
int highWaterMark
LIBCOM_API void epicsStdCall epicsRingBytesDelete ( epicsRingBytesId  id)

Delete the ring buffer and free any associated memory.

Parameters
idRingbufferID returned by epicsRingBytesCreate()

Definition at line 66 of file epicsRingBytes.c.

67 {
68  ringPvt *pring = (ringPvt *)id;
69  if (pring->lock) epicsSpinDestroy(pring->lock);
70  free((void *)pring);
71 }
LIBCOM_API void epicsSpinDestroy(epicsSpinId)
Definition: osdSpin.c:54
epicsSpinId lock
LIBCOM_API void epicsStdCall epicsRingBytesFlush ( epicsRingBytesId  id)

Make the ring buffer empty.

Parameters
idRingbufferID returned by epicsRingBytesCreate()
Note
Should only be used when both gets and puts are locked out.

Definition at line 169 of file epicsRingBytes.c.

170 {
171  ringPvt *pring = (ringPvt *)id;
172 
173  if (pring->lock) epicsSpinLock(pring->lock);
174  pring->nextGet = pring->nextPut;
175  if (pring->lock) epicsSpinUnlock(pring->lock);
176 }
volatile int nextPut
volatile int nextGet
LIBCOM_API void epicsSpinLock(epicsSpinId)
Definition: osdSpin.c:59
LIBCOM_API void epicsSpinUnlock(epicsSpinId)
Definition: osdSpin.c:81
epicsSpinId lock
LIBCOM_API int epicsStdCall epicsRingBytesFreeBytes ( epicsRingBytesId  id)

Return the number of free bytes in the ring buffer.

Parameters
idRingbufferID returned by epicsRingBytesCreate()
Returns
The number of free bytes in the ring buffer

Definition at line 178 of file epicsRingBytes.c.

179 {
180  ringPvt *pring = (ringPvt *)id;
181  int nextGet, nextPut;
182 
183  if (pring->lock) epicsSpinLock(pring->lock);
184  nextGet = pring->nextGet;
185  nextPut = pring->nextPut;
186  if (pring->lock) epicsSpinUnlock(pring->lock);
187 
188  if (nextPut < nextGet)
189  return nextGet - nextPut - SLOP;
190  else
191  return pring->size - nextPut + nextGet - SLOP;
192 }
#define SLOP
volatile int nextPut
volatile int nextGet
LIBCOM_API void epicsSpinLock(epicsSpinId)
Definition: osdSpin.c:59
LIBCOM_API void epicsSpinUnlock(epicsSpinId)
Definition: osdSpin.c:81
epicsSpinId lock
LIBCOM_API int epicsStdCall epicsRingBytesGet ( epicsRingBytesId  id,
char *  value,
int  nbytes 
)

Read data out of the ring buffer.

Parameters
idRingbufferID returned by epicsRingBytesCreate()
valueWhere to put the data fetched from the buffer
nbytesMaximum number of bytes to get
Returns
The number of bytes actually fetched

Definition at line 73 of file epicsRingBytes.c.

75 {
76  ringPvt *pring = (ringPvt *)id;
77  int nextGet, nextPut, size;
78  int count;
79 
80  if (pring->lock) epicsSpinLock(pring->lock);
81  nextGet = pring->nextGet;
82  nextPut = pring->nextPut;
83  size = pring->size;
84 
85  if (nextGet <= nextPut) {
86  count = nextPut - nextGet;
87  if (count < nbytes)
88  nbytes = count;
89  if (nbytes)
90  memcpy (value, (void *)&pring->buffer[nextGet], nbytes);
91  nextGet += nbytes;
92  }
93  else {
94  count = size - nextGet;
95  if (count > nbytes)
96  count = nbytes;
97  memcpy (value, (void *)&pring->buffer[nextGet], count);
98  nextGet += count;
99  if (nextGet == size) {
100  int nLeft = nbytes - count;
101  if (nLeft > nextPut)
102  nLeft = nextPut;
103  memcpy (value+count, (void *)&pring->buffer[0], nLeft);
104  nextGet = nLeft;
105  nbytes = count + nLeft;
106  }
107  else {
108  nbytes = count;
109  }
110  }
111  pring->nextGet = nextGet;
112 
113  if (pring->lock) epicsSpinUnlock(pring->lock);
114  return nbytes;
115 }
Definition: link.h:174
volatile char buffer[1]
volatile int nextPut
volatile int nextGet
LIBCOM_API void epicsSpinLock(epicsSpinId)
Definition: osdSpin.c:59
LIBCOM_API void epicsSpinUnlock(epicsSpinId)
Definition: osdSpin.c:81
epicsSpinId lock
LIBCOM_API int epicsStdCall epicsRingBytesHighWaterMark ( epicsRingBytesIdConst  id)

See how full a ring buffer has been since it was last checked.

Returns the maximum amount of data the ring buffer has held in bytes since the water mark was last reset. A new ring buffer starts with a water mark of 0.

Parameters
idRingbufferID returned by epicsRingBytesCreate()
Returns
Actual Highwater mark

Definition at line 235 of file epicsRingBytes.c.

236 {
237  ringPvt *pring = (ringPvt *)id;
238  return pring->highWaterMark;
239 }
int highWaterMark
LIBCOM_API int epicsStdCall epicsRingBytesIsEmpty ( epicsRingBytesId  id)

Test if the ring buffer is currently empty.

Parameters
idRingbufferID returned by epicsRingBytesCreate()
Returns
1 if the buffer is empty, otherwise 0

Definition at line 218 of file epicsRingBytes.c.

219 {
220  ringPvt *pring = (ringPvt *)id;
221  int isEmpty;
222 
223  if (pring->lock) epicsSpinLock(pring->lock);
224  isEmpty = (pring->nextPut == pring->nextGet);
225  if (pring->lock) epicsSpinUnlock(pring->lock);
226 
227  return isEmpty;
228 }
volatile int nextPut
volatile int nextGet
LIBCOM_API void epicsSpinLock(epicsSpinId)
Definition: osdSpin.c:59
LIBCOM_API void epicsSpinUnlock(epicsSpinId)
Definition: osdSpin.c:81
epicsSpinId lock
LIBCOM_API int epicsStdCall epicsRingBytesIsFull ( epicsRingBytesId  id)

Test if the ring buffer is currently full.

Parameters
idRingbufferID returned by epicsRingBytesCreate()
Returns
1 if the buffer is full, otherwise 0

Definition at line 230 of file epicsRingBytes.c.

231 {
232  return (epicsRingBytesFreeBytes(id) <= 0);
233 }
LIBCOM_API int epicsStdCall epicsRingBytesFreeBytes(epicsRingBytesId id)
Return the number of free bytes in the ring buffer.
LIBCOM_API epicsRingBytesId epicsStdCall epicsRingBytesLockedCreate ( int  nbytes)

Create a new ring buffer, secured by a spinlock.

Parameters
nbytesSize of ring buffer to create
Returns
Ring buffer Id or NULL on failure

Definition at line 57 of file epicsRingBytes.c.

58 {
59  ringPvt *pring = (ringPvt *)epicsRingBytesCreate(size);
60  if(!pring)
61  return NULL;
62  pring->lock = epicsSpinCreate();
63  return((void *)pring);
64 }
#define NULL
Definition: catime.c:38
LIBCOM_API epicsRingBytesId epicsStdCall epicsRingBytesCreate(int size)
Create a new ring buffer.
LIBCOM_API epicsSpinId epicsSpinCreate(void)
Definition: osdSpin.c:28
epicsSpinId lock
LIBCOM_API int epicsStdCall epicsRingBytesPut ( epicsRingBytesId  id,
char *  value,
int  nbytes 
)

Write data into the ring buffer.

Parameters
idRingbufferID returned by epicsRingBytesCreate()
valueSource of the data to be put into the buffer
nbytesHow many bytes to put
Returns
The number of bytes actually stored, zero if not enough space

Definition at line 117 of file epicsRingBytes.c.

119 {
120  ringPvt *pring = (ringPvt *)id;
121  int nextGet, nextPut, size;
122  int freeCount, copyCount, topCount, used;
123 
124  if (pring->lock) epicsSpinLock(pring->lock);
125  nextGet = pring->nextGet;
126  nextPut = pring->nextPut;
127  size = pring->size;
128 
129  if (nextPut < nextGet) {
130  freeCount = nextGet - nextPut - SLOP;
131  if (nbytes > freeCount) {
132  if (pring->lock) epicsSpinUnlock(pring->lock);
133  return 0;
134  }
135  if (nbytes) {
136  memcpy ((void *)&pring->buffer[nextPut], value, nbytes);
137  }
138  nextPut += nbytes;
139  }
140  else {
141  freeCount = size - nextPut + nextGet - SLOP;
142  if (nbytes > freeCount) {
143  if (pring->lock) epicsSpinUnlock(pring->lock);
144  return 0;
145  }
146  topCount = size - nextPut;
147  copyCount = (nbytes > topCount) ? topCount : nbytes;
148  if (copyCount) {
149  memcpy ((void *)&pring->buffer[nextPut], value, copyCount);
150  }
151  nextPut += copyCount;
152  if (nextPut == size) {
153  int nLeft = nbytes - copyCount;
154  if (nLeft)
155  memcpy ((void *)&pring->buffer[0], value+copyCount, nLeft);
156  nextPut = nLeft;
157  }
158  }
159  pring->nextPut = nextPut;
160 
161  used = nextPut - nextGet;
162  if (used < 0) used += pring->size;
163  if (used > pring->highWaterMark) pring->highWaterMark = used;
164 
165  if (pring->lock) epicsSpinUnlock(pring->lock);
166  return nbytes;
167 }
Definition: link.h:174
#define SLOP
volatile char buffer[1]
volatile int nextPut
volatile int nextGet
LIBCOM_API void epicsSpinLock(epicsSpinId)
Definition: osdSpin.c:59
LIBCOM_API void epicsSpinUnlock(epicsSpinId)
Definition: osdSpin.c:81
epicsSpinId lock
int highWaterMark
LIBCOM_API void epicsStdCall epicsRingBytesResetHighWaterMark ( epicsRingBytesId  id)

Reset the Highwater mark of the ring buffer.

The Highwater mark will be set to the current usage

Parameters
idRingbufferID returned by epicsRingBytesCreate()

Definition at line 241 of file epicsRingBytes.c.

242 {
243  ringPvt *pring = (ringPvt *)id;
244  int used;
245  if (pring->lock) epicsSpinLock(pring->lock);
246  used = pring->nextGet - pring->nextPut;
247  if (used < 0) used += pring->size;
248  pring->highWaterMark = used;
249  if (pring->lock) epicsSpinUnlock(pring->lock);
250 }
volatile int nextPut
volatile int nextGet
LIBCOM_API void epicsSpinLock(epicsSpinId)
Definition: osdSpin.c:59
LIBCOM_API void epicsSpinUnlock(epicsSpinId)
Definition: osdSpin.c:81
epicsSpinId lock
int highWaterMark
LIBCOM_API int epicsStdCall epicsRingBytesSize ( epicsRingBytesId  id)

Return the size of the ring buffer.

Parameters
idRingbufferID returned by epicsRingBytesCreate()
Returns
Return the size of the ring buffer, i.e., nbytes specified in the call to epicsRingBytesCreate().

Definition at line 211 of file epicsRingBytes.c.

212 {
213  ringPvt *pring = (ringPvt *)id;
214 
215  return pring->size - SLOP;
216 }
#define SLOP
LIBCOM_API int epicsStdCall epicsRingBytesUsedBytes ( epicsRingBytesId  id)

Return the number of bytes currently stored in the ring buffer.

Parameters
idRingbufferID returned by epicsRingBytesCreate()
Returns
The number of bytes currently stored in the ring buffer

Definition at line 194 of file epicsRingBytes.c.

195 {
196  ringPvt *pring = (ringPvt *)id;
197  int nextGet, nextPut;
198  int used;
199 
200  if (pring->lock) epicsSpinLock(pring->lock);
201  nextGet = pring->nextGet;
202  nextPut = pring->nextPut;
203  if (pring->lock) epicsSpinUnlock(pring->lock);
204 
205  used = nextPut - nextGet;
206  if (used < 0) used += pring->size;
207 
208  return used;
209 }
volatile int nextPut
volatile int nextGet
LIBCOM_API void epicsSpinLock(epicsSpinId)
Definition: osdSpin.c:59
LIBCOM_API void epicsSpinUnlock(epicsSpinId)
Definition: osdSpin.c:81
epicsSpinId lock