1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FFRT_LINKED_LIST_H
17 #define FFRT_LINKED_LIST_H
18 
19 #include <cstddef>
20 #include <cstdint>
21 
22 namespace ffrt {
23 class LinkedList {
24 public:
LinkedList()25     LinkedList() : prev(this), next(this)
26     {
27     }
28 
LinkedList(LinkedList * prev,LinkedList * next)29     LinkedList(LinkedList* prev, LinkedList* next) : prev(prev), next(next)
30     {
31     }
32 
33     template <typename T>
OffsetOf(LinkedList T::* member)34     static ptrdiff_t OffsetOf(LinkedList T::*member) noexcept
35     {
36         return reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<T*>(0)->*member));
37     }
38 
39     template <typename T>
ContainerOf(LinkedList * node,LinkedList T::* member)40     static T* ContainerOf(LinkedList* node, LinkedList T::*member) noexcept
41     {
42         return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(node) - OffsetOf<T>(member));
43     }
44 
45     template <typename T>
ContainerOf(LinkedList T::* member)46     T* ContainerOf(LinkedList T::*member) noexcept
47     {
48         return ContainerOf(this, member);
49     }
50 
InsertAfter(LinkedList * cur,LinkedList * node)51     static void InsertAfter(LinkedList* cur, LinkedList* node) noexcept
52     {
53         node->next = cur->next;
54         node->prev = cur;
55         cur->next->prev = node;
56         cur->next = node;
57     }
58 
InsertBefore(LinkedList * cur,LinkedList * node)59     static void InsertBefore(LinkedList* cur, LinkedList* node) noexcept
60     {
61         node->next = cur;
62         node->prev = cur->prev;
63         cur->prev->next = node;
64         cur->prev = node;
65     }
66 
Delete(LinkedList & node)67     static void Delete(LinkedList& node) noexcept
68     {
69         node.prev->next = node.next;
70         node.next->prev = node.prev;
71         node.next = &node;
72         node.prev = &node;
73     }
74 
Delete(LinkedList * node)75     static void Delete(LinkedList* node) noexcept
76     {
77         node->prev->next = node->next;
78         node->next->prev = node->prev;
79         node->next = node;
80         node->prev = node;
81     }
82 
RemoveCur(LinkedList & node)83     static void RemoveCur(LinkedList& node) noexcept
84     {
85         if (node.Null()) {
86             return;
87         }
88         Delete(node);
89     }
90 
RemoveCur(LinkedList * node)91     static void RemoveCur(LinkedList* node) noexcept
92     {
93         if (node->Null()) {
94             return;
95         }
96         Delete(node);
97     }
98 
Next(LinkedList * cur)99     static LinkedList* Next(LinkedList* cur) noexcept
100     {
101         if (cur->Empty()) {
102             return nullptr;
103         }
104 
105         LinkedList* next = cur->next;
106         return next;
107     }
108 
109     template <typename T>
Next(LinkedList * cur,LinkedList T::* member)110     static T* Next(LinkedList* cur, LinkedList T::*member) noexcept
111     {
112         if (cur->Empty()) {
113             return nullptr;
114         }
115 
116         LinkedList* next = cur->next;
117         return ContainerOf<T>(next, member);
118     }
119 
RemoveNext(LinkedList * cur)120     static LinkedList* RemoveNext(LinkedList* cur) noexcept
121     {
122         if (cur->Empty()) {
123             return nullptr;
124         }
125 
126         LinkedList* next = cur->next;
127         Delete(next);
128         return next;
129     }
130 
131     template <typename T>
RemoveNext(LinkedList * cur,LinkedList T::* member)132     static T* RemoveNext(LinkedList* cur, LinkedList T::*member) noexcept
133     {
134         if (cur->Empty()) {
135             return nullptr;
136         }
137 
138         LinkedList* next = cur->next;
139         Delete(next);
140         return ContainerOf<T>(next, member);
141     }
142 
RemovePrev(LinkedList * cur)143     static LinkedList* RemovePrev(LinkedList* cur) noexcept
144     {
145         if (cur->Empty()) {
146             return nullptr;
147         }
148 
149         LinkedList* prev = cur->prev;
150         Delete(prev);
151         return prev;
152     }
153 
154     template <typename T>
RemovePrev(LinkedList * cur,LinkedList T::* member)155     static T* RemovePrev(LinkedList* cur, LinkedList T::*member) noexcept
156     {
157         if (cur->Empty()) {
158             return nullptr;
159         }
160 
161         LinkedList* prev = cur->prev;
162         Delete(prev);
163         return ContainerOf<T>(prev, member);
164     }
165 
InsertAfter(LinkedList & node)166     void InsertAfter(LinkedList& node) noexcept
167     {
168         InsertAfter(this, &node);
169     }
170 
InsertAfter(LinkedList * node)171     void InsertAfter(LinkedList* node) noexcept
172     {
173         InsertAfter(this, node);
174     }
175 
InsertBefore(LinkedList & node)176     void InsertBefore(LinkedList& node) noexcept
177     {
178         InsertBefore(this, &node);
179     }
180 
InsertBefore(LinkedList * node)181     void InsertBefore(LinkedList* node) noexcept
182     {
183         InsertBefore(this, node);
184     }
185 
Next()186     LinkedList* Next() noexcept
187     {
188         return Next(this);
189     }
190 
191     template <typename T>
Next(LinkedList T::* member)192     T* Next(LinkedList T::*member) noexcept
193     {
194         return Next(this, member);
195     }
196 
RemoveNext()197     LinkedList* RemoveNext() noexcept
198     {
199         return RemoveNext(this);
200     }
201 
202     template <typename T>
RemoveNext(LinkedList T::* member)203     T* RemoveNext(LinkedList T::*member) noexcept
204     {
205         return RemoveNext(this, member);
206     }
207 
RemovePrev()208     LinkedList* RemovePrev() noexcept
209     {
210         return RemovePrev(this);
211     }
212 
213     template <typename T>
RemovePrev(LinkedList T::* member)214     T* RemovePrev(LinkedList T::*member) noexcept
215     {
216         return RemovePrev(this, member);
217     }
218 
PushFront(LinkedList & node)219     void PushFront(LinkedList& node) noexcept
220     {
221         InsertAfter(&node);
222     }
223 
PushFront(LinkedList * node)224     void PushFront(LinkedList* node) noexcept
225     {
226         InsertAfter(node);
227     }
228 
PushBack(LinkedList & node)229     void PushBack(LinkedList& node) noexcept
230     {
231         InsertBefore(&node);
232     }
233 
PushBack(LinkedList * node)234     void PushBack(LinkedList* node) noexcept
235     {
236         InsertBefore(node);
237     }
238 
Front()239     LinkedList* Front() noexcept
240     {
241         return Next();
242     }
243 
244     template <typename T>
Front(LinkedList T::* member)245     T* Front(LinkedList T::*member) noexcept
246     {
247         return Next(member);
248     }
249 
PopFront()250     LinkedList* PopFront() noexcept
251     {
252         return RemoveNext();
253     }
254 
255     template <typename T>
PopFront(LinkedList T::* member)256     T* PopFront(LinkedList T::*member) noexcept
257     {
258         return RemoveNext(member);
259     }
260 
PopBack()261     LinkedList* PopBack() noexcept
262     {
263         return RemovePrev();
264     }
265 
266     template <typename T>
PopBack(LinkedList T::* member)267     T* PopBack(LinkedList T::*member) noexcept
268     {
269         return RemovePrev(member);
270     }
271 
Empty()272     bool Empty() const noexcept
273     {
274         return next == this;
275     }
276 
Null()277     bool Null() const noexcept
278     {
279         return prev == nullptr && next == nullptr;
280     }
281 
InList()282     bool InList() const noexcept
283     {
284         return (next != nullptr && next != this);
285     }
286 
287 private:
288     LinkedList* prev;
289     LinkedList* next;
290 };
291 } // namespace ffrt
292 #endif
293