arduino-audio-tools
Loading...
Searching...
No Matches
RingBufferSPSC< T > Class Template Referenceabstract

Lock-free Single-Producer Single-Consumer ring buffer. More...

#include <CodecOpusOgg.h>

Inheritance diagram for RingBufferSPSC< T >:
BaseBuffer< uint8_t > BaseBuffer< uint8_t >

Public Member Functions

 RingBufferSPSC ()=default
 RingBufferSPSC ()=default
 RingBufferSPSC (const RingBufferSPSC &)=delete
 RingBufferSPSC (const RingBufferSPSC &)=delete
 RingBufferSPSC (size_t capacity)
 RingBufferSPSC (size_t capacity)
 ~RingBufferSPSC () override=default
 ~RingBufferSPSC () override=default
T * address () override
 returns the address of the start of the physical read buffer
T * address () override
 returns the address of the start of the physical read buffer
int available () override
 provides the number of entries that are available to read
int available () override
 provides the number of entries that are available to read
int availableForWrite () override
 provides the number of entries that are available to write
int availableForWrite () override
 provides the number of entries that are available to write
virtual int bufferCountEmpty ()
 Provides the number of entries that are available to write: -1 does not apply.
virtual int bufferCountFilled ()
 Provides the number of entries that are available to read: -1 does not apply.
void clear ()
 same as reset
virtual int clearArray (int len)
 Removes the next len entries.
virtual void flush ()
virtual float freePercent ()
 Returns the free space of the buffer in %.
bool isEmpty ()
virtual bool isFull ()
 checks if the buffer is full
virtual float levelPercent ()
 Returns the level of the buffer in %.
RingBufferSPSC & operator= (const RingBufferSPSC &)=delete
RingBufferSPSC & operator= (const RingBufferSPSC &)=delete
virtual bool peek (uint8_t &result)=0
 peeks the actual entry from the buffer
bool peek (T &result) override
bool peek (T &result) override
virtual bool read (uint8_t &result)=0
 reads a single value
bool read (T &result) override
bool read (T &result) override
virtual int readArray (uint8_t data[], int len)
 reads multiple values
int readArray (T data[], int len) override
int readArray (T data[], int len) override
void reset () override
 clears the buffer
void reset () override
 clears the buffer
bool resize (size_t capacity) override
 Resizes the buffer if supported: returns false if not supported.
bool resize (size_t capacity) override
 Resizes the buffer if supported: returns false if not supported.
void setUsePSRAM (bool flag)
void setUsePSRAM (bool flag)
size_t size () override
size_t size () override
virtual bool write (uint8_t data)=0
 write add an entry to the buffer
bool write (T data) override
bool write (T data) override
virtual int writeArray (const uint8_t data[], int len)
 Fills the buffer data.
int writeArray (const T data[], int len) override
int writeArray (const T data[], int len) override
virtual int writeArrayOverwrite (const uint8_t data[], int len)
 Fills the buffer data and overwrites the oldest data if the buffer is full.

Detailed Description

template<typename T = uint8_t>
class audio_tools::audio_tools::RingBufferSPSC< T >

Lock-free Single-Producer Single-Consumer ring buffer.

Safe to use from two cores / contexts simultaneously only when there is exactly one writer and exactly one reader — e.g. an ISR or a second core filling the buffer while the main loop drains it (USB audio RX path on RP2040 with core-1 tud_task).

