xrpld
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 = Container::Node;
17
18public:
20 using value_type = Container::value_type;
21 using difference_type = Container::difference_type;
22 using pointer =
24 using reference = std::
25 conditional_t<IsConst, typename Container::const_reference, typename Container::reference>;
26
28
32
33 template <bool OtherIsConst>
38
41 {
42 node_ = node;
43 return static_cast<LockFreeStackIterator&>(*this);
44 }
45
48 {
49 node_ = node_->next_.load();
50 return static_cast<LockFreeStackIterator&>(*this);
51 }
52
55 {
56 LockFreeStackIterator result(*this);
57 node_ = node_->next_;
58 return result;
59 }
60
62 node() const
63 {
64 return node_;
65 }
66
68 operator*() const
69 {
70 return *this->operator->();
71 }
72
74 operator->() const
75 {
76 return static_cast<pointer>(node_);
77 }
78
79private:
81};
82
83//------------------------------------------------------------------------------
84
85template <class Container, bool LhsIsConst, bool RhsIsConst>
86bool
93
94template <class Container, bool LhsIsConst, bool RhsIsConst>
95bool
102
103//------------------------------------------------------------------------------
104
117template <class Element, class Tag = void>
119{
120public:
121 class Node
122 {
123 public:
124 Node() : next_(nullptr)
125 {
126 }
127
128 explicit Node(Node* next) : next_(next)
129 {
130 }
131
132 Node(Node const&) = delete;
133 Node&
134 operator=(Node const&) = delete;
135
136 private:
137 friend class LockFreeStack;
138
139 template <class Container, bool IsConst>
141
143 };
144
145public:
146 using value_type = Element;
147 using pointer = Element*;
148 using reference = Element&;
149 using const_pointer = Element const*;
150 using const_reference = Element const&;
155
156 LockFreeStack() : end_(nullptr), head_(&end_)
157 {
158 }
159
160 LockFreeStack(LockFreeStack const&) = delete;
162 operator=(LockFreeStack const&) = delete;
163
165 [[nodiscard]] bool
166 empty() const
167 {
168 return head_.load() == &end_;
169 }
170
182 // VFALCO NOTE Fix this, shouldn't it be a reference like intrusive list?
183 bool
185 {
186 bool first = false;
187 Node* oldHead = head_.load(std::memory_order_relaxed);
188 do
189 {
190 first = (oldHead == &end_);
191 node->next_ = oldHead;
192 } while (!head_.compare_exchange_strong(
193 oldHead, node, std::memory_order_release, std::memory_order_relaxed));
194 return first;
195 }
196
206 Element*
208 {
209 Node* node = head_.load();
210 Node* newHead = nullptr;
211 do
212 {
213 if (node == &end_)
214 return nullptr;
215 newHead = node->next_.load();
216 } while (!head_.compare_exchange_strong(
217 node, newHead, std::memory_order_release, std::memory_order_relaxed));
218 return static_cast<Element*>(node);
219 }
220
230 {
231 return iterator(head_.load());
232 }
233
236 {
237 return iterator(&end_);
238 }
239
240 [[nodiscard]] const_iterator
241 begin() const
242 {
243 return const_iterator(head_.load());
244 }
245
246 [[nodiscard]] const_iterator
247 end() const
248 {
249 return const_iterator(&end_);
250 }
251
252 [[nodiscard]] const_iterator
253 cbegin() const
254 {
255 return const_iterator(head_.load());
256 }
257
258 [[nodiscard]] const_iterator
259 cend() const
260 {
261 return const_iterator(&end_);
262 }
263
264
265private:
268};
269
270} // 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)