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 =
24 using reference =
26
30
34
35 template <bool OtherIsConst>
39
42 {
43 m_node = node;
44 return static_cast<LockFreeStackIterator&>(*this);
45 }
46
49 {
50 m_node = m_node->m_next.load();
51 return static_cast<LockFreeStackIterator&>(*this);
52 }
53
56 {
57 LockFreeStackIterator result(*this);
58 m_node = m_node->m_next;
59 return result;
60 }
61
63 node() const
64 {
65 return m_node;
66 }
67
69 operator*() const
70 {
71 return *this->operator->();
72 }
73
75 operator->() const
76 {
77 return static_cast<pointer>(m_node);
78 }
79
80private:
82};
83
84//------------------------------------------------------------------------------
85
86template <class Container, bool LhsIsConst, bool RhsIsConst>
87bool
94
95template <class Container, bool LhsIsConst, bool RhsIsConst>
96bool
100{
101 return lhs.node() != rhs.node();
102}
103
104//------------------------------------------------------------------------------
105
118template <class Element, class Tag = void>
120{
121public:
122 class Node
123 {
124 public:
125 Node() : m_next(nullptr)
126 {
127 }
128
129 explicit Node(Node* next) : m_next(next)
130 {
131 }
132
133 Node(Node const&) = delete;
134 Node&
135 operator=(Node const&) = delete;
136
137 private:
138 friend class LockFreeStack;
139
140 template <class Container, bool IsConst>
142
144 };
145
146public:
147 using value_type = Element;
148 using pointer = Element*;
149 using reference = Element&;
150 using const_pointer = Element const*;
151 using const_reference = Element const&;
156
158 {
159 }
160
161 LockFreeStack(LockFreeStack const&) = delete;
163 operator=(LockFreeStack const&) = delete;
164
166 bool
167 empty() const
168 {
169 return m_head.load() == &m_end;
170 }
171
183 // VFALCO NOTE Fix this, shouldn't it be a reference like intrusive list?
184 bool
186 {
187 bool first;
188 Node* old_head = m_head.load(std::memory_order_relaxed);
189 do
190 {
191 first = (old_head == &m_end);
192 node->m_next = old_head;
193 } while (!m_head.compare_exchange_strong(old_head, node, std::memory_order_release, std::memory_order_relaxed));
194 return first;
195 }
196
206 Element*
208 {
209 Node* node = m_head.load();
210 Node* new_head;
211 do
212 {
213 if (node == &m_end)
214 return nullptr;
215 new_head = node->m_next.load();
216 } while (!m_head.compare_exchange_strong(node, new_head, std::memory_order_release, std::memory_order_relaxed));
217 return static_cast<Element*>(node);
218 }
219
229 {
230 return iterator(m_head.load());
231 }
232
235 {
236 return iterator(&m_end);
237 }
238
240 begin() const
241 {
242 return const_iterator(m_head.load());
243 }
244
246 end() const
247 {
248 return const_iterator(&m_end);
249 }
250
252 cbegin() const
253 {
254 return const_iterator(m_head.load());
255 }
256
258 cend() const
259 {
260 return const_iterator(&m_end);
261 }
264private:
267};
268
269} // namespace beast
reference operator*() const
LockFreeStackIterator & operator++()
typename Container::Node Node
LockFreeStackIterator & operator=(NodePtr node)
typename std::conditional< IsConst, typename Container::const_pointer, typename Container::pointer >::type pointer
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 Container::difference_type difference_type
LockFreeStackIterator operator++(int)
typename std::conditional< IsConst, typename Container::const_reference, typename Container::reference >::type reference
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)