rippled
Loading...
Searching...
No Matches
LockFreeStack.h
1#ifndef BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
2#define BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
3
4#include <atomic>
5#include <iterator>
6#include <type_traits>
7
8namespace beast {
9
10//------------------------------------------------------------------------------
11
12template <class Container, bool IsConst>
14{
15protected:
16 using Node = typename Container::Node;
18
19public:
21 using value_type = typename Container::value_type;
22 using difference_type = typename Container::difference_type;
23 using pointer =
25 using reference =
27
31
35
36 template <bool OtherIsConst>
40
43 {
44 m_node = node;
45 return static_cast<LockFreeStackIterator&>(*this);
46 }
47
50 {
51 m_node = m_node->m_next.load();
52 return static_cast<LockFreeStackIterator&>(*this);
53 }
54
57 {
58 LockFreeStackIterator result(*this);
59 m_node = m_node->m_next;
60 return result;
61 }
62
64 node() const
65 {
66 return m_node;
67 }
68
70 operator*() const
71 {
72 return *this->operator->();
73 }
74
76 operator->() const
77 {
78 return static_cast<pointer>(m_node);
79 }
80
81private:
83};
84
85//------------------------------------------------------------------------------
86
87template <class Container, bool LhsIsConst, bool RhsIsConst>
88bool
95
96template <class Container, bool LhsIsConst, bool RhsIsConst>
97bool
101{
102 return lhs.node() != rhs.node();
103}
104
105//------------------------------------------------------------------------------
106
119template <class Element, class Tag = void>
121{
122public:
123 class Node
124 {
125 public:
126 Node() : m_next(nullptr)
127 {
128 }
129
130 explicit Node(Node* next) : m_next(next)
131 {
132 }
133
134 Node(Node const&) = delete;
135 Node&
136 operator=(Node const&) = delete;
137
138 private:
139 friend class LockFreeStack;
140
141 template <class Container, bool IsConst>
143
145 };
146
147public:
148 using value_type = Element;
149 using pointer = Element*;
150 using reference = Element&;
151 using const_pointer = Element const*;
152 using const_reference = Element const&;
157
159 {
160 }
161
162 LockFreeStack(LockFreeStack const&) = delete;
164 operator=(LockFreeStack const&) = delete;
165
167 bool
168 empty() const
169 {
170 return m_head.load() == &m_end;
171 }
172
184 // VFALCO NOTE Fix this, shouldn't it be a reference like intrusive list?
185 bool
187 {
188 bool first;
189 Node* old_head = m_head.load(std::memory_order_relaxed);
190 do
191 {
192 first = (old_head == &m_end);
193 node->m_next = old_head;
194 } while (!m_head.compare_exchange_strong(old_head, node, std::memory_order_release, std::memory_order_relaxed));
195 return first;
196 }
197
207 Element*
209 {
210 Node* node = m_head.load();
211 Node* new_head;
212 do
213 {
214 if (node == &m_end)
215 return nullptr;
216 new_head = node->m_next.load();
217 } while (!m_head.compare_exchange_strong(node, new_head, std::memory_order_release, std::memory_order_relaxed));
218 return static_cast<Element*>(node);
219 }
220
230 {
231 return iterator(m_head.load());
232 }
233
236 {
237 return iterator(&m_end);
238 }
239
241 begin() const
242 {
243 return const_iterator(m_head.load());
244 }
245
247 end() const
248 {
249 return const_iterator(&m_end);
250 }
251
253 cbegin() const
254 {
255 return const_iterator(m_head.load());
256 }
257
259 cend() const
260 {
261 return const_iterator(&m_end);
262 }
265private:
268};
269
270} // namespace beast
271
272#endif
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)