1#include "mpmc_queue_base.hpp"
6#include "libxr_mem.hpp"
16 : element_size_(element_size),
18 payload_stride_(AlignUpChecked(element_size_, alignof(size_t))),
24 ASSERT(element_size_ > 0);
25 ASSERT(capacity_ > 1);
26 ASSERT(capacity_ <=
static_cast<size_t>(std::numeric_limits<SequenceDiffType>::max()));
28 const size_t payload_bytes = MultiplyChecked(payload_stride_, capacity_);
29 sequences_ =
new (std::align_val_t(
alignof(SequenceCell))) SequenceCell[capacity_];
31 payloads_ =
static_cast<std::byte*
>(
32 ::operator
new[](payload_bytes, std::align_val_t(PAYLOAD_ALLOC_ALIGN)));
34 for (
size_t index = 0; index < capacity_; ++index)
36 sequences_[index].value.store(
static_cast<SequenceType>(index),
37 std::memory_order_relaxed);
46 ::operator
delete[](payloads_, std::align_val_t(PAYLOAD_ALLOC_ALIGN));
61 SequenceType position = tail_.load(std::memory_order_relaxed);
65 SequenceCell& slot = sequences_[position % capacity_];
66 const SequenceType sequence = slot.value.load(std::memory_order_acquire);
71 if (tail_.compare_exchange_weak(position, position + 1, std::memory_order_relaxed,
72 std::memory_order_relaxed))
75 slot.value.store(position + 1, std::memory_order_release);
86 position = tail_.load(std::memory_order_relaxed);
98 SequenceType position = head_.load(std::memory_order_relaxed);
102 SequenceCell& slot = sequences_[position % capacity_];
103 const SequenceType sequence = slot.value.load(std::memory_order_acquire);
110 if (head_.compare_exchange_weak(position, position + 1, std::memory_order_relaxed,
111 std::memory_order_relaxed))
113 if (value !=
nullptr)
117 slot.value.store(position +
static_cast<SequenceType>(capacity_),
118 std::memory_order_release);
129 position = head_.load(std::memory_order_relaxed);
141 const SequenceType head_snapshot = head_.load(std::memory_order_acquire);
142 const SequenceType tail_snapshot = tail_.load(std::memory_order_acquire);
143 const SequenceType used = tail_snapshot - head_snapshot;
144 return (used <= capacity_) ? used : capacity_;
151void* MPMCQueueBase::PayloadPtr(
size_t index)
153 return payloads_ + index * payload_stride_;
161const void* MPMCQueueBase::PayloadPtr(
size_t index)
const
163 return payloads_ + index * payload_stride_;
171size_t MPMCQueueBase::AlignUpChecked(
size_t value,
size_t align)
173 DEV_ASSERT(align > 0);
174 ASSERT(value <= std::numeric_limits<size_t>::max() - (align - 1));
175 return ((value + align - 1) / align) * align;
184size_t MPMCQueueBase::MultiplyChecked(
size_t lhs,
size_t rhs)
186 if (lhs == 0 || rhs == 0)
191 ASSERT(lhs <= std::numeric_limits<size_t>::max() / rhs);
MPMCQueueBase(size_t element_size, size_t capacity)
构造一个字节队列内核 / Construct one byte-queue core
std::make_signed_t< SequenceType > SequenceDiffType
size_t Size() const
获取并发快照下的当前元素数 / Get the current approximate element count
ErrorCode PopBytes(void *value=nullptr)
按字节出队一个 payload;传空指针时只丢弃队头元素 / Dequeue one payload by bytes; pass null to discard the front item only
~MPMCQueueBase()
析构字节队列内核 / Destroy the byte-queue core
size_t SequenceType
单调递增的逻辑序号类型 / Monotonic logical sequence type.
ErrorCode PushBytes(const void *value)
按字节入队一个 payload / Enqueue one payload by bytes
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ PTR_NULL
空指针 / Null pointer
@ OK
操作成功 / Operation successful