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