Uncoupled communication between two objects which run in separate threads can be achieved through buffers. A buffer is placed between the two communicating objects and can store a single element. There are different types of buffers depending on the context in which they are used but they all share the same interface which supplies two functions: put and get. Three different variations have to be considered:
- fully synchronous: put and get both block the calling thread. The put call blocks when there is data already present in the buffer and get blocks when called on an empty buffer. Calling get empties the buffer.
- continuous write: get blocks on an empty buffer, put doesn't block but overwrites the current data (if present) in the buffer. The get call moves the data out of the buffer, meaning that all data is only read once.
- continuous read: the buffer is initialised with a default value. Neither put nor get block. The data in the buffer can be re-read any number of times and can always be overwritten.
The fully synchronous and continuous write buffers both store a unique element which is removed from the buffer as soon as get is called. Because of this the internal storage is implemented with a std::unique_ptr. For the continuous read buffer this is not the case so it just stores the element by value because the buffer is never empty.