34 static_assert(__atomic_always_lock_free(
sizeof(Node*),
nullptr),
35 "IntrusiveMpscQueue requires lock-free pointer atomics");
36 static_assert(
alignof(Node) >=
alignof(Node*),
37 "IntrusiveMpscQueue nodes require natural pointer alignment");
38 static_assert(NextMember !=
nullptr,
"IntrusiveMpscQueue requires a valid intrusive link member");
41 enum class PopResult {
52 storeNext(&stub,
nullptr, __ATOMIC_RELAXED);
57 Node* previous = beginPush(node);
58 finishPush(node, previous);
74 Node* next = loadNext(tail);
78 if (loadHead() == tail) {
79 return PopResult::Empty;
81 return PopResult::Transient;
86 next = loadNext(tail);
92 return PopResult::Item;
95 if (tail != loadHead()) {
96 return PopResult::Transient;
102 next = loadNext(tail);
106 return PopResult::Transient;
111 return PopResult::Item;
120 Node* beginPush(Node& node) {
123 storeNext(&node,
nullptr, __ATOMIC_RELAXED);
124 return __atomic_exchange_n(&m_Head, &node, __ATOMIC_ACQ_REL);
127 static void finishPush(Node& node, Node* previous) {
129 storeNext(previous, &node, __ATOMIC_RELEASE);
132 Node* loadHead()
const {
133 return __atomic_load_n(&m_Head, __ATOMIC_ACQUIRE);
136 static Node* loadNext(Node* node) {
137 return __atomic_load_n(&(node->*NextMember), __ATOMIC_ACQUIRE);
140 static void storeNext(Node* node, Node* next,
int memoryOrder) {
141 __atomic_store_n(&(node->*NextMember), next, memoryOrder);