CCF
Loading...
Searching...
No Matches
dl_list.h
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the Apache 2.0 License.
3#pragma once
4
5#include <cassert>
6#include <type_traits>
7
8namespace ds
9{
10 // Adapted from snmalloc 0.5.3.
11 // Intrusive doubly-linked list. Elements added via `insert()` and
12 // `insert_back()` become owned by the list (i.e. deleted on `clear()`).
13 template <class T>
14 class DLList final
15 {
16 private:
17 static_assert(
18 std::is_same_v<decltype(T::prev), T*>, "T->prev must be a T*");
19 static_assert(
20 std::is_same_v<decltype(T::next), T*>, "T->next must be a T*");
21
22 T* head = nullptr;
23 T* tail = nullptr;
24
25 public:
26 DLList() = default;
27
28 DLList(DLList&& o) noexcept : head(o.head), tail(o.tail)
29 {
30 o.head = nullptr;
31 o.tail = nullptr;
32 }
33
35 {
36 clear();
37 }
38
39 DLList& operator=(DLList&& o) noexcept
40 {
41 head = o.head;
42 tail = o.tail;
43
44 o.head = nullptr;
45 o.tail = nullptr;
46 return *this;
47 }
48
49 bool is_empty()
50 {
51 return head == nullptr;
52 }
53
55 {
56 return head;
57 }
58
60 {
61 return tail;
62 }
63
64 T* pop()
65 {
66 T* item = head;
67
68 if (item != nullptr)
69 {
70 remove(item);
71 }
72
73 return item;
74 }
75
77 {
78 T* item = tail;
79
80 if (item != nullptr)
81 {
82 remove(item);
83 }
84
85 return item;
86 }
87
88 void insert(T* item)
89 {
90#ifndef NDEBUG
92#endif
93
94 item->next = head;
95 item->prev = nullptr;
96
97 if (head != nullptr)
98 {
99 head->prev = item;
100 }
101 else
102 {
103 tail = item;
104 }
105
106 head = item;
107#ifndef NDEBUG
108 debug_check();
109#endif
110 }
111
112 void insert_back(T* item)
113 {
114#ifndef NDEBUG
116#endif
117
118 item->prev = tail;
119 item->next = nullptr;
120
121 if (tail != nullptr)
122 {
123 tail->next = item;
124 }
125 else
126 {
127 head = item;
128 }
129
130 tail = item;
131#ifndef NDEBUG
132 debug_check();
133#endif
134 }
135
136 void remove(T* item)
137 {
138#ifndef NDEBUG
140#endif
141
142 if (item->next != nullptr)
143 {
144 item->next->prev = item->prev;
145 }
146 else
147 {
148 tail = item->prev;
149 }
150
151 if (item->prev != nullptr)
152 {
153 item->prev->next = item->next;
154 }
155 else
156 {
157 head = item->next;
158 }
159
160#ifndef NDEBUG
161 debug_check();
162#endif
163 }
164
165 void clear()
166 {
167 while (head != nullptr)
168 {
169 auto c = head;
170 // The analysis does not seem to take into account that the
171 // penultimate remove will result in head->next == nullptr
172 // and head == nullptr on the next iteration
173 // This is perhaps related to
174 // https://github.com/llvm/llvm-project/issues/43395
175 remove(c); // NOLINT(clang-analyzer-cplusplus.NewDelete)
176 delete c; // NOLINT(cppcoreguidelines-owning-memory)
177 }
178 }
179
181 {
182#ifndef NDEBUG
183 debug_check();
184 T* curr = head;
185
186 while (curr != item)
187 {
188 assert(curr != nullptr);
189 curr = curr->next;
190 }
191#else
192 (void)(item);
193#endif
194 }
195
197 {
198#ifndef NDEBUG
199 debug_check();
200 T* curr = head;
201
202 while (curr != nullptr)
203 {
204 assert(curr != item);
205 curr = curr->next;
206 }
207#else
208 (void)(item);
209#endif
210 }
211
213 {
214#ifndef NDEBUG
215 T* item = head;
216 T* prev = nullptr;
217
218 while (item != nullptr)
219 {
220 assert(item->prev == prev);
221 prev = item;
222 item = item->next;
223 }
224#endif
225 }
226 };
227}
Definition dl_list.h:15
void insert(T *item)
Definition dl_list.h:88
void debug_check_contains(T *item)
Definition dl_list.h:180
void debug_check_not_contains(T *item)
Definition dl_list.h:196
T * pop()
Definition dl_list.h:64
void remove(T *item)
Definition dl_list.h:136
void insert_back(T *item)
Definition dl_list.h:112
T * get_tail()
Definition dl_list.h:59
void clear()
Definition dl_list.h:165
DLList()=default
T * get_head()
Definition dl_list.h:54
void debug_check()
Definition dl_list.h:212
~DLList()
Definition dl_list.h:34
DLList & operator=(DLList &&o) noexcept
Definition dl_list.h:39
DLList(DLList &&o) noexcept
Definition dl_list.h:28
bool is_empty()
Definition dl_list.h:49
T * pop_tail()
Definition dl_list.h:76
Definition dl_list.h:9