moved memory barriers as per this thread: http://music.columbia.edu/pipermail/portaudio/2011-August/012803.html . use volatile because MSVC Read/WriteBarrier() intrinsics are just compiler barriers, but MSVC will insert memory barriers if you use volatile. see: http://msdn.microsoft.com/en-us/library/ms686355(VS.85).aspx
This commit is contained in:
parent
fa8a45c845
commit
f22cec3d45
2 changed files with 19 additions and 7 deletions
|
|
@ -79,14 +79,12 @@ ring_buffer_size_t PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, ring_buf
|
|||
** 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));
|
||||
}
|
||||
|
||||
|
|
@ -128,6 +126,12 @@ ring_buffer_size_t PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, rin
|
|||
*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;
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +140,9 @@ ring_buffer_size_t PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, rin
|
|||
*/
|
||||
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;
|
||||
}
|
||||
|
|
@ -152,7 +158,7 @@ ring_buffer_size_t PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, ring
|
|||
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;
|
||||
|
|
@ -172,13 +178,19 @@ ring_buffer_size_t PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, ring
|
|||
*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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ extern "C"
|
|||
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. */
|
||||
|
|
|
|||
Loading…
Reference in a new issue