rippled
Loading...
Searching...
No Matches
LockFreeStack.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of Beast: https://github.com/vinniefalco/Beast
4 Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
21#define BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
22
23#include <atomic>
24#include <iterator>
25#include <type_traits>
26
27namespace beast {
28
29//------------------------------------------------------------------------------
30
31template <class Container, bool IsConst>
33{
34protected:
35 using Node = typename Container::Node;
36 using NodePtr =
38
39public:
41 using value_type = typename Container::value_type;
42 using difference_type = typename Container::difference_type;
43 using pointer = typename std::conditional<
44 IsConst,
45 typename Container::const_pointer,
46 typename Container::pointer>::type;
47 using reference = typename std::conditional<
48 IsConst,
49 typename Container::const_reference,
50 typename Container::reference>::type;
51
55
59
60 template <bool OtherIsConst>
66
69 {
70 m_node = node;
71 return static_cast<LockFreeStackIterator&>(*this);
72 }
73
76 {
77 m_node = m_node->m_next.load();
78 return static_cast<LockFreeStackIterator&>(*this);
79 }
80
83 {
84 LockFreeStackIterator result(*this);
85 m_node = m_node->m_next;
86 return result;
87 }
88
90 node() const
91 {
92 return m_node;
93 }
94
96 operator*() const
97 {
98 return *this->operator->();
99 }
100
101 pointer
103 {
104 return static_cast<pointer>(m_node);
105 }
106
107private:
109};
110
111//------------------------------------------------------------------------------
112
113template <class Container, bool LhsIsConst, bool RhsIsConst>
114bool
118{
119 return lhs.node() == rhs.node();
120}
121
122template <class Container, bool LhsIsConst, bool RhsIsConst>
123bool
127{
128 return lhs.node() != rhs.node();
129}
130
131//------------------------------------------------------------------------------
132
145template <class Element, class Tag = void>
147{
148public:
149 class Node
150 {
151 public:
152 Node() : m_next(nullptr)
153 {
154 }
155
156 explicit Node(Node* next) : m_next(next)
157 {
158 }
159
160 Node(Node const&) = delete;
161 Node&
162 operator=(Node const&) = delete;
163
164 private:
165 friend class LockFreeStack;
166
167 template <class Container, bool IsConst>
169
171 };
172
173public:
174 using value_type = Element;
175 using pointer = Element*;
176 using reference = Element&;
177 using const_pointer = Element const*;
178 using const_reference = Element const&;
184
186 {
187 }
188
189 LockFreeStack(LockFreeStack const&) = delete;
191 operator=(LockFreeStack const&) = delete;
192
194 bool
195 empty() const
196 {
197 return m_head.load() == &m_end;
198 }
199
211 // VFALCO NOTE Fix this, shouldn't it be a reference like intrusive list?
212 bool
214 {
215 bool first;
216 Node* old_head = m_head.load(std::memory_order_relaxed);
217 do
218 {
219 first = (old_head == &m_end);
220 node->m_next = old_head;
221 } while (!m_head.compare_exchange_strong(
222 old_head,
223 node,
226 return first;
227 }
228
238 Element*
240 {
241 Node* node = m_head.load();
242 Node* new_head;
243 do
244 {
245 if (node == &m_end)
246 return nullptr;
247 new_head = node->m_next.load();
248 } while (!m_head.compare_exchange_strong(
249 node,
250 new_head,
253 return static_cast<Element*>(node);
254 }
255
265 {
266 return iterator(m_head.load());
267 }
268
271 {
272 return iterator(&m_end);
273 }
274
276 begin() const
277 {
278 return const_iterator(m_head.load());
279 }
280
282 end() const
283 {
284 return const_iterator(&m_end);
285 }
286
288 cbegin() const
289 {
290 return const_iterator(m_head.load());
291 }
292
294 cend() const
295 {
296 return const_iterator(&m_end);
297 }
300private:
303};
304
305} // namespace beast
306
307#endif
reference operator*() const
LockFreeStackIterator & operator++()
typename Container::Node Node
typename std::conditional< IsConst, typename Container::const_pointer, typename Container::pointer >::type pointer
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 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)