aboutsummaryrefslogtreecommitdiff
path: root/pd/portaudio/src/common/pa_ringbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'pd/portaudio/src/common/pa_ringbuffer.c')
-rw-r--r--pd/portaudio/src/common/pa_ringbuffer.c156
1 files changed, 49 insertions, 107 deletions
diff --git a/pd/portaudio/src/common/pa_ringbuffer.c b/pd/portaudio/src/common/pa_ringbuffer.c
index f4e1201a..ad9e2ae5 100644
--- a/pd/portaudio/src/common/pa_ringbuffer.c
+++ b/pd/portaudio/src/common/pa_ringbuffer.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_ringbuffer.c 1240 2007-07-17 13:05:07Z bjornroche $
+ * $Id: pa_ringbuffer.c 1346 2008-02-20 10:09:20Z rossb $
* Portable Audio I/O Library
* Ring Buffer utility.
*
@@ -7,6 +7,8 @@
* modified for SMP safety on Mac OS X by Bjorn Roche
* modified for SMP safety on Linux by Leland Lucius
* also, allowed for const where possible
+ * modified for multiple-byte-sized data elements by Sven Fischer
+ *
* Note that this is safe only for a single-thread reader and a
* single-thread writer.
*
@@ -55,93 +57,33 @@
#include <math.h>
#include "pa_ringbuffer.h"
#include <string.h>
-
-/****************
- * First, we'll define some memory barrier primitives based on the system.
- * right now only OS X, FreeBSD, and Linux are supported. In addition to providing
- * memory barriers, these functions should ensure that data cached in registers
- * is written out to cache where it can be snooped by other CPUs. (ie, the volatile
- * keyword should not be required)
- *
- * the primitives that must be defined are:
- *
- * PaUtil_FullMemoryBarrier()
- * PaUtil_ReadMemoryBarrier()
- * PaUtil_WriteMemoryBarrier()
- *
- ****************/
-
-#if defined(__APPLE__)
-# include <libkern/OSAtomic.h>
- /* Here are the memory barrier functions. Mac OS X only provides
- full memory barriers, so the three types of barriers are the same,
- however, these barriers are superior to compiler-based ones. */
-# define PaUtil_FullMemoryBarrier() OSMemoryBarrier()
-# define PaUtil_ReadMemoryBarrier() OSMemoryBarrier()
-# define PaUtil_WriteMemoryBarrier() OSMemoryBarrier()
-#elif defined(__GNUC__)
- /* GCC >= 4.1 has built-in intrinsics. We'll use those */
-# if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
-# define PaUtil_FullMemoryBarrier() __sync_synchronize()
-# define PaUtil_ReadMemoryBarrier() __sync_synchronize()
-# define PaUtil_WriteMemoryBarrier() __sync_synchronize()
- /* as a fallback, GCC understands volatile asm and "memory" to mean it
- * should not reorder memory read/writes */
-# elif defined( __PPC__ )
-# define PaUtil_FullMemoryBarrier() asm volatile("sync":::"memory")
-# define PaUtil_ReadMemoryBarrier() asm volatile("sync":::"memory")
-# define PaUtil_WriteMemoryBarrier() asm volatile("sync":::"memory")
-# elif defined( __i386__ ) || defined( __i486__ ) || defined( __i586__ ) || defined( __i686__ ) || defined( __x86_64__ )
-# define PaUtil_FullMemoryBarrier() asm volatile("mfence":::"memory")
-# define PaUtil_ReadMemoryBarrier() asm volatile("lfence":::"memory")
-# define PaUtil_WriteMemoryBarrier() asm volatile("sfence":::"memory")
-# else
-# ifdef ALLOW_SMP_DANGERS
-# warning Memory barriers not defined on this system or system unknown
-# warning For SMP safety, you should fix this.
-# define PaUtil_FullMemoryBarrier()
-# define PaUtil_ReadMemoryBarrier()
-# define PaUtil_WriteMemoryBarrier()
-# else
-# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
-# endif
-# endif
-#else
-# ifdef ALLOW_SMP_DANGERS
-# warning Memory barriers not defined on this system or system unknown
-# warning For SMP safety, you should fix this.
-# define PaUtil_FullMemoryBarrier()
-# define PaUtil_ReadMemoryBarrier()
-# define PaUtil_WriteMemoryBarrier()
-# else
-# error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
-# endif
-#endif
+#include "pa_memorybarrier.h"
/***************************************************************************
* Initialize FIFO.
- * numBytes must be power of 2, returns -1 if not.
+ * elementCount must be power of 2, returns -1 if not.
*/
-long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long numBytes, void *dataPtr )
+long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long elementSizeBytes, long elementCount, void *dataPtr )
{
- if( ((numBytes-1) & numBytes) != 0) return -1; /* Not Power of two. */
- rbuf->bufferSize = numBytes;
+ if( ((elementCount-1) & elementCount) != 0) return -1; /* Not Power of two. */
+ rbuf->bufferSize = elementCount;
rbuf->buffer = (char *)dataPtr;
PaUtil_FlushRingBuffer( rbuf );
- rbuf->bigMask = (numBytes*2)-1;
- rbuf->smallMask = (numBytes)-1;
+ rbuf->bigMask = (elementCount*2)-1;
+ rbuf->smallMask = (elementCount)-1;
+ rbuf->elementSizeBytes = elementSizeBytes;
return 0;
}
/***************************************************************************
-** Return number of bytes available for reading. */
+** Return number of elements available for reading. */
long PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf )
{
PaUtil_ReadMemoryBarrier();
return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
}
/***************************************************************************
-** Return number of bytes available for writing. */
+** Return number of elements available for writing. */
long PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf )
{
/* Since we are calling PaUtil_GetRingBufferReadAvailable, we don't need an aditional MB */
@@ -159,126 +101,126 @@ void PaUtil_FlushRingBuffer( PaUtilRingBuffer *rbuf )
** Get address of region(s) to which we can write data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
-** Returns room available to be written or numBytes, whichever is smaller.
+** Returns room available to be written or elementCount, whichever is smaller.
*/
-long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long numBytes,
+long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long elementCount,
void **dataPtr1, long *sizePtr1,
void **dataPtr2, long *sizePtr2 )
{
long index;
long available = PaUtil_GetRingBufferWriteAvailable( rbuf );
- if( numBytes > available ) numBytes = available;
+ if( elementCount > available ) elementCount = available;
/* Check to see if write is not contiguous. */
index = rbuf->writeIndex & rbuf->smallMask;
- if( (index + numBytes) > rbuf->bufferSize )
+ if( (index + elementCount) > rbuf->bufferSize )
{
/* Write data in two blocks that wrap the buffer. */
long firstHalf = rbuf->bufferSize - index;
- *dataPtr1 = &rbuf->buffer[index];
+ *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
*sizePtr1 = firstHalf;
*dataPtr2 = &rbuf->buffer[0];
- *sizePtr2 = numBytes - firstHalf;
+ *sizePtr2 = elementCount - firstHalf;
}
else
{
- *dataPtr1 = &rbuf->buffer[index];
- *sizePtr1 = numBytes;
+ *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+ *sizePtr1 = elementCount;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
- return numBytes;
+ return elementCount;
}
/***************************************************************************
*/
-long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long numBytes )
+long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long elementCount )
{
/* we need to ensure that previous writes are seen before we update the write index */
PaUtil_WriteMemoryBarrier();
- return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask;
+ return rbuf->writeIndex = (rbuf->writeIndex + elementCount) & rbuf->bigMask;
}
/***************************************************************************
** Get address of region(s) from which we can read data.
** If the region is contiguous, size2 will be zero.
** If non-contiguous, size2 will be the size of second region.
-** Returns room available to be written or numBytes, whichever is smaller.
+** Returns room available to be written or elementCount, whichever is smaller.
*/
-long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long numBytes,
+long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long elementCount,
void **dataPtr1, long *sizePtr1,
void **dataPtr2, long *sizePtr2 )
{
long index;
long available = PaUtil_GetRingBufferReadAvailable( rbuf );
- if( numBytes > available ) numBytes = available;
+ if( elementCount > available ) elementCount = available;
/* Check to see if read is not contiguous. */
index = rbuf->readIndex & rbuf->smallMask;
- if( (index + numBytes) > rbuf->bufferSize )
+ if( (index + elementCount) > rbuf->bufferSize )
{
/* Write data in two blocks that wrap the buffer. */
long firstHalf = rbuf->bufferSize - index;
- *dataPtr1 = &rbuf->buffer[index];
+ *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
*sizePtr1 = firstHalf;
*dataPtr2 = &rbuf->buffer[0];
- *sizePtr2 = numBytes - firstHalf;
+ *sizePtr2 = elementCount - firstHalf;
}
else
{
- *dataPtr1 = &rbuf->buffer[index];
- *sizePtr1 = numBytes;
+ *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+ *sizePtr1 = elementCount;
*dataPtr2 = NULL;
*sizePtr2 = 0;
}
- return numBytes;
+ return elementCount;
}
/***************************************************************************
*/
-long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long numBytes )
+long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long elementCount )
{
/* we need to ensure that previous writes are always seen before updating the index. */
PaUtil_WriteMemoryBarrier();
- return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask;
+ return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask;
}
/***************************************************************************
-** Return bytes written. */
-long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long numBytes )
+** Return elements written. */
+long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long elementCount )
{
long size1, size2, numWritten;
void *data1, *data2;
- numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+ numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
if( size2 > 0 )
{
- memcpy( data1, data, size1 );
- data = ((char *)data) + size1;
- memcpy( data2, data, size2 );
+ memcpy( data1, data, size1*rbuf->elementSizeBytes );
+ data = ((char *)data) + size1*rbuf->elementSizeBytes;
+ memcpy( data2, data, size2*rbuf->elementSizeBytes );
}
else
{
- memcpy( data1, data, size1 );
+ memcpy( data1, data, size1*rbuf->elementSizeBytes );
}
PaUtil_AdvanceRingBufferWriteIndex( rbuf, numWritten );
return numWritten;
}
/***************************************************************************
-** Return bytes read. */
-long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long numBytes )
+** Return elements read. */
+long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long elementCount )
{
long size1, size2, numRead;
void *data1, *data2;
- numRead = PaUtil_GetRingBufferReadRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );
+ numRead = PaUtil_GetRingBufferReadRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
if( size2 > 0 )
{
- memcpy( data, data1, size1 );
- data = ((char *)data) + size1;
- memcpy( data, data2, size2 );
+ memcpy( data, data1, size1*rbuf->elementSizeBytes );
+ data = ((char *)data) + size1*rbuf->elementSizeBytes;
+ memcpy( data, data2, size2*rbuf->elementSizeBytes );
}
else
{
- memcpy( data, data1, size1 );
+ memcpy( data, data1, size1*rbuf->elementSizeBytes );
}
PaUtil_AdvanceRingBufferReadIndex( rbuf, numRead );
return numRead;