Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
Loading...
Searching...
No Matches
spsc_ring_buffer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Roc Streaming authors
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 */
8
9//! @file roc_core/spsc_ring_buffer.h
10//! @brief Single-producer single-consumer circular buffer of copyable objects.
11
12#ifndef ROC_CORE_SPSC_RING_BUFFER_H_
13#define ROC_CORE_SPSC_RING_BUFFER_H_
14
15#include "roc_core/iarena.h"
18#include "roc_core/stddefs.h"
19
20namespace roc {
21namespace core {
22
23//! Thread-safe lock-free single-producer single-consumer
24//! circular buffer of copyable objects.
25//!
26//! Allows access from two concurrent threads: writer and reader.
27//! Both writer and reader are never blocked.
28//! Provides sequential consistency.
29//!
30//! @tparam T defines object type, it should be copyable.
31//!
32//! Implemented on top of SpscByteBuffer.
33template <class T> class SpscRingBuffer : public NonCopyable<> {
34public:
35 //! Initialize.
37 : byte_buf_(arena, sizeof(T), n_elements) {
38 }
39
40 //! Deinitialize.
42 while (void* ptr = byte_buf_.begin_read()) {
43 static_cast<T*>(ptr)->~T();
44 byte_buf_.end_read();
45 }
46 }
47
48 //! Check that allocation succeeded.
49 bool is_valid() const {
50 return byte_buf_.is_valid();
51 }
52
53 //! Check if buffer is empty.
54 bool is_empty() const {
55 return byte_buf_.is_empty();
56 }
57
58 //! Append element to the end of the buffer.
59 //! If buffer is full, drops element and returns false.
60 //! Should be called from writer thread.
61 //! Lock-free.
62 bool push_back(const T& element) {
63 void* ptr = byte_buf_.begin_write();
64 if (!ptr) {
65 return false;
66 }
67
68 new (ptr) T(element);
69
70 byte_buf_.end_write();
71
72 return true;
73 }
74
75 //! Fetch element from the beginning of the buffer.
76 //! If buffer is empty, returns false.
77 //! Should be called from reader thread.
78 //! Lock-free.
79 bool pop_front(T& element) {
80 void* ptr = byte_buf_.begin_read();
81 if (!ptr) {
82 element = T();
83 return false;
84 }
85
86 element = *static_cast<T*>(ptr);
87 static_cast<T*>(ptr)->~T();
88
89 byte_buf_.end_read();
90
91 return true;
92 }
93
94private:
95 SpscByteBuffer byte_buf_;
96};
97
98} // namespace core
99} // namespace roc
100
101#endif // ROC_CORE_SPSC_RING_BUFFER_H_
Memory arena interface.
Definition iarena.h:23
Base class for non-copyable objects.
Definition noncopyable.h:23
Shared ownership intrusive pointer.
Definition shared_ptr.h:32
Thread-safe lock-free single-producer single-consumer circular buffer of byte chunks.
void end_write()
End writing of a chunk. Should be called if and only if begin_write() returned non-NULL....
uint8_t * begin_read()
Begin reading of a chunk. If buffer is empty, returns NULL. Should be called from reader thread....
uint8_t * begin_write()
Begin writing of a chunk. If buffer is full, returns NULL. Should be called from writer thread....
bool is_empty() const
Check if buffer is empty.
bool is_valid() const
Check that initial allocation succeeded.
void end_read()
End reading of a chunk. Should be called if and only if begin_read() returned non-NULL....
Thread-safe lock-free single-producer single-consumer circular buffer of copyable objects.
SpscRingBuffer(IArena &arena, size_t n_elements)
Initialize.
bool push_back(const T &element)
Append element to the end of the buffer. If buffer is full, drops element and returns false....
bool pop_front(T &element)
Fetch element from the beginning of the buffer. If buffer is empty, returns false....
bool is_valid() const
Check that allocation succeeded.
bool is_empty() const
Check if buffer is empty.
Memory arena interface.
Root namespace.
Non-copyable object.
Single-producer single-consumer circular buffer of byte chunks.
Commonly used types and functions.