1 /* 2 * Copyright (c) 2025 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 COMMON_COMPONENTS_COMMON_NEW_MARK_STACK_H 17 #define COMMON_COMPONENTS_COMMON_NEW_MARK_STACK_H 18 19 #include <mutex> 20 #include "common_components/base/time_utils.h" 21 22 namespace common { 23 template<class T> 24 class MarkStackBuffer { 25 constexpr static size_t MAX = 64; 26 27 public: 28 MarkStackBuffer<T>* next = nullptr; 29 MarkStackBuffer<T>* pre = nullptr; full()30 bool full() { return count == MAX; } 31 empty()32 bool empty() { return count == 0; } 33 push_back(T t)34 void push_back(T t) 35 { 36 LOGF_CHECK(!full()) << "Mark stack buffer can not be full when push back"; 37 stack_[count] = t; 38 count++; 39 } 40 back()41 T back() 42 { 43 LOGF_CHECK(!empty()) << "Mark stack buffer can not be empty when get back"; 44 return stack_[count - 1]; 45 } 46 pop_back()47 void pop_back() 48 { 49 LOGF_CHECK(!empty()) << "Mark stack buffer can not be empty when pop back"; 50 count--; 51 } 52 size_t count = 0; 53 54 private: 55 T stack_[MAX]; 56 }; 57 58 template<class T> 59 class MarkStack { 60 public: 61 MarkStack() = default; 62 MarkStack(MarkStack && stack)63 MarkStack(MarkStack&& stack) 64 { 65 this->h_ = stack.head(); 66 this->t_ = stack.tail(); 67 this->s_ = stack.size(); 68 stack.clean(); 69 } 70 MarkStack(MarkStackBuffer<T> * buf)71 MarkStack(MarkStackBuffer<T>* buf) : h_(buf) 72 { 73 MarkStackBuffer<T>* tmp = buf; 74 while (tmp != nullptr) { 75 if (tmp->next == nullptr) { 76 this->t_ = tmp; 77 } 78 this->s_++; 79 tmp = tmp->next; 80 } 81 } 82 ~MarkStack()83 ~MarkStack() { clear(); } 84 head()85 MarkStackBuffer<T>* head() { return this->h_; } 86 tail()87 MarkStackBuffer<T>* tail() { return this->t_; } 88 size()89 size_t size() { return this->s_; } 90 count()91 size_t count() 92 { 93 MarkStackBuffer<T> *current = this->h_; 94 size_t ret = 0; 95 while (current!=nullptr) { 96 ret+=current->count; 97 current = current->next; 98 } 99 100 return ret; 101 } 102 empty()103 bool empty() 104 { 105 return this->s_ == 0 && this->h_ == nullptr && this->t_ == nullptr; 106 } 107 clear()108 void clear() 109 { 110 while (!empty()) { 111 MarkStackBuffer<T>* tmp = this->h_; 112 this->h_ = this->h_->next; 113 if (this->h_ != nullptr) { 114 this->h_->pre = nullptr; 115 } 116 delete tmp; 117 tmp = nullptr; 118 this->s_--; 119 } 120 this->t_ = nullptr; 121 } 122 push_back(T value)123 void push_back(T value) 124 { 125 if (this->t_ == nullptr || this->t_->full()) { 126 push(new MarkStackBuffer<T>()); 127 } 128 this->t_->push_back(value); 129 } 130 back()131 T back() 132 { 133 if (this->t_ == nullptr) { 134 return nullptr; 135 } 136 return this->t_->back(); 137 } 138 pop_back()139 void pop_back() 140 { 141 LOGF_CHECK(!empty()) << "Mark stack can not be empty when pop back"; 142 this->t_->pop_back(); 143 if (this->t_->empty()) { 144 auto tmp = pop(); 145 delete tmp; 146 tmp = nullptr; 147 } 148 } 149 insert(MarkStack<T> & stack)150 void insert(MarkStack<T>& stack) 151 { 152 if (stack.empty()) { 153 return; 154 } 155 if (this->h_ == nullptr) { 156 this->h_ = stack.head(); 157 this->t_ = stack.tail(); 158 this->s_ = stack.size(); 159 stack.clean(); 160 return; 161 } 162 this->t_->next = stack.head(); 163 stack.head()->pre = this->t_; 164 this->t_ = stack.tail(); 165 this->s_ += stack.size(); 166 stack.clean(); 167 } 168 split(size_t splitNum)169 MarkStackBuffer<T>* split(size_t splitNum) 170 { 171 if (splitNum == 0 || s_ == 0) { 172 return nullptr; 173 } 174 auto res = this->h_; 175 size_t num = 0; 176 while (num < splitNum) { 177 if (num == splitNum - 1) { 178 auto tmp = this->h_; 179 this->h_ = this->h_->next; 180 if (this->h_ != nullptr) { 181 this->h_->pre = nullptr; 182 } 183 tmp->next = nullptr; 184 } else { 185 this->h_ = this->h_->next; 186 } 187 num++; 188 this->s_--; 189 if (this->h_ == nullptr) { 190 this->t_ = nullptr; 191 return res; 192 } 193 } 194 return res; 195 } 196 private: push(MarkStackBuffer<T> * buf)197 void push(MarkStackBuffer<T>* buf) 198 { 199 if (empty()) { 200 this->h_ = buf; 201 this->t_ = buf; 202 this->s_++; 203 return; 204 } 205 buf->pre = this->t_; 206 this->t_->next = buf; 207 this->t_ = buf; 208 this->s_++; 209 } 210 pop()211 MarkStackBuffer<T>* pop() 212 { 213 if (empty()) { 214 return nullptr; 215 } 216 MarkStackBuffer<T>* res = this->t_; 217 this->t_ = this->t_->pre; 218 if (this->t_ != nullptr) { 219 this->t_->next = nullptr; 220 } else { 221 this->h_ = nullptr; 222 } 223 res->pre = nullptr; 224 this->s_--; 225 return res; 226 } 227 clean()228 void clean() 229 { 230 if (empty()) { 231 return; 232 } 233 this->h_ = nullptr; 234 this->t_ = nullptr; 235 this->s_ = 0; 236 } 237 238 MarkStackBuffer<T>* h_ = nullptr; 239 MarkStackBuffer<T>* t_ = nullptr; 240 size_t s_ = 0; 241 }; 242 } 243 #endif // COMMON_COMPONENTS_COMMON_NEW_MARK_STACK_H 244