rippled
Loading...
Searching...
No Matches
LockFreeStack.h
1#pragma once
2
3#include <atomic>
4#include <iterator>
5#include <type_traits>
6
7namespace beast {
8
9//------------------------------------------------------------------------------
10
11template <class Container, bool IsConst>
13{
14protected:
15 using Node = typename Container::Node;
17
18public:
20 using value_type = typename Container::value_type;
21 using difference_type = typename Container::difference_type;
22 using pointer = typename std::
23 conditional<IsConst, typename Container::const_pointer, typename Container::pointer>::type;
24 using reference = typename std::conditional<
25 IsConst,
26 typename Container::const_reference,
27 typename Container::reference>::type;
28
32
36
37 template <bool OtherIsConst>
42
45 {
46 m_node = node;
47 return static_cast<LockFreeStackIterator&>(*this);
48 }
49
52 {
53 m_node = m_node->m_next.load();
54 return static_cast<LockFreeStackIterator&>(*this);
55 }
56
59 {
60 LockFreeStackIterator result(*this);
61 m_node = m_node->m_next;
62 return result;
63 }
64
66 node() const
67 {
68 return m_node;
69 }
70
72 operator*() const
73 {
74 return *this->operator->();
75 }
76
78 operator->() const
79 {
80 return static_cast<pointer>(m_node);
81 }
82
83private:
85};
86
87//------------------------------------------------------------------------------
88
89template <class Container, bool LhsIsConst, bool RhsIsConst>
90bool
97
98template <class Container, bool LhsIsConst, bool RhsIsConst>
99bool
103{
104 return lhs.node() != rhs.node();
105}
106
107//------------------------------------------------------------------------------
108
121template <class Element, class Tag = void>
123{
124public:
125 class Node
126 {
127 public:
128 Node() : m_next(nullptr)
129 {
130 }
131
132 explicit Node(Node* next) : m_next(next)
133 {
134 }
135
136 Node(Node const&) = delete;
137 Node&
138 operator=(Node const&) = delete;
139
140 private:
141 friend class LockFreeStack;
142
143 template <class Container, bool IsConst>
145
147 };
148
149public:
150 using value_type = Element;
151 using pointer = Element*;
152 using reference = Element&;
153 using const_pointer = Element const*;
154 using const_reference = Element const&;
159
161 {
162 }
163
164 LockFreeStack(LockFreeStack const&) = delete;
166 operator=(LockFreeStack const&) = delete;
167
169 bool
170 empty() const
171 {
172 return m_head.load() == &m_end;
173 }
174
186 // VFALCO NOTE Fix this, shouldn't it be a reference like intrusive list?
187 bool
189 {
190 bool first = false;
191 Node* old_head = m_head.load(std::memory_order_relaxed);
192 do
193 {
194 first = (old_head == &m_end);
195 node->m_next = old_head;
196 } while (!m_head.compare_exchange_strong(
198 return first;
199 }
200
210 Element*
212 {
213 Node* node = m_head.load();
214 Node* new_head = nullptr;
215 do
216 {
217 if (node == &m_end)
218 return nullptr;
219 new_head = node->m_next.load();
220 } while (!m_head.compare_exchange_strong(
222 return static_cast<Element*>(node);
223 }
224
234 {
235 return iterator(m_head.load());
236 }
237
240 {
241 return iterator(&m_end);
242 }
243
245 begin() const
246 {
247 return const_iterator(m_head.load());
248 }
249
251 end() const
252 {
253 return const_iterator(&m_end);
254 }
255
257 cbegin() const
258 {
259 return const_iterator(m_head.load());
260 }
261
263 cend() const
264 {
265 return const_iterator(&m_end);
266 }
269private:
272};
273
274} // namespace beast
reference operator*() const
LockFreeStackIterator & operator++()
typename Container::Node Node
LockFreeStackIterator & operator=(NodePtr node)
LockFreeStackIterator(LockFreeStackIterator< Container, OtherIsConst > const &other)
LockFreeStackIterator(NodePtr node)
typename Container::value_type value_type
typename std::conditional< IsConst, Node const *, Node * >::type NodePtr
typename std::conditional< IsConst, typename Container::const_pointer, typename Container::pointer >::type pointer
typename Container::difference_type difference_type
typename std::conditional< IsConst, typename Container::const_reference, typename Container::reference >::type reference
LockFreeStackIterator operator++(int)
Node(Node const &)=delete
Node & operator=(Node const &)=delete
std::atomic< Node * > m_next
Multiple Producer, Multiple Consumer (MPMC) intrusive stack.
const_iterator cend() const
bool push_front(Node *node)
Push a node onto the stack.
LockFreeStackIterator< LockFreeStack< Element, Tag >, false > iterator
const_iterator cbegin() const
iterator begin()
Return a forward iterator to the beginning or end of the stack.
Element * pop_front()
Pop an element off the stack.
LockFreeStack(LockFreeStack const &)=delete
bool empty() const
Returns true if the stack is empty.
LockFreeStack & operator=(LockFreeStack const &)=delete
Element const * const_pointer
Element const & const_reference
const_iterator begin() const
std::atomic< Node * > m_head
LockFreeStackIterator< LockFreeStack< Element, Tag >, true > const_iterator
const_iterator end() const
T is_same_v
bool operator==(LockFreeStackIterator< Container, LhsIsConst > const &lhs, LockFreeStackIterator< Container, RhsIsConst > const &rhs)
bool operator!=(LockFreeStackIterator< Container, LhsIsConst > const &lhs, LockFreeStackIterator< Container, RhsIsConst > const &rhs)