Condy v1.6.0
C++ Asynchronous System Call Layer for Linux
Loading...
Searching...
No Matches
intrusive.hpp
Go to the documentation of this file.
1
5
6#pragma once
7
8#include "condy/utils.hpp"
9#include <cassert>
10#include <utility>
11
12namespace condy {
13
14struct SingleLinkEntry {
15 SingleLinkEntry *next = nullptr;
16};
17
18struct DoubleLinkEntry {
19 DoubleLinkEntry *next = nullptr;
20 DoubleLinkEntry *prev = nullptr;
21};
22
23template <typename T, SingleLinkEntry T::*Member> class IntrusiveSingleList {
24public:
25 IntrusiveSingleList() = default;
26 IntrusiveSingleList(IntrusiveSingleList &&other) noexcept
27 : head_(std::exchange(other.head_, nullptr)),
28 tail_(std::exchange(other.tail_, nullptr)) {}
29 IntrusiveSingleList &operator=(IntrusiveSingleList &&other) noexcept {
30 if (this != &other) {
31 assert(empty());
32 head_ = std::exchange(other.head_, nullptr);
33 tail_ = std::exchange(other.tail_, nullptr);
34 }
35 return *this;
36 }
37
38 IntrusiveSingleList(const IntrusiveSingleList &) = delete;
39 IntrusiveSingleList &operator=(const IntrusiveSingleList &) = delete;
40
41public:
42 void push_back(T *item) noexcept {
43 assert(item != nullptr);
44 SingleLinkEntry *entry = &(item->*Member);
45 assert(entry->next == nullptr);
46 entry->next = nullptr;
47 if (!head_) {
48 head_ = entry;
49 tail_ = entry;
50 } else {
51 tail_->next = entry;
52 tail_ = entry;
53 }
54 }
55
56 void push_back(IntrusiveSingleList other) noexcept {
57 if (other.empty()) {
58 return;
59 }
60 if (empty()) {
61 head_ = other.head_;
62 tail_ = other.tail_;
63 } else {
64 tail_->next = other.head_;
65 tail_ = other.tail_;
66 }
67 }
68
69 bool empty() const noexcept { return head_ == nullptr; }
70
71 T *pop_front() noexcept {
72 if (empty()) {
73 return nullptr;
74 }
75 SingleLinkEntry *entry = head_;
76 head_ = head_->next;
77 if (!head_) {
78 tail_ = nullptr;
79 }
80 entry->next = nullptr;
81 return container_of(Member, entry);
82 }
83
84private:
85 SingleLinkEntry *head_ = nullptr;
86 SingleLinkEntry *tail_ = nullptr;
87};
88
89template <typename T, DoubleLinkEntry T::*Member> class IntrusiveDoubleList {
90public:
91 IntrusiveDoubleList() = default;
92 IntrusiveDoubleList(IntrusiveDoubleList &&other) noexcept
93 : head_(std::exchange(other.head_, nullptr)),
94 tail_(std::exchange(other.tail_, nullptr)) {}
95 IntrusiveDoubleList &operator=(IntrusiveDoubleList &&other) noexcept {
96 if (this != &other) {
97 assert(empty());
98 head_ = std::exchange(other.head_, nullptr);
99 tail_ = std::exchange(other.tail_, nullptr);
100 }
101 return *this;
102 }
103
104 IntrusiveDoubleList(const IntrusiveDoubleList &) = delete;
105 IntrusiveDoubleList &operator=(const IntrusiveDoubleList &) = delete;
106
107public:
108 void push_back(T *item) noexcept {
109 assert(item != nullptr);
110 DoubleLinkEntry *entry = &(item->*Member);
111 assert(entry->next == nullptr && entry->prev == nullptr);
112 entry->next = nullptr;
113 entry->prev = tail_;
114 if (!head_) {
115 head_ = entry;
116 tail_ = entry;
117 } else {
118 tail_->next = entry;
119 tail_ = entry;
120 }
121 }
122
123 bool empty() const noexcept { return head_ == nullptr; }
124
125 T *pop_front() noexcept {
126 if (empty()) {
127 return nullptr;
128 }
129 DoubleLinkEntry *entry = head_;
130 head_ = head_->next;
131 if (head_) {
132 head_->prev = nullptr;
133 } else {
134 tail_ = nullptr;
135 }
136 entry->next = nullptr;
137 entry->prev = nullptr;
138 return container_of(Member, entry);
139 }
140
141 bool remove(T *item) noexcept {
142 assert(item != nullptr);
143 DoubleLinkEntry *entry = &(item->*Member);
144 if (entry->prev == nullptr && entry->next == nullptr &&
145 head_ != entry) {
146 return false;
147 }
148 if (entry->prev) {
149 entry->prev->next = entry->next;
150 } else {
151 assert(head_ == entry);
152 head_ = entry->next;
153 }
154 if (entry->next) {
155 entry->next->prev = entry->prev;
156 } else {
157 assert(tail_ == entry);
158 tail_ = entry->prev;
159 }
160 entry->next = nullptr;
161 entry->prev = nullptr;
162 return true;
163 }
164
165private:
166 DoubleLinkEntry *head_ = nullptr;
167 DoubleLinkEntry *tail_ = nullptr;
168};
169
170} // namespace condy
The main namespace for the Condy library.
Definition condy.hpp:30
Internal utility classes and functions used by Condy.