27template <
class T,
class Alloc = DLNA_ALLOCATOR<T>>
31 std::atomic<Node*>
next{
nullptr};
32 std::atomic<Node*>
prior{
nullptr};
52 if (
node !=
nullptr &&
owner !=
nullptr) {
53 Node* next_node =
node->
next.load(std::memory_order_acquire);
54 if (next_node !=
nullptr && next_node != &
owner->
last) {
72 if (
node !=
nullptr &&
owner !=
nullptr) {
73 Node* prior_node =
node->
prior.load(std::memory_order_acquire);
74 if (prior_node !=
nullptr && prior_node != &
owner->
first) {
105 return !(*
this == it);
110 if (
node ==
nullptr)
throw std::out_of_range(
"Iterator dereference: nullptr");
115 if (
node ==
nullptr)
throw std::out_of_range(
"Iterator dereference: nullptr");
122 inline operator bool()
const {
return !
is_eof; }
134 for (
int j = 0; j < offset && tmp !=
nullptr; j++) {
135 Node* next_node = tmp->
next.load(std::memory_order_acquire);
136 if (next_node ==
nullptr || next_node == &
owner->
last) {
141 }
else if (offset < 0) {
142 for (
int j = 0; j < -offset && tmp !=
nullptr; j++) {
143 Node* prior_node = tmp->
prior.load(std::memory_order_acquire);
144 if (prior_node ==
nullptr || prior_node == &
owner->
first) {
157 using NodeAlloc =
typename std::allocator_traits<Alloc>::template rebind_alloc<Node>;
168 Node* current = ref.
first.
next.load(std::memory_order_acquire);
169 while (current != &ref.
last) {
171 current = current->
next.load(std::memory_order_acquire);
179 for (
int i = 0; i < N; ++i) {
197 if (node ==
nullptr)
return false;
201 Node* old_last_prior =
last.
prior.load(std::memory_order_acquire);
204 node->
next.store(&
last, std::memory_order_relaxed);
205 node->
prior.store(old_last_prior, std::memory_order_relaxed);
209 if (old_last_prior->
next.compare_exchange_weak(
210 expected_next, node, std::memory_order_release,
211 std::memory_order_relaxed)) {
213 Node* expected_prior = old_last_prior;
214 if (
last.
prior.compare_exchange_weak(expected_prior, node,
215 std::memory_order_release,
216 std::memory_order_relaxed)) {
222 old_last_prior->
next.store(&
last, std::memory_order_relaxed);
229 if (node ==
nullptr)
return false;
233 Node* old_first_next =
first.
next.load(std::memory_order_acquire);
236 node->
prior.store(&
first, std::memory_order_relaxed);
237 node->
next.store(old_first_next, std::memory_order_relaxed);
241 if (old_first_next->
prior.compare_exchange_weak(
242 expected_prior, node, std::memory_order_release,
243 std::memory_order_relaxed)) {
245 Node* expected_next = old_first_next;
246 if (
first.
next.compare_exchange_weak(expected_next, node,
247 std::memory_order_release,
248 std::memory_order_relaxed)) {
254 old_first_next->
prior.store(&
first, std::memory_order_relaxed);
261 if (node ==
nullptr)
return false;
265 if (current_node ==
nullptr)
return false;
268 Node* prior = current_node->
prior.load(std::memory_order_acquire);
269 if (prior ==
nullptr)
return false;
272 node->
prior.store(prior, std::memory_order_relaxed);
273 node->
next.store(current_node, std::memory_order_relaxed);
276 Node* expected_next = current_node;
277 if (prior->
next.compare_exchange_weak(expected_next, node,
278 std::memory_order_release,
279 std::memory_order_relaxed)) {
281 Node* expected_prior = prior;
282 if (current_node->
prior.compare_exchange_weak(
283 expected_prior, node, std::memory_order_release,
284 std::memory_order_relaxed)) {
290 prior->
next.store(current_node, std::memory_order_relaxed);
307 Node* first_data =
first.
next.load(std::memory_order_acquire);
308 if (first_data == &
last)
return false;
310 Node* next_node = first_data->
next.load(std::memory_order_acquire);
311 data = first_data->
data;
314 if (
first.
next.compare_exchange_weak(first_data, next_node,
315 std::memory_order_release,
316 std::memory_order_relaxed)) {
317 if (next_node->
prior.compare_exchange_weak(first_data, &
first,
318 std::memory_order_release,
319 std::memory_order_relaxed)) {
326 first.
next.store(first_data, std::memory_order_relaxed);
333 Node* last_data =
last.
prior.load(std::memory_order_acquire);
334 if (last_data == &
first)
return false;
336 Node* prior_node = last_data->
prior.load(std::memory_order_acquire);
337 data = last_data->
data;
340 if (
last.
prior.compare_exchange_weak(last_data, prior_node,
341 std::memory_order_release,
342 std::memory_order_relaxed)) {
343 if (prior_node->
next.compare_exchange_weak(last_data, &
last,
344 std::memory_order_release,
345 std::memory_order_relaxed)) {
352 last.
prior.store(last_data, std::memory_order_relaxed);
359 if (p_delete ==
nullptr || p_delete == &
first || p_delete == &
last) {
364 Node* prior_node = p_delete->
prior.load(std::memory_order_acquire);
365 Node* next_node = p_delete->
next.load(std::memory_order_acquire);
367 if (prior_node ==
nullptr || next_node ==
nullptr)
return false;
370 if (prior_node->
next.compare_exchange_weak(p_delete, next_node,
371 std::memory_order_release,
372 std::memory_order_relaxed)) {
373 if (next_node->
prior.compare_exchange_weak(p_delete, prior_node,
374 std::memory_order_release,
375 std::memory_order_relaxed)) {
382 prior_node->
next.store(p_delete, std::memory_order_relaxed);
389 Node* first_data =
first.
next.load(std::memory_order_acquire);
390 Iterator it(first_data == &
last ?
nullptr : first_data,
this);
402 Node* last_data =
last.
prior.load(std::memory_order_acquire);
403 Iterator it(last_data == &
first ?
nullptr : last_data,
this);
433 for (
int j = 0; j < index && n != &
last; j++) {
434 n = n->
next.load(std::memory_order_acquire);
449 Node* last_data =
last.
prior.load(std::memory_order_acquire);
455 Node* first_data =
first.
next.load(std::memory_order_acquire);
473 if (!p_delete)
return;
Bidirectional iterator for ListLockFree.
Definition: ListLockFree.h:44
Iterator operator++()
Definition: ListLockFree.h:51
T * operator->()
Definition: ListLockFree.h:114
Node * get_node()
Definition: ListLockFree.h:120
bool operator!=(const Iterator &it) const
Definition: ListLockFree.h:104
Iterator(Node *node, ListLockFree *owner_ptr=nullptr)
Definition: ListLockFree.h:47
bool operator==(const Iterator &it) const
Definition: ListLockFree.h:100
ListLockFree * owner
Definition: ListLockFree.h:129
Iterator operator--(int)
Definition: ListLockFree.h:85
Iterator operator+(int offset)
Definition: ListLockFree.h:91
T & operator*()
Definition: ListLockFree.h:109
void set_owner(ListLockFree *owner_ptr)
Definition: ListLockFree.h:124
Iterator operator++(int)
Definition: ListLockFree.h:65
Node * node
Definition: ListLockFree.h:127
bool is_eof
Definition: ListLockFree.h:128
Iterator getIteratorAtOffset(int offset)
Definition: ListLockFree.h:131
Iterator operator--()
Definition: ListLockFree.h:71
Iterator operator-(int offset)
Definition: ListLockFree.h:95
Lock-free double linked list using atomic operations.
Definition: ListLockFree.h:28
Node first
Definition: ListLockFree.h:461
T & operator[](int index)
Access element at index (O(n)). Not thread-safe under concurrency. Make sure that no other thread mod...
Definition: ListLockFree.h:431
bool pop_front(T &data)
Definition: ListLockFree.h:305
~ListLockFree()
Definition: ListLockFree.h:184
ListLockFree(const ListLockFree &ref)
Copy constructor (not thread-safe for the source list)
Definition: ListLockFree.h:165
Iterator end()
Definition: ListLockFree.h:395
bool clear()
Definition: ListLockFree.h:417
ListLockFree(const T(&a)[N], const Alloc &alloc=Alloc())
Constructor using array.
Definition: ListLockFree.h:177
Iterator rbegin()
Definition: ListLockFree.h:401
typename std::allocator_traits< Alloc >::template rebind_alloc< Node > NodeAlloc
Definition: ListLockFree.h:157
size_t size()
Definition: ListLockFree.h:413
ListLockFree(const Alloc &alloc=Alloc())
Default constructor.
Definition: ListLockFree.h:160
std::atomic< size_t > record_count
Definition: ListLockFree.h:463
NodeAlloc node_alloc_
Definition: ListLockFree.h:464
bool empty()
Definition: ListLockFree.h:415
T & front()
Provides the first element.
Definition: ListLockFree.h:454
bool pop_back()
Definition: ListLockFree.h:300
void link()
Definition: ListLockFree.h:478
bool push_front(const T &data)
Definition: ListLockFree.h:227
bool swap(ListLockFree< T > &ref)
Swap contents with another list. Not implemented (returns false).
Definition: ListLockFree.h:190
Iterator begin()
Definition: ListLockFree.h:388
bool pop_front()
Definition: ListLockFree.h:295
T & back()
Provides the last element.
Definition: ListLockFree.h:448
Node last
Definition: ListLockFree.h:462
Node * createNode()
Definition: ListLockFree.h:466
bool erase(Iterator it)
Definition: ListLockFree.h:357
Iterator rend()
Definition: ListLockFree.h:408
bool insert(Iterator it, const T &data)
Definition: ListLockFree.h:259
bool pop_back(T &data)
Definition: ListLockFree.h:331
void deleteNode(Node *p_delete)
Definition: ListLockFree.h:472
bool push_back(const T &data)
Definition: ListLockFree.h:195
Definition: Allocator.h:13
Definition: ListLockFree.h:30
std::atomic< Node * > prior
Definition: ListLockFree.h:32
T data
Definition: ListLockFree.h:33
Node(const T &value)
Definition: ListLockFree.h:36
std::atomic< Node * > next
Definition: ListLockFree.h:31