Diff of /portaudio/src/common/pa_ringbuffer.c [638b14] .. [6d9958] Maximize Restore

  Switch to side-by-side view

--- a/portaudio/src/common/pa_ringbuffer.c
+++ b/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 )
-{
-    if( ((numBytes-1) & numBytes) != 0) return -1; /* Not Power of two. */
-    rbuf->bufferSize = numBytes;
+long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long elementSizeBytes, long elementCount, void *dataPtr )
+{
+    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 @@
 ** 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.
-*/
-long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long numBytes,
+** Returns room available to be written or elementCount, whichever is smaller.
+*/
+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;
-    }
-    else
-    {
-        *dataPtr1 = &rbuf->buffer[index];
-        *sizePtr1 = numBytes;
+        *sizePtr2 = elementCount - firstHalf;
+    }
+    else
+    {
+        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+        *sizePtr1 = elementCount;
         *dataPtr2 = NULL;
         *sizePtr2 = 0;
     }
-    return numBytes;
-}
-
-
-/***************************************************************************
-*/
-long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long numBytes )
+    return elementCount;
+}
+
+
+/***************************************************************************
+*/
+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.
-*/
-long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long numBytes,
+** Returns room available to be written or elementCount, whichever is smaller.
+*/
+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;
-    }
-    else
-    {
-        *dataPtr1 = &rbuf->buffer[index];
-        *sizePtr1 = numBytes;
+        *sizePtr2 = elementCount - firstHalf;
+    }
+    else
+    {
+        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+        *sizePtr1 = elementCount;
         *dataPtr2 = NULL;
         *sizePtr2 = 0;
     }
-    return numBytes;
-}
-/***************************************************************************
-*/
-long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long numBytes )
+    return elementCount;
+}
+/***************************************************************************
+*/
+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 bytes written. */
-long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long numBytes )
+    return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask;
+}
+
+/***************************************************************************
+** 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 );
-    }
-    else
-    {
-        memcpy( data1, data, size1 );
+        memcpy( data1, data, size1*rbuf->elementSizeBytes );
+        data = ((char *)data) + size1*rbuf->elementSizeBytes;
+        memcpy( data2, data, size2*rbuf->elementSizeBytes );
+    }
+    else
+    {
+        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 );
-    }
-    else
-    {
-        memcpy( data, data1, size1 );
+        memcpy( data, data1, size1*rbuf->elementSizeBytes );
+        data = ((char *)data) + size1*rbuf->elementSizeBytes;
+        memcpy( data, data2, size2*rbuf->elementSizeBytes );
+    }
+    else
+    {
+        memcpy( data, data1, size1*rbuf->elementSizeBytes );
     }
     PaUtil_AdvanceRingBufferReadIndex( rbuf, numRead );
     return numRead;