Design ──────

  • head_ is the element-count of everything ever written; only the producer writes it (release store) and the consumer reads it (acquire load).
  • tail_ is the element-count of everything ever read; only the consumer writes it (release store) and the producer reads it (acquire load).
  • No shared mutable counter between the two sides — the shared mutable state of RingBuffer<T>::_numElems is the classic data race on M0+.
  • Capacity is rounded up to the next power of two so that index masking replaces modulo and wrap-around is handled by a single bit-AND.
  • readArray / writeArray use memcpy for bulk transfers and split them at the wrap-around point, giving at most two memcpy calls per operation (T=uint8_t makes this a byte copy; for other T it's an element copy).

Not suitable for MPMC (multiple producers or consumers); use QueueLockFree for that.

Backing storage is a Vector<T>, using Vector's own default allocator (plain heap - unaffected, existing callers like the I2S/USB audio TX/RX buffers see no change at all). setUsePSRAM(true), called before the first resize(), switches it to an allocator that prefers PSRAM and falls back to the plain heap silently where PSRAM isn't available - useful for a buffer sized to soak up bursty backlogs (see e.g. PacedVideoOutput) where a few hundred KB would be far too much to ask of internal RAM but is a rounding error against multiple MB of PSRAM.

Template Parameters
TElement type. Works for any trivially-copyable T; the bulk-copy optimisation is most effective for T=uint8_t (audio streams).
Author
Phil Schatzmann

Constructor & Destructor Documentation

◆ RingBufferSPSC() [1/6]

template<typename T = uint8_t>
RingBufferSPSC ( )
default

◆ RingBufferSPSC() [2/6]

template<typename T = uint8_t>
RingBufferSPSC ( size_t capacity)
inlineexplicit

◆ ~RingBufferSPSC() [1/2]

template<typename T = uint8_t>
~RingBufferSPSC ( )
overridedefault

◆ RingBufferSPSC() [3/6]

template<typename T = uint8_t>
RingBufferSPSC ( const RingBufferSPSC< T > & )
delete

◆ RingBufferSPSC() [4/6]

template<typename T = uint8_t>
RingBufferSPSC ( )
default

◆ RingBufferSPSC() [5/6]

template<typename T = uint8_t>
RingBufferSPSC ( size_t capacity)
inlineexplicit

◆ ~RingBufferSPSC() [2/2]

template<typename T = uint8_t>
~RingBufferSPSC ( )
overridedefault

◆ RingBufferSPSC() [6/6]

template<typename T = uint8_t>
RingBufferSPSC ( const RingBufferSPSC< T > & )
delete

Member Function Documentation

◆ address() [1/2]

template<typename T = uint8_t>
T * address ( )
inlineoverridevirtual

returns the address of the start of the physical read buffer

Implements BaseBuffer< uint8_t >.

◆ address() [2/2]

template<typename T = uint8_t>
T * address ( )
inlineoverridevirtual

returns the address of the start of the physical read buffer

Implements BaseBuffer< uint8_t >.

◆ available() [1/2]

template<typename T = uint8_t>
int available ( )
inlineoverridevirtual

provides the number of entries that are available to read

Implements BaseBuffer< uint8_t >.

◆ available() [2/2]

template<typename T = uint8_t>
int available ( )
inlineoverridevirtual

provides the number of entries that are available to read

Implements BaseBuffer< uint8_t >.

◆ availableForWrite() [1/2]

template<typename T = uint8_t>
int availableForWrite ( )
inlineoverridevirtual

provides the number of entries that are available to write

Implements BaseBuffer< uint8_t >.

◆ availableForWrite() [2/2]

template<typename T = uint8_t>
int availableForWrite ( )
inlineoverridevirtual

provides the number of entries that are available to write

Implements BaseBuffer< uint8_t >.

◆ bufferCountEmpty()

virtual int bufferCountEmpty ( )
inlinevirtualinherited

Provides the number of entries that are available to write: -1 does not apply.

Reimplemented in NBuffer< T >, NBuffer< T >, NBuffer< uint8_t >, NBuffer< T >, SynchronizedNBufferRTOST< uint8_t >, and SynchronizedNBufferZephyrT< uint8_t >.

◆ bufferCountFilled()

virtual int bufferCountFilled ( )
inlinevirtualinherited

Provides the number of entries that are available to read: -1 does not apply.

Reimplemented in NBuffer< T >, NBuffer< T >, NBuffer< uint8_t >, NBuffer< T >, SynchronizedNBufferRTOST< uint8_t >, and SynchronizedNBufferZephyrT< uint8_t >.

◆ clear()

void clear ( )
inlineinherited

same as reset

◆ clearArray()

virtual int clearArray ( int len)
inlinevirtualinherited

Removes the next len entries.

Reimplemented in SingleBuffer< T >, SingleBuffer< T >, SingleBuffer< uint8_t >, and SingleBuffer< T >.

◆ flush()

virtual void flush ( )
inlinevirtualinherited

Submit any partially-filled write buffer so the reader can access it. Only meaningful for NBuffer-style block pools; no-op for ring buffers.

Reimplemented in NBuffer< T >, NBuffer< T >, NBuffer< uint8_t >, and NBuffer< T >.

◆ freePercent()

virtual float freePercent ( )
inlinevirtualinherited

Returns the free space of the buffer in %.

◆ isEmpty()

bool isEmpty ( )
inlineinherited

◆ isFull()

◆ levelPercent()

virtual float levelPercent ( )
inlinevirtualinherited

Returns the level of the buffer in %.

Reimplemented in AdaptiveResamplingBuffer.

◆ operator=() [1/2]

template<typename T = uint8_t>
RingBufferSPSC & operator= ( const RingBufferSPSC< T > & )
delete

◆ operator=() [2/2]

template<typename T = uint8_t>
RingBufferSPSC & operator= ( const RingBufferSPSC< T > & )
delete

◆ peek() [1/3]

virtual bool peek ( uint8_t & result)
pure virtualinherited

◆ peek() [2/3]

template<typename T = uint8_t>
bool peek ( T & result)
inlineoverride

◆ peek() [3/3]

template<typename T = uint8_t>
bool peek ( T & result)
inlineoverride

◆ read() [1/3]

virtual bool read ( uint8_t & result)
pure virtualinherited

◆ read() [2/3]

template<typename T = uint8_t>
bool read ( T & result)
inlineoverride

◆ read() [3/3]

template<typename T = uint8_t>
bool read ( T & result)
inlineoverride

◆ readArray() [1/3]

virtual int readArray ( uint8_t data[],
int len )
inlinevirtualinherited

◆ readArray() [2/3]

template<typename T = uint8_t>
int readArray ( T data[],
int len )
inlineoverride

◆ readArray() [3/3]

template<typename T = uint8_t>
int readArray ( T data[],
int len )
inlineoverride

◆ reset() [1/2]

template<typename T = uint8_t>
void reset ( )
inlineoverridevirtual

clears the buffer

Implements BaseBuffer< uint8_t >.

◆ reset() [2/2]

template<typename T = uint8_t>
void reset ( )
inlineoverridevirtual

clears the buffer

Implements BaseBuffer< uint8_t >.

◆ resize() [1/2]

template<typename T = uint8_t>
bool resize ( size_t bytes)
inlineoverridevirtual

Resizes the buffer if supported: returns false if not supported.

Reimplemented from BaseBuffer< uint8_t >.

◆ resize() [2/2]

template<typename T = uint8_t>
bool resize ( size_t bytes)
inlineoverridevirtual

Resizes the buffer if supported: returns false if not supported.

Reimplemented from BaseBuffer< uint8_t >.

◆ setUsePSRAM() [1/2]

template<typename T = uint8_t>
void setUsePSRAM ( bool flag)
inline

◆ setUsePSRAM() [2/2]

template<typename T = uint8_t>
void setUsePSRAM ( bool flag)
inline

◆ size() [1/2]

template<typename T = uint8_t>
size_t size ( )
inlineoverridevirtual

Implements BaseBuffer< uint8_t >.

◆ size() [2/2]

template<typename T = uint8_t>
size_t size ( )
inlineoverridevirtual

Implements BaseBuffer< uint8_t >.

◆ write() [1/3]

virtual bool write ( uint8_t data)
pure virtualinherited

◆ write() [2/3]

template<typename T = uint8_t>
bool write ( T data)
inlineoverride

◆ write() [3/3]

template<typename T = uint8_t>
bool write ( T data)
inlineoverride

◆ writeArray() [1/3]

virtual int writeArray ( const uint8_t data[],
int len )
inlinevirtualinherited

◆ writeArray() [2/3]

template<typename T = uint8_t>
int writeArray ( const T data[],
int len )
inlineoverride

◆ writeArray() [3/3]

template<typename T = uint8_t>
int writeArray ( const T data[],
int len )
inlineoverride

◆ writeArrayOverwrite()

virtual int writeArrayOverwrite ( const uint8_t data[],
int len )
inlinevirtualinherited

Fills the buffer data and overwrites the oldest data if the buffer is full.


The documentation for this class was generated from the following files: