etl/docs/IO/buffer_descriptors.md
John Wellbelove 09af946a8f Added more documentation for chrono classes
Updated callouts
2026-04-13 10:59:19 +02:00

6.1 KiB

title
buffer_descriptors

{{< callout >}} Header: buffer_descriptors.h
Since: All versions
{{< /callout >}}

A set of descriptors to a collection of buffers.

template <typename TBuffer,      // The type to store in the buffer.
          TSize    BUFFER_SIZE,  // The size of each buffer.
          size_t   N_BUFFERS,    // The total number of buffers.
          typename TFlag = bool> // The 'in use' flag type.
class buffer_descriptors

The type used for the 'in use' flag depends on how the buffer descriptors class is used. For interrupts and multi-threaded code, either the flag type must force a fence (by using an atomic type) or the calls to allocate and release must ensure that they are not re-ordered by the compiler or processor.

Member types

Type
value_type The type that is stored in the buffers
size_type An unsigned integral type
flag_type
pointer
descriptor A nested class that encapsulates the details of an individual buffer
notification A nested class that is sent to the user defined callback function
callback_type etl::delegate<void(notification)>

Static Constants

Value
N_BUFFERS The number of buffers that the buffer descriptor controls
BUFFER_SIZE The number of elements in each buffer

Constructors

buffer_descriptors(pointer pbuffers)

Description
Construct with a pointer to the start of the buffers to control. This storage should be contiguous and large enough to hold N_BUFFERS.


buffer_descriptors(pointer pbuffers, const callback_type& callback)

Description
Construct with a pointer to the start of the buffers to control and the callback.

Member functions

void set_callback(const callback_type& callback)

Description
Set the callback for notification.


bool is_valid() const

Description
Returns true if class contains valid buffers.


void notify(notification n)

Description
Calls the user defined callback with the descriptor and buffer size. Used when the buffer has been filled and is ready for processing via the callback.


descriptor allocate()

Description
Returns a new descriptor. If all descriptors are in use then the descriptor will be invalid.


descriptor allocate(value_type fill)

Description
Returns a new descriptor and fills the buffer with fill. If all descriptors are in use then the descriptor will be invalid.


void clear()

Description
Clears by releasing all allocated descriptors.

descriptor

Description
A nested class that encapsulates the details of an individual buffer.


const size_type MAX_SIZE

Description
The maximum size of the buffer.


descriptor()

Description
Default constructor.


ETL_CONSTEXPR pointer data() const

Description
Returns a pointer to the start of the buffer.


ETL_CONSTEXPR size_type max_size() const

Description
Returns the maximum size of the buffer.


bool is_valid() const

Description
Returns true if the descriptor points to a valid buffer.


bool is_allocated() const

Description
Returns true if the descriptor has been allocated.


bool is_released() const

Description
Returns true if the descriptor has been released.


void release()

Description
Releases the descriptor.


notification

Description
A nested class that is sent to the user defined callback function.


notification()

Description
Default contructor. Initialises to a default constructed descriptor and a count of zero.


notification(descriptor desc, size_t count)

Description
Construct with the supplied parameters.


descriptor get_descriptor() const

Description
Gets the descriptor.


size_t get_count() const

Description
Gets the count.

Example

Very simplified.
Assumes that there is a DMA driver class called DMA.
In the real world the descriptor would be queued in the callback and handled in a foreground thread.
The handler in the thread would release the descriptor.

constexpr size_t BUFFER_SIZE = 256U;
constexpr size_t N_BUFFERS   = 8U;

// Define the buffer descriptors type.
using BD = etl::buffer_descriptors<char, BUFFER_SIZE, N_BUFFERS, std::atomic_char>;

// The buffers to use with it.
char buffers[N_BUFFERS][BUFFER_SIZE];

// The function to call when a buffer is ready.
void Callback(BD::notification notification)
{
  // Process the buffer in the descriptor here.
  ProcessData(notification.get_descriptor().data(), notification.get_count());

  // Finished with the descriptor now, so release it back.
  notification.get_descriptor().release();
}

// Create the buffer_descriptors.
BD bd(&buffers[0][0], BD::callback_type::create<Callback>());

// The current dma descriptor.
BD::descriptor dma_descriptor;

// An object that controls the DMA.
DMA dma;

// Call to start the DMA.
void DMAStart()
{
  // Get a new descriptor.
  dma_descriptor = bd.allocate();

  if (dma_descriptor.is_valid())
  {
    // Link the buffer to the DMA channel.
    dma.Start(dma_descriptor.data());
  }
  else
  {
    // No valid descriptors available.
    LogError("No Descriptor Available");
  }
}

// Called when the DMA has completed (usually an interrupt).
void DMAComplete()
{
  // DMA is complete. Notify the callback.
  bd.notify(BD::notification(dma_descriptor, dma.GetTransferredSize()));
}