Audacity  3.0.3
Classes | Public Member Functions | Private Attributes | List of all members
MessageBuffer< Data > Class Template Reference

Communicate data atomically from one writer thread to one reader. More...

#include <PlaybackSchedule.h>

Inheritance diagram for MessageBuffer< Data >:
[legend]
Collaboration diagram for MessageBuffer< Data >:
[legend]

Classes

struct  UpdateSlot
 

Public Member Functions

void Initialize ()
 
Data Read ()
 Move data out (if available), or else copy it out. More...
 
void Write (const Data &data)
 Copy data in. More...
 
void Write (Data &&data)
 Move data in. More...
 

Private Attributes

NonInterfering< UpdateSlotmSlots [2]
 
std::atomic< unsigned char > mLastWrittenSlot { 0 }
 

Detailed Description

template<typename Data>
class MessageBuffer< Data >

Communicate data atomically from one writer thread to one reader.

This is not a queue: it is not necessary for each write to be read. Rather loss of a message is allowed: writer may overwrite. Data must be default-constructible and either copyable or movable.

Definition at line 34 of file PlaybackSchedule.h.

Member Function Documentation

◆ Initialize()

template<typename Data >
void MessageBuffer< Data >::Initialize

Definition at line 56 of file PlaybackSchedule.h.

57 {
58  for (auto &slot : mSlots)
59  // Lock both slots first, maybe spinning a little
60  while ( slot.mBusy.exchange( true, std::memory_order_acquire ) )
61  {}
62 
63  mSlots[0].mData = {};
64  mSlots[1].mData = {};
65  mLastWrittenSlot.store( 0, std::memory_order_relaxed );
66 
67  for (auto &slot : mSlots)
68  slot.mBusy.exchange( false, std::memory_order_release );
69 }

◆ Read()

template<typename Data >
Data MessageBuffer< Data >::Read

Move data out (if available), or else copy it out.

Definition at line 72 of file PlaybackSchedule.h.

73 {
74  // Whichever slot was last written, prefer to read that.
75  auto idx = mLastWrittenSlot.load( std::memory_order_relaxed );
76  idx = 1 - idx;
77  bool wasBusy = false;
78  do {
79  // This loop is unlikely to execute twice, but it might because the
80  // producer thread is writing a slot.
81  idx = 1 - idx;
82  wasBusy = mSlots[idx].mBusy.exchange( true, std::memory_order_acquire );
83  } while ( wasBusy );
84 
85  // Copy the slot
86  auto result = std::move( mSlots[idx].mData );
87 
88  mSlots[idx].mBusy.store( false, std::memory_order_release );
89 
90  return result;
91 }

◆ Write() [1/2]

template<typename Data >
void MessageBuffer< Data >::Write ( const Data &  data)

Copy data in.

Definition at line 94 of file PlaybackSchedule.h.

95 {
96  // Whichever slot was last written, prefer to write the other.
97  auto idx = mLastWrittenSlot.load( std::memory_order_relaxed );
98  bool wasBusy = false;
99  do {
100  // This loop is unlikely to execute twice, but it might because the
101  // consumer thread is reading a slot.
102  idx = 1 - idx;
103  wasBusy = mSlots[idx].mBusy.exchange( true, std::memory_order_acquire );
104  } while ( wasBusy );
105 
106  mSlots[idx].mData = data;
107  mLastWrittenSlot.store( idx, std::memory_order_relaxed );
108 
109  mSlots[idx].mBusy.store( false, std::memory_order_release );
110 }

◆ Write() [2/2]

template<typename Data >
void MessageBuffer< Data >::Write ( Data &&  data)

Move data in.

Definition at line 113 of file PlaybackSchedule.h.

114 {
115  // Whichever slot was last written, prefer to write the other.
116  auto idx = mLastWrittenSlot.load( std::memory_order_relaxed );
117  bool wasBusy = false;
118  do {
119  // This loop is unlikely to execute twice, but it might because the
120  // consumer thread is reading a slot.
121  idx = 1 - idx;
122  wasBusy = mSlots[idx].mBusy.exchange( true, std::memory_order_acquire );
123  } while ( wasBusy );
124 
125  mSlots[idx].mData = std::move( data );
126  mLastWrittenSlot.store( idx, std::memory_order_relaxed );
127 
128  mSlots[idx].mBusy.store( false, std::memory_order_release );
129 }

Member Data Documentation

◆ mLastWrittenSlot

template<typename Data >
std::atomic<unsigned char> MessageBuffer< Data >::mLastWrittenSlot { 0 }
private

Definition at line 41 of file PlaybackSchedule.h.

◆ mSlots

template<typename Data >
NonInterfering<UpdateSlot> MessageBuffer< Data >::mSlots[2]
private

Definition at line 39 of file PlaybackSchedule.h.


The documentation for this class was generated from the following file:
MessageBuffer::mLastWrittenSlot
std::atomic< unsigned char > mLastWrittenSlot
Definition: PlaybackSchedule.h:41
MessageBuffer::mSlots
NonInterfering< UpdateSlot > mSlots[2]
Definition: PlaybackSchedule.h:39