13 #ifndef __MPSC_LINKED_QUEUE_HPP__ 14 #define __MPSC_LINKED_QUEUE_HPP__ 19 #include <glog/logging.h> 45 explicit Node(E* element =
nullptr) : element(element) {}
48 std::atomic<Node<E>*> next = ATOMIC_VAR_INIT(
nullptr);
60 while (
auto element =
dequeue()) {
72 CHECK_NOTNULL(element);
74 auto newNode =
new Node<T>(element);
78 auto oldhead = head.exchange(newNode, std::memory_order_acq_rel);
84 oldhead->next.store(newNode, std::memory_order_release);
90 auto currentTail = tail;
94 auto nextTail = currentTail->next.load(std::memory_order_acquire);
104 if (nextTail ==
nullptr) {
108 if (head.load(std::memory_order_relaxed) == tail) {
116 nextTail = currentTail->next.load(std::memory_order_acquire);
117 }
while (nextTail ==
nullptr);
120 CHECK_NOTNULL(nextTail);
124 currentTail->next.store(
nullptr, std::memory_order_release);
126 auto element = nextTail->element;
127 nextTail->element =
nullptr;
139 template <
typename F>
142 auto end = head.load();
146 node = node->next.load();
151 if (node ==
nullptr) {
166 return tail->next.load(std::memory_order_relaxed) ==
nullptr &&
167 head.load(std::memory_order_relaxed) == tail;
179 alignas(64) std::atomic<Node<T>*> head;
180 alignas(64) Node<T>* tail;
181 char pad[64 -
sizeof(Node<T>*)];
186 #endif // __MPSC_LINKED_QUEUE_HPP__ Definition: mpsc_linked_queue.hpp:38
void for_each(F &&f)
Definition: mpsc_linked_queue.hpp:140
F && f
Definition: defer.hpp:270
T * dequeue()
Definition: mpsc_linked_queue.hpp:88
MpscLinkedQueue()
Definition: mpsc_linked_queue.hpp:52
Definition: executor.hpp:48
bool empty()
Definition: mpsc_linked_queue.hpp:164
void enqueue(T *element)
Definition: mpsc_linked_queue.hpp:68
~MpscLinkedQueue()
Definition: mpsc_linked_queue.hpp:58