1 /** 2 * Copyright (c) 2021-2022 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 PANDA_VERIFIER_UTIL_OBJ_POOL_HPP_ 17 #define PANDA_VERIFIER_UTIL_OBJ_POOL_HPP_ 18 19 #include "macros.h" 20 21 #include <cstdint> 22 #include <optional> 23 #include <utility> 24 25 namespace panda::verifier { 26 27 template <typename T, template <typename...> class Vector, typename InitializerType = void (*)(T &, std::size_t), 28 typename CleanerType = void (*)(T &)> 29 class ObjPool { 30 public: 31 class Accessor { 32 public: Accessor()33 Accessor() : idx {0}, pool {nullptr}, prev {nullptr}, next {nullptr} {} Accessor(std::size_t index,ObjPool * obj_pool)34 Accessor(std::size_t index, ObjPool *obj_pool) : idx {index}, pool {obj_pool}, prev {nullptr}, next {nullptr} 35 { 36 Insert(); 37 } Accessor(const Accessor & p)38 Accessor(const Accessor &p) : idx {p.idx}, pool {p.pool}, prev {nullptr}, next {nullptr} 39 { 40 Insert(); 41 } Accessor(Accessor && p)42 Accessor(Accessor &&p) : idx {p.idx}, pool {p.pool}, prev {p.prev}, next {p.next} 43 { 44 p.Reset(); 45 Rebind(); 46 } 47 Accessor &operator=(const Accessor &p) 48 { 49 Erase(); 50 Reset(); 51 idx = p.idx; 52 pool = p.pool; 53 Insert(); 54 return *this; 55 } 56 Accessor &operator=(Accessor &&p) 57 { 58 Erase(); 59 idx = p.idx; 60 pool = p.pool; 61 prev = p.prev; 62 next = p.next; 63 p.Reset(); 64 Rebind(); 65 return *this; 66 } ~Accessor()67 ~Accessor() 68 { 69 Erase(); 70 } 71 T &operator*() 72 { 73 return pool->Storage[idx]; 74 } 75 const T &operator*() const 76 { 77 return pool->Storage[idx]; 78 } 79 operator bool() const 80 { 81 return pool != nullptr; 82 } Free()83 void Free() 84 { 85 Erase(); 86 Reset(); 87 } 88 89 private: Reset()90 void Reset() 91 { 92 idx = 0; 93 pool = nullptr; 94 prev = nullptr; 95 next = nullptr; 96 } Insert()97 void Insert() 98 { 99 if (pool != nullptr) { 100 next = pool->Accessors[idx]; 101 if (next != nullptr) 102 next->prev = this; 103 pool->Accessors[idx] = this; 104 } 105 } Erase()106 void Erase() 107 { 108 if (pool != nullptr) { 109 if (prev == nullptr) { 110 pool->Accessors[idx] = next; 111 if (pool->Accessors[idx] == nullptr) { 112 pool->Cleaner(pool->Storage[idx]); 113 pool->Free.push_back(idx); 114 } 115 } else 116 prev->next = next; 117 if (next != nullptr) 118 next->prev = prev; 119 } 120 } Rebind()121 void Rebind() 122 { 123 if (pool != nullptr) { 124 if (prev != nullptr) 125 prev->next = this; 126 else 127 pool->Accessors[idx] = this; 128 if (next != nullptr) 129 next->prev = this; 130 } 131 } 132 133 std::size_t idx; 134 ObjPool *pool; 135 Accessor *prev; 136 Accessor *next; 137 138 friend class ObjPool; 139 }; 140 ObjPool(InitializerType initializer,CleanerType cleaner)141 ObjPool(InitializerType initializer, CleanerType cleaner) : Initializer {initializer}, Cleaner {cleaner} {} ObjPool(InitializerType initializer)142 ObjPool(InitializerType initializer) : Initializer {initializer}, Cleaner {[](T &) { return; }} {} ObjPool()143 ObjPool() : Initializer {[](T &, std::size_t) { return; }}, Cleaner {[](T &) { return; }} {} 144 145 ~ObjPool() = default; 146 147 DEFAULT_MOVE_SEMANTIC(ObjPool); 148 DEFAULT_COPY_SEMANTIC(ObjPool); 149 New()150 Accessor New() 151 { 152 std::size_t idx; 153 if (FreeCount() > 0) { 154 idx = Free.back(); 155 Free.pop_back(); 156 } else { 157 idx = Storage.size(); 158 Storage.emplace_back(); 159 Accessors.emplace_back(nullptr); 160 } 161 Initializer(Storage[idx], idx); 162 return Accessor {idx, this}; 163 } 164 FreeCount()165 std::size_t FreeCount() const 166 { 167 return Free.size(); 168 } 169 Count()170 std::size_t Count() const 171 { 172 return Storage.size(); 173 } 174 AccCount()175 std::size_t AccCount() const 176 { 177 size_t count = 0; 178 for (auto el : Accessors) { 179 Accessor *acc = el; 180 while (acc != nullptr) { 181 ++count; 182 acc = acc->next; 183 } 184 } 185 return count; 186 } 187 AllObjects()188 auto AllObjects() 189 { 190 thread_local size_t idx = 0; 191 return [this]() -> std::optional<Accessor> { 192 while (idx < Storage.size() && Accessors[idx] == nullptr) { 193 ++idx; 194 } 195 if (idx >= Storage.size()) { 196 idx = 0; 197 return std::nullopt; 198 } 199 return {Accessor {idx++, this}}; 200 }; 201 } 202 ShrinkToFit()203 void ShrinkToFit() 204 { 205 size_t idx1 = 0; 206 size_t idx2 = Storage.size() - 1; 207 while (idx1 < idx2) { 208 while ((idx1 < idx2) && (Accessors[idx1] != nullptr)) 209 ++idx1; 210 while ((idx1 < idx2) && (Accessors[idx2] == nullptr)) 211 --idx2; 212 if (idx1 < idx2) { 213 Storage[idx1] = std::move(Storage[idx2]); 214 Accessors[idx1] = Accessors[idx2]; 215 Accessor *acc = Accessors[idx1]; 216 while (acc != nullptr) { 217 acc->idx = idx1; 218 acc = acc->next; 219 } 220 --idx2; 221 } 222 } 223 if (Accessors[idx1] != nullptr) 224 ++idx1; 225 Storage.resize(idx1); 226 Storage.shrink_to_fit(); 227 Accessors.resize(idx1); 228 Accessors.shrink_to_fit(); 229 Free.clear(); 230 Free.shrink_to_fit(); 231 } 232 233 private: 234 InitializerType Initializer; 235 CleanerType Cleaner; 236 237 Vector<T> Storage; 238 Vector<std::size_t> Free; 239 Vector<Accessor *> Accessors; 240 }; 241 242 } // namespace panda::verifier 243 244 #endif // !PANDA_VERIFIER_UTIL_OBJ_POOL_HPP_ 245