libASPL
Loading...
Searching...
No Matches
aspl::DoubleBuffer< T > Class Template Reference

Doubly-buffered value with non-blocking read and blocking write. More...

#include <aspl/DoubleBuffer.hpp>

Classes

class  ReadLock
 Read lock. More...
 

Public Member Functions

 DoubleBuffer (const T &value)
 Initialize buffer with given value.
 
 DoubleBuffer (T &&value=T())
 Initialize buffer with given value.
 
 DoubleBuffer (const DoubleBuffer &)=delete
 
DoubleBufferoperator= (const DoubleBuffer &)=delete
 
ReadLock GetReadLock () const
 Get locked read-only reference to the value. Non-blocking and lock-free, see ReadLock.
 
Get () const
 Get copy of the value. Non-blocking and lock-free, see ReadLock.
 
template<typename TT >
void Set (TT &&value)
 Set value.
 

Friends

class ReadLock
 

Detailed Description

template<typename T>
class aspl::DoubleBuffer< T >

Doubly-buffered value with non-blocking read and blocking write.

Logically, this is a single-value container, which has getter and setter with the following characteristics:

  • getters are running concurrently, and setters are serialized
  • setter is blocking; it may be blocked by both getters and setters, but in the average case only by setters
  • getter is non-blocking and lock-free; it does not block if a setter thread is suspended in the middle
  • getter is not wait-free though; if setters are called too frequently and have higher priority, then getter may spin until it has a chance to cut in between
  • sequential consistency is provided; after a setter returns, it's guaranteed that subsequent getters will observe up-to-date value

Physically container is implemented as two copies of the value:

  • one copy is read-only and used by getters (concurrently)
  • another one is for setters; basically, the setter updates its copy while it's not visible to getters, waits until all getter using another copy finish, and switches the copies

The algorithm is optimized for the following use case:

  • getters are frequent and setters are infrequent
  • the value is not very large and it's acceptable to make extra copies

The value stored in the double buffer is immutable after it's set. To change the value, you need to call the getter, make a copy, modify it, and pass it to the setter.

The value should have public default and copy constructors. If it also has move constructor, it can be used in setter.

If the value has non-trivial destructor, before setter returns, it waits until the previously used value is not accessed by readers anymore and invokes destructor for the old value.

Typical reader looks like the following:

...
{
auto readLock = fooBuf.GetReadLock();
const T& fooValue = readLock.GetReference();
// safe read-only access to fooValue until block end
}
const T & GetReference() const
Get read-only reference to the value. The reference may be used until read lock destructor is called....
Doubly-buffered value with non-blocking read and blocking write.
ReadLock GetReadLock() const
Get locked read-only reference to the value. Non-blocking and lock-free, see ReadLock.

Or, if the reader is okay to call the copy constructor:

...
T fooValue = fooBuf.Get();
T Get() const
Get copy of the value. Non-blocking and lock-free, see ReadLock.

Typical writer looks like this:

...
T fooValue = fooBuf.Get();
// modify fooValue
fooBuf.Set(std::move(fooValue));
void Set(TT &&value)
Set value.
See also
ReadLock.

Definition at line 95 of file DoubleBuffer.hpp.

Constructor & Destructor Documentation

◆ DoubleBuffer() [1/2]

template<typename T >
aspl::DoubleBuffer< T >::DoubleBuffer ( const T & value)
inlineexplicit

Initialize buffer with given value.

Definition at line 197 of file DoubleBuffer.hpp.

◆ DoubleBuffer() [2/2]

template<typename T >
aspl::DoubleBuffer< T >::DoubleBuffer ( T && value = T())
inlineexplicit

Initialize buffer with given value.

Definition at line 203 of file DoubleBuffer.hpp.

Member Function Documentation

◆ Get()

template<typename T >
T aspl::DoubleBuffer< T >::Get ( ) const
inline

Get copy of the value. Non-blocking and lock-free, see ReadLock.

Definition at line 222 of file DoubleBuffer.hpp.

◆ GetReadLock()

template<typename T >
ReadLock aspl::DoubleBuffer< T >::GetReadLock ( ) const
inline

Get locked read-only reference to the value. Non-blocking and lock-free, see ReadLock.

Definition at line 215 of file DoubleBuffer.hpp.

◆ Set()

template<typename T >
template<typename TT >
void aspl::DoubleBuffer< T >::Set ( TT && value)
inline

Set value.

Blocks until all getters, invoked before this call, are finished. Concurrent setter calls are serialized.

It is guaranteed that if a getter is called after a setter returns, the getter will observe the updated value.

The value is either copied or moved into the internal buffer, depending on whether an lvalue or rvalue is passed.

Definition at line 240 of file DoubleBuffer.hpp.

Friends And Related Symbol Documentation

◆ ReadLock

template<typename T >
friend class ReadLock
friend

Definition at line 303 of file DoubleBuffer.hpp.


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