xrpld
Loading...
Searching...
No Matches
LockFreeStack.h
1#pragma once
2
3#include <atomic>
4#include <cstddef>
5#include <iterator>
6#include <type_traits>
7
8namespace beast {
9
10//------------------------------------------------------------------------------
11
12template <class Container, bool IsConst>
14{
15protected:
16 using Node = Container::Node;
18
19public:
21 using value_type = Container::value_type;
22 using difference_type = Container::difference_type;
23 using pointer =
25 using reference = std::
26 conditional_t<IsConst, typename Container::const_reference, typename Container::reference>;
27
29
33
34 template <bool OtherIsConst>
39
42 {
43 node_ = node;
44 return *this;
45 }
46
49 {
50 node_ = node_->next_.load();
51 return static_cast<LockFreeStackIterator&>(*this);
52 }
53
56 {
57 LockFreeStackIterator result(*this);
58 node_ = node_->next_;
59 return result;
60 }
61
62 [[nodiscard]] NodePtr
63 node() const
64 {
65 return node_;
66 }
67
69 operator*() const
70 {
71 return *this->operator->();
72 }
73
75 operator->() const
76 {
77 return static_cast<pointer>(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
119template <class Element, class Tag = void>
121{
122public:
123 class Node
124 {
125 public:
126 Node() : next_(nullptr)
127 {
128 }
129
130 explicit Node(Node* next) : 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
158 LockFreeStack() : end_(nullptr), head_(&end_)
159 {
160 }
161
162 LockFreeStack(LockFreeStack const&) = delete;
164 operator=(LockFreeStack const&) = delete;
165
169 [[nodiscard]] bool
170 empty() const
171 {
172 return head_.load() == &end_;
173 }
174
187 // VFALCO NOTE Fix this, shouldn't it be a reference like intrusive list?
188 bool
190 {
191 bool first = false;
192 Node* oldHead = head_.load(std::memory_order_relaxed);
193 do
194 {
195 first = (oldHead == &end_);
196 node->next_ = oldHead;
197 } while (!head_.compare_exchange_strong(
198 oldHead, node, std::memory_order_release, std::memory_order_relaxed));
199 return first;
200 }
201
212 Element*
214 {
215 Node* node = head_.load();
216 Node* newHead = nullptr;
217 do
218 {
219 if (node == &end_)
220 return nullptr;
221 newHead = node->next_.load();
222 } while (!head_.compare_exchange_strong(
223 node, newHead, std::memory_order_release, std::memory_order_relaxed));
224 return static_cast<Element*>(node);
225 }
226
237 {
238 return iterator(head_.load());
239 }
240
243 {
244 return iterator(&end_);
245 }
246
247 [[nodiscard]] const_iterator
248 begin() const
249 {
250 return const_iterator(head_.load());
251 }
252
253 [[nodiscard]] const_iterator
254 end() const
255 {
256 return const_iterator(&end_);
257 }
258
259 [[nodiscard]] const_iterator
260 cbegin() const
261 {
262 return const_iterator(head_.load());
263 }
264
265 [[nodiscard]] const_iterator
266 cend() const
267 {
268 return const_iterator(&end_);
269 }
270
271
272private:
275};
276
277} // namespace beast
reference operator*() const
Container::value_type value_type
std:: conditional_t< IsConst, typename Container::const_reference, typename Container::reference > reference
std::forward_iterator_tag iterator_category
LockFreeStackIterator & operator++()
LockFreeStackIterator & operator=(NodePtr node)
LockFreeStackIterator(LockFreeStackIterator< Container, OtherIsConst > const &other)
LockFreeStackIterator(NodePtr node)
Container::difference_type difference_type
std::conditional_t< IsConst, Node const *, Node * > NodePtr
std::conditional_t< IsConst, typename Container::const_pointer, typename Container::pointer > pointer
LockFreeStackIterator operator++(int)
Node(Node const &)=delete
Node & operator=(Node const &)=delete
std::atomic< Node * > next_
const_iterator cend() const
bool pushFront(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.
LockFreeStack(LockFreeStack const &)=delete
bool empty() const
Returns true if the stack is empty.
LockFreeStack & operator=(LockFreeStack const &)=delete
Element * popFront()
Pop an element off the stack.
Element const * const_pointer
std::atomic< Node * > head_
Element const & const_reference
std::ptrdiff_t difference_type
const_iterator begin() const
LockFreeStackIterator< LockFreeStack< Element, Tag >, true > const_iterator
const_iterator end() const
bool operator==(LockFreeStackIterator< Container, LhsIsConst > const &lhs, LockFreeStackIterator< Container, RhsIsConst > const &rhs)
bool operator!=(LockFreeStackIterator< Container, LhsIsConst > const &lhs, LockFreeStackIterator< Container, RhsIsConst > const &rhs)