1484543d1Sopenharmony_ci/*
2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License.
5484543d1Sopenharmony_ci * You may obtain a copy of the License at
6484543d1Sopenharmony_ci *
7484543d1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8484543d1Sopenharmony_ci *
9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and
13484543d1Sopenharmony_ci * limitations under the License.
14484543d1Sopenharmony_ci */
15484543d1Sopenharmony_ci
16484543d1Sopenharmony_ci#ifndef _INTRUSIVELIST_H_
17484543d1Sopenharmony_ci#define _INTRUSIVELIST_H_
18484543d1Sopenharmony_ci#include <cassert>
19484543d1Sopenharmony_ci#include <utility>
20484543d1Sopenharmony_ci#include <cstddef>
21484543d1Sopenharmony_cinamespace ffrt {
22484543d1Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
23484543d1Sopenharmony_citemplate <typename Tag>
24484543d1Sopenharmony_cistruct SListNode {
25484543d1Sopenharmony_ci    // if next point to self, isn't in list
26484543d1Sopenharmony_ci    bool IsLinked() const noexcept
27484543d1Sopenharmony_ci    {
28484543d1Sopenharmony_ci        return next != this;
29484543d1Sopenharmony_ci    }
30484543d1Sopenharmony_ci    explicit SListNode(SListNode* p) noexcept : next {p}
31484543d1Sopenharmony_ci    {
32484543d1Sopenharmony_ci    }
33484543d1Sopenharmony_ci    SListNode() noexcept = default;
34484543d1Sopenharmony_ci
35484543d1Sopenharmony_ciprivate:
36484543d1Sopenharmony_ci    void Swap(SListNode& rhs) noexcept
37484543d1Sopenharmony_ci    {
38484543d1Sopenharmony_ci        std::swap(next, rhs.next);
39484543d1Sopenharmony_ci    }
40484543d1Sopenharmony_ci
41484543d1Sopenharmony_ciprivate:
42484543d1Sopenharmony_ci    template <typename, typename>
43484543d1Sopenharmony_ci    friend struct SList;
44484543d1Sopenharmony_ci    SListNode* next {this};
45484543d1Sopenharmony_ci};
46484543d1Sopenharmony_ci
47484543d1Sopenharmony_citemplate <typename T, typename NodeType>
48484543d1Sopenharmony_cistruct SList {
49484543d1Sopenharmony_ci    bool empty() const noexcept
50484543d1Sopenharmony_ci    {
51484543d1Sopenharmony_ci        return m_head.next == nullptr;
52484543d1Sopenharmony_ci    }
53484543d1Sopenharmony_ci
54484543d1Sopenharmony_ci    SList() noexcept = default;
55484543d1Sopenharmony_ci
56484543d1Sopenharmony_ci    SList(SList&& rhs) noexcept
57484543d1Sopenharmony_ci    {
58484543d1Sopenharmony_ci        Swap(rhs);
59484543d1Sopenharmony_ci    }
60484543d1Sopenharmony_ci    SList& operator=(SList&& rhs) noexcept
61484543d1Sopenharmony_ci    {
62484543d1Sopenharmony_ci        if (this != &rhs) {
63484543d1Sopenharmony_ci            SList tmp {std::move(rhs)};
64484543d1Sopenharmony_ci            Swap(tmp);
65484543d1Sopenharmony_ci        }
66484543d1Sopenharmony_ci        return *this;
67484543d1Sopenharmony_ci    }
68484543d1Sopenharmony_ci
69484543d1Sopenharmony_ci    void PushFront(T& node) noexcept
70484543d1Sopenharmony_ci    {
71484543d1Sopenharmony_ci        auto& nd = static_cast<NodeType&>(node);
72484543d1Sopenharmony_ci        nd.next = std::exchange(m_head.next, &nd);
73484543d1Sopenharmony_ci    }
74484543d1Sopenharmony_ci
75484543d1Sopenharmony_ci    T* PopFront() noexcept
76484543d1Sopenharmony_ci    {
77484543d1Sopenharmony_ci        if (empty()) {
78484543d1Sopenharmony_ci            return nullptr;
79484543d1Sopenharmony_ci        } else {
80484543d1Sopenharmony_ci            auto node = m_head.next;
81484543d1Sopenharmony_ci            m_head.next = std::exchange(node->next, node);
82484543d1Sopenharmony_ci            return static_cast<T*>(node);
83484543d1Sopenharmony_ci        }
84484543d1Sopenharmony_ci    }
85484543d1Sopenharmony_ci
86484543d1Sopenharmony_ciprivate:
87484543d1Sopenharmony_ci    void Swap(SList& rhs) noexcept
88484543d1Sopenharmony_ci    {
89484543d1Sopenharmony_ci        m_head.Swap(rhs.m_head);
90484543d1Sopenharmony_ci    }
91484543d1Sopenharmony_ci
92484543d1Sopenharmony_ciprivate:
93484543d1Sopenharmony_ci    NodeType m_head {nullptr};
94484543d1Sopenharmony_ci};
95484543d1Sopenharmony_ci
96484543d1Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
97484543d1Sopenharmony_cistruct ListNode {
98484543d1Sopenharmony_ci    bool IsLinked() const noexcept
99484543d1Sopenharmony_ci    {
100484543d1Sopenharmony_ci        return next != this && prev != this;
101484543d1Sopenharmony_ci    }
102484543d1Sopenharmony_ci
103484543d1Sopenharmony_ci    ListNode(ListNode* p, ListNode* n) noexcept : prev {p}, next {n}
104484543d1Sopenharmony_ci    {
105484543d1Sopenharmony_ci    }
106484543d1Sopenharmony_ci    ListNode() noexcept = default;
107484543d1Sopenharmony_ci
108484543d1Sopenharmony_ciprivate:
109484543d1Sopenharmony_ci    template <typename, typename>
110484543d1Sopenharmony_ci    friend struct List;
111484543d1Sopenharmony_ci    ListNode* prev {this};
112484543d1Sopenharmony_ci    ListNode* next {this};
113484543d1Sopenharmony_ci};
114484543d1Sopenharmony_ci
115484543d1Sopenharmony_citemplate <typename T, typename NodeType>
116484543d1Sopenharmony_cistruct List {
117484543d1Sopenharmony_ci    List() noexcept : m_head {&m_tail, &m_tail}, m_tail {&m_head, &m_head}
118484543d1Sopenharmony_ci    {
119484543d1Sopenharmony_ci    }
120484543d1Sopenharmony_ci
121484543d1Sopenharmony_ci    List(List&& rhs) noexcept : List()
122484543d1Sopenharmony_ci    {
123484543d1Sopenharmony_ci        if (!rhs.empty()) {
124484543d1Sopenharmony_ci            NodeType* x = rhs.m_head.next;
125484543d1Sopenharmony_ci            m_head.next = x;
126484543d1Sopenharmony_ci            x->prev = &m_head;
127484543d1Sopenharmony_ci
128484543d1Sopenharmony_ci            NodeType* y = rhs.m_tail.prev;
129484543d1Sopenharmony_ci            y->next = &m_tail;
130484543d1Sopenharmony_ci            m_tail.prev = y;
131484543d1Sopenharmony_ci
132484543d1Sopenharmony_ci            m_size = rhs.m_size;
133484543d1Sopenharmony_ci            // reset rhs to empty
134484543d1Sopenharmony_ci            rhs.Reset();
135484543d1Sopenharmony_ci        }
136484543d1Sopenharmony_ci    }
137484543d1Sopenharmony_ci
138484543d1Sopenharmony_ci    List& operator=(List&& rhs) noexcept
139484543d1Sopenharmony_ci    {
140484543d1Sopenharmony_ci        if (this != &rhs && !rhs.empty()) {
141484543d1Sopenharmony_ci            Reset();
142484543d1Sopenharmony_ci            NodeType* x = rhs.m_head.next;
143484543d1Sopenharmony_ci            m_head.next = x;
144484543d1Sopenharmony_ci            x->prev = &m_head;
145484543d1Sopenharmony_ci
146484543d1Sopenharmony_ci            NodeType* y = rhs.m_tail.prev;
147484543d1Sopenharmony_ci            y->next = &m_tail;
148484543d1Sopenharmony_ci            m_tail.prev = y;
149484543d1Sopenharmony_ci
150484543d1Sopenharmony_ci            m_size = rhs.m_size;
151484543d1Sopenharmony_ci            // reset rhs to empty
152484543d1Sopenharmony_ci            rhs.Reset();
153484543d1Sopenharmony_ci        }
154484543d1Sopenharmony_ci        return *this;
155484543d1Sopenharmony_ci    }
156484543d1Sopenharmony_ci
157484543d1Sopenharmony_ci    bool empty() const noexcept
158484543d1Sopenharmony_ci    {
159484543d1Sopenharmony_ci        return Size() == 0;
160484543d1Sopenharmony_ci    }
161484543d1Sopenharmony_ci
162484543d1Sopenharmony_ci    size_t Size() const noexcept
163484543d1Sopenharmony_ci    {
164484543d1Sopenharmony_ci        return m_size;
165484543d1Sopenharmony_ci    }
166484543d1Sopenharmony_ci
167484543d1Sopenharmony_ci    void PushFront(T& node) noexcept
168484543d1Sopenharmony_ci    {
169484543d1Sopenharmony_ci        auto& nd = static_cast<NodeType&>(node);
170484543d1Sopenharmony_ci
171484543d1Sopenharmony_ci        m_head.next->prev = &nd;
172484543d1Sopenharmony_ci        nd.prev = &m_head;
173484543d1Sopenharmony_ci        nd.next = m_head.next;
174484543d1Sopenharmony_ci        m_head.next = &nd;
175484543d1Sopenharmony_ci        ++m_size;
176484543d1Sopenharmony_ci    }
177484543d1Sopenharmony_ci
178484543d1Sopenharmony_ci    void PushBack(T& node) noexcept
179484543d1Sopenharmony_ci    {
180484543d1Sopenharmony_ci        auto& nd = static_cast<NodeType&>(node);
181484543d1Sopenharmony_ci
182484543d1Sopenharmony_ci        m_tail.prev->next = &nd;
183484543d1Sopenharmony_ci        nd.prev = m_tail.prev;
184484543d1Sopenharmony_ci        nd.next = &m_tail;
185484543d1Sopenharmony_ci        m_tail.prev = &nd;
186484543d1Sopenharmony_ci        ++m_size;
187484543d1Sopenharmony_ci    }
188484543d1Sopenharmony_ci
189484543d1Sopenharmony_ci    T* PopFront() noexcept
190484543d1Sopenharmony_ci    {
191484543d1Sopenharmony_ci        if (empty()) {
192484543d1Sopenharmony_ci            return nullptr;
193484543d1Sopenharmony_ci        } else {
194484543d1Sopenharmony_ci            auto node = static_cast<T*>(m_head.next);
195484543d1Sopenharmony_ci            Unlink(*node);
196484543d1Sopenharmony_ci            return node;
197484543d1Sopenharmony_ci        }
198484543d1Sopenharmony_ci    }
199484543d1Sopenharmony_ci
200484543d1Sopenharmony_ci    T* Front() noexcept
201484543d1Sopenharmony_ci    {
202484543d1Sopenharmony_ci        return empty() ? nullptr : static_cast<T*>(m_head.next);
203484543d1Sopenharmony_ci    }
204484543d1Sopenharmony_ci
205484543d1Sopenharmony_ci    T* PopBack() noexcept
206484543d1Sopenharmony_ci    {
207484543d1Sopenharmony_ci        if (empty()) {
208484543d1Sopenharmony_ci            return nullptr;
209484543d1Sopenharmony_ci        } else {
210484543d1Sopenharmony_ci            auto node = static_cast<T*>(m_tail.prev);
211484543d1Sopenharmony_ci            Unlink(*node);
212484543d1Sopenharmony_ci            return node;
213484543d1Sopenharmony_ci        }
214484543d1Sopenharmony_ci    }
215484543d1Sopenharmony_ci
216484543d1Sopenharmony_ci    void Erase(T& node) noexcept
217484543d1Sopenharmony_ci    {
218484543d1Sopenharmony_ci        Unlink(node);
219484543d1Sopenharmony_ci    }
220484543d1Sopenharmony_ci
221484543d1Sopenharmony_ciprivate:
222484543d1Sopenharmony_ci    void Unlink(NodeType& node) noexcept
223484543d1Sopenharmony_ci    {
224484543d1Sopenharmony_ci        assert(node.IsLinked());
225484543d1Sopenharmony_ci        node.prev->next = node.next;
226484543d1Sopenharmony_ci        node.next->prev = node.prev;
227484543d1Sopenharmony_ci        node.next = node.prev = &node;
228484543d1Sopenharmony_ci        --m_size;
229484543d1Sopenharmony_ci    }
230484543d1Sopenharmony_ci
231484543d1Sopenharmony_ciprivate:
232484543d1Sopenharmony_ci    void Reset() noexcept
233484543d1Sopenharmony_ci    {
234484543d1Sopenharmony_ci        m_tail.prev = &m_head;
235484543d1Sopenharmony_ci        m_tail.next = &m_head;
236484543d1Sopenharmony_ci        m_head.prev = &m_tail;
237484543d1Sopenharmony_ci        m_head.next = &m_tail;
238484543d1Sopenharmony_ci        m_size = 0;
239484543d1Sopenharmony_ci    }
240484543d1Sopenharmony_ci
241484543d1Sopenharmony_ciprivate:
242484543d1Sopenharmony_ci    NodeType m_head;
243484543d1Sopenharmony_ci    NodeType m_tail;
244484543d1Sopenharmony_ci    size_t m_size {0};
245484543d1Sopenharmony_ci};
246484543d1Sopenharmony_ci} // namespace ffrt
247484543d1Sopenharmony_ci#endif // HICORO_INTRUSIVELIST_H
248