27template <
typename T, std::
size_t Capacity = 256>
29 static_assert((Capacity & (Capacity - 1)) == 0,
"Capacity must be a power of 2");
30 static_assert(Capacity >= 2,
"Capacity must be at least 2");
31 static_assert(std::is_trivially_copyable_v<T>,
"ShmMpscQueue value type T must be trivially copyable for shared memory safety.");
38 alignas(64) std::atomic<std::size_t>
sequence{0};
39 alignas(
alignof(T)) uint8_t
storage[
sizeof(T)]{};
41 [[nodiscard]] T*
ptr() noexcept
43 return reinterpret_cast<T*
>(
storage);
46 [[nodiscard]]
const T*
ptr() const noexcept
48 return reinterpret_cast<const T*
>(
storage);
67 explicit ShmMpscQueue(
void* mappedAddress,
bool initializeMemory =
false) noexcept
69 bind(mappedAddress, initializeMemory);
75 void bind(
void* mappedAddress,
bool initializeMemory =
false) noexcept
77 _layout =
static_cast<Layout*
>(mappedAddress);
78 if (_layout && initializeMemory) {
83 _layout->
enqueuePos.store(0, std::memory_order_relaxed);
84 _layout->
dequeuePos.store(0, std::memory_order_relaxed);
86 for (std::size_t i = 0; i < Capacity; ++i) {
87 _layout->
cells[i].
sequence.store(i, std::memory_order_relaxed);
99 [[nodiscard]]
bool isValid() const noexcept
113 template <
typename U>
120 Cell* cell =
nullptr;
121 std::size_t pos = _layout->
enqueuePos.load(std::memory_order_relaxed);
125 const std::size_t seq = cell->
sequence.load(std::memory_order_acquire);
126 const intptr_t dif =
static_cast<intptr_t
>(seq) -
static_cast<intptr_t
>(pos);
129 if (_layout->
enqueuePos.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed)) {
132 }
else if (dif < 0) {
136 pos = _layout->
enqueuePos.load(std::memory_order_relaxed);
141 if constexpr (std::is_trivially_copyable_v<T>) {
142 std::memcpy(cell->
storage, &item,
sizeof(T));
144 new (cell->
storage) T(std::forward<U>(item));
147 cell->
sequence.store(pos + 1, std::memory_order_release);
160 std::size_t pos = _layout->
dequeuePos.load(std::memory_order_relaxed);
162 const std::size_t seq = cell->
sequence.load(std::memory_order_acquire);
163 const intptr_t dif =
static_cast<intptr_t
>(seq) -
static_cast<intptr_t
>(pos + 1);
170 if constexpr (std::is_trivially_copyable_v<T>) {
171 std::memcpy(&outItem, cell->
storage,
sizeof(T));
173 outItem = std::move(*cell->
ptr());
177 cell->
sequence.store(pos + Capacity, std::memory_order_release);
178 _layout->
dequeuePos.store(pos + 1, std::memory_order_relaxed);
183 [[nodiscard]]
bool empty() const noexcept
185 if (!_layout)
return true;
186 const std::size_t pos = _layout->
dequeuePos.load(std::memory_order_relaxed);
188 const std::size_t seq = cell->
sequence.load(std::memory_order_acquire);
189 return static_cast<intptr_t
>(seq) -
static_cast<intptr_t
>(pos + 1) < 0;
193 [[nodiscard]]
constexpr std::size_t
capacity() const noexcept
199 Layout* _layout{
nullptr};
Lock-free, zero-allocation multi-producer single-consumer ring buffer layout for shared memory....
Definition ShmMpscQueue.hpp:28
static constexpr std::size_t BufferCapacity
Definition ShmMpscQueue.hpp:34
void bind(void *mappedAddress, bool initializeMemory=false) noexcept
Bind to a mapped shared memory region.
Definition ShmMpscQueue.hpp:75
bool empty() const noexcept
Check if queue is currently empty.
Definition ShmMpscQueue.hpp:183
bool tryPush(U &&item) noexcept
Lock-free push into shared memory queue (multi-producer safe).
Definition ShmMpscQueue.hpp:114
static constexpr std::size_t requiredMemorySize() noexcept
Required byte size of the shared memory layout.
Definition ShmMpscQueue.hpp:93
ShmMpscQueue(void *mappedAddress, bool initializeMemory=false) noexcept
Construct queue bound to a mapped shared memory address.
Definition ShmMpscQueue.hpp:67
bool tryPop(T &outItem) noexcept
Lock-free pop from shared memory queue (single-consumer safe).
Definition ShmMpscQueue.hpp:154
static constexpr std::size_t BufferMask
Definition ShmMpscQueue.hpp:35
constexpr std::size_t capacity() const noexcept
Get configured capacity of the queue.
Definition ShmMpscQueue.hpp:193
bool isValid() const noexcept
Validate that the mapped shared memory contains a compatible ShmMpscQueue header.
Definition ShmMpscQueue.hpp:99
Definition DomainSocket.hpp:35
constexpr uint32_t CORIUM_SHM_MAGIC
Definition ShmMpscQueue.hpp:20
constexpr uint32_t CORIUM_SHM_VERSION
Definition ShmMpscQueue.hpp:21
Definition ShmMpscQueue.hpp:37
std::atomic< std::size_t > sequence
Definition ShmMpscQueue.hpp:38
T * ptr() noexcept
Definition ShmMpscQueue.hpp:41
uint8_t storage[sizeof(T)]
Definition ShmMpscQueue.hpp:39
const T * ptr() const noexcept
Definition ShmMpscQueue.hpp:46
Definition ShmMpscQueue.hpp:52
std::atomic< std::size_t > enqueuePos
Definition ShmMpscQueue.hpp:58
std::atomic< std::size_t > dequeuePos
Definition ShmMpscQueue.hpp:59
uint32_t elementSize
Definition ShmMpscQueue.hpp:56
uint32_t version
Definition ShmMpscQueue.hpp:54
Cell cells[Capacity]
Definition ShmMpscQueue.hpp:61
uint32_t capacity
Definition ShmMpscQueue.hpp:55
uint32_t magic
Definition ShmMpscQueue.hpp:53