** Return number of elements available for reading. */
ring_buffer_size_t PaUtil_GetRingBufferReadAvailable( const PaUtilRingBuffer *rbuf )
{
- PaUtil_ReadMemoryBarrier();
return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
}
/***************************************************************************
** Return number of elements available for writing. */
ring_buffer_size_t PaUtil_GetRingBufferWriteAvailable( const PaUtilRingBuffer *rbuf )
{
- /* Since we are calling PaUtil_GetRingBufferReadAvailable, we don't need an aditional MB */
return ( rbuf->bufferSize - PaUtil_GetRingBufferReadAvailable(rbuf));
}
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
+
+ /* fixme: do we want a memory barrier here for write-after-read / acquire ?
+ if( available )
+ PaUtil_ReadMemoryBarrier(); / * (read-after-read / acquire) * /
+ */
+
return elementCount;
}
*/
ring_buffer_size_t PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount )
{
- /* we need to ensure that previous writes are seen before we update the write index */
+ /* we need to ensure that previous writes are seen before we update the write index
+ (write after write / release)
+ */
PaUtil_WriteMemoryBarrier();
return rbuf->writeIndex = (rbuf->writeIndex + elementCount) & rbuf->bigMask;
}
void **dataPtr2, ring_buffer_size_t *sizePtr2 )
{
ring_buffer_size_t index;
- ring_buffer_size_t available = PaUtil_GetRingBufferReadAvailable( rbuf );
+ ring_buffer_size_t available = PaUtil_GetRingBufferReadAvailable( rbuf ); /* doesn't use memory barrier */
if( elementCount > available ) elementCount = available;
/* Check to see if read is not contiguous. */
index = rbuf->readIndex & rbuf->smallMask;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
+
+ if( available )
+ PaUtil_ReadMemoryBarrier(); /* (read-after-read / acquire) */
+
return elementCount;
}
/***************************************************************************
*/
ring_buffer_size_t PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount )
{
- /* we need to ensure that previous writes are always seen before updating the index. */
+ /* ensure that previous reads (copies out of the ring buffer) are always completed before updating the read index.
+ (write-after-read / release)
+ */
PaUtil_WriteMemoryBarrier();
return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask;
}
typedef struct PaUtilRingBuffer
{
ring_buffer_size_t bufferSize; /**< Number of elements in FIFO. Power of 2. Set by PaUtil_InitRingBuffer. */
- ring_buffer_size_t writeIndex; /**< Index of next writable element. Set by PaUtil_AdvanceRingBufferWriteIndex. */
- ring_buffer_size_t readIndex; /**< Index of next readable element. Set by PaUtil_AdvanceRingBufferReadIndex. */
+ volatile ring_buffer_size_t writeIndex; /**< Index of next writable element. Set by PaUtil_AdvanceRingBufferWriteIndex. */
+ volatile ring_buffer_size_t readIndex; /**< Index of next readable element. Set by PaUtil_AdvanceRingBufferReadIndex. */
ring_buffer_size_t bigMask; /**< Used for wrapping indices with extra bit to distinguish full/empty. */
ring_buffer_size_t smallMask; /**< Used for fitting indices to buffer. */
ring_buffer_size_t elementSizeBytes; /**< Number of bytes per element. */