Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::runtime::TripleBuffer< T > Class Template Reference

Lock-free triple buffer for publishing the latest value from a writer thread to a reader thread without blocking either side. More...

#include <triple_buffer.hpp>

Public Member Functions

 TripleBuffer ()=default
 TripleBuffer (const T &initial)
 Initialize all three internal buffers with the same value.
void write (const T &value) noexcept(std::is_nothrow_copy_assignable_v< T >)
 Publish a new value from the writer thread.
template<typename Fill>
void write_with (Fill &&fill) noexcept(noexcept(std::declval< Fill >()(std::declval< T & >())))
 Fill and publish the writer-owned back buffer in place.
const T & read () noexcept
 Read the latest published value from the reader thread.

Detailed Description

template<typename T>
class pulp::runtime::TripleBuffer< T >

Lock-free triple buffer for publishing the latest value from a writer thread to a reader thread without blocking either side.

Use case: swapping large config blobs (wavetable data, IR buffers, meter snapshots) from the main thread to the audio thread. The writer never blocks, and the reader always gets the most recently completed write. No allocation on the read path.

Template Parameters
TValue type. Must be default-constructible and assignable.
// Audio thread (writer):
meters.write(current_levels);
// UI thread (reader):
const auto& levels = meters.read();
draw_meter(levels);
const T & read() noexcept
Read the latest published value from the reader thread.
Definition triple_buffer.hpp:88
void write(const T &value) noexcept(std::is_nothrow_copy_assignable_v< T >)
Publish a new value from the writer thread.
Definition triple_buffer.hpp:62
Note
Exactly one writer and one reader at a time. The writer owns its back slot index and the reader its front slot index as plain, unsynchronized state, so successive write() calls must be ordered by happens-before (one thread, or a mutex / host dispatch handoff when the writer role moves between threads), and likewise for read(). Two overlapping writers or two overlapping readers corrupt slot ownership permanently, not just one frame. Debug builds assert when two calls in the same role overlap.

Constructor & Destructor Documentation

◆ TripleBuffer() [1/2]

template<typename T>
pulp::runtime::TripleBuffer< T >::TripleBuffer ( )
default

◆ TripleBuffer() [2/2]

template<typename T>
pulp::runtime::TripleBuffer< T >::TripleBuffer ( const T & initial)
inlineexplicit

Initialize all three internal buffers with the same value.

Member Function Documentation

◆ read()

template<typename T>
const T & pulp::runtime::TripleBuffer< T >::read ( )
inlinenoexcept

Read the latest published value from the reader thread.

If new data is available, atomically swaps middle to front first.

Returns
Const reference to the front buffer. Valid until the next read().

◆ write()

template<typename T>
void pulp::runtime::TripleBuffer< T >::write ( const T & value)
inlinenoexcept

Publish a new value from the writer thread.

Writes into the back buffer, then atomically swaps it to middle. Costs one copy and one atomic exchange; never blocks or retries.

◆ write_with()

template<typename T>
template<typename Fill>
void pulp::runtime::TripleBuffer< T >::write_with ( Fill && fill)
inlinenoexcept

Fill and publish the writer-owned back buffer in place.

This is useful for prepared payloads whose assignment through a temporary could allocate. The callback runs only on the writer thread and must not retain the reference. If it throws, no value is published.


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