1 /* 2 * Copyright (c) 2021 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_VERIFICATION_UTIL_OBJ_POOL_H_ 17 #define PANDA_VERIFICATION_UTIL_OBJ_POOL_H_ 18 19 #include <cstdint> 20 #include <optional> 21 #include <utility> 22 23 #include "macros.h" 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 using ObjType = T; 32 33 class Accessor { 34 public: Accessor()35 Accessor() : idx {0}, pool {nullptr} {} 36 Accessor(std::size_t index,ObjPool * obj_pool)37 Accessor(std::size_t index, ObjPool *obj_pool) : idx {index}, pool {obj_pool} 38 { 39 if (obj_pool != nullptr) { 40 obj_pool->IncRC(idx); 41 } 42 } 43 Accessor(const Accessor & p)44 Accessor(const Accessor &p) : idx {p.idx}, pool {p.pool} 45 { 46 if (pool != nullptr) { 47 pool->IncRC(idx); 48 } 49 } 50 Accessor(Accessor && p)51 Accessor(Accessor &&p) : idx {p.idx}, pool {p.pool} 52 { 53 p.Reset(); 54 } 55 56 Accessor &operator=(const Accessor &p) 57 { 58 if (p.pool != nullptr) { 59 p.pool->IncRC(p.idx); 60 } 61 if (pool != nullptr) { 62 pool->DecRC(idx); 63 } 64 idx = p.idx; 65 pool = p.pool; 66 return *this; 67 } 68 69 Accessor &operator=(Accessor &&p) 70 { 71 auto old_idx = idx; 72 auto old_pool = pool; 73 idx = p.idx; 74 pool = p.pool; 75 if (old_pool != nullptr) { 76 old_pool->DecRC(old_idx); 77 } 78 p.Reset(); 79 return *this; 80 } 81 ~Accessor()82 ~Accessor() 83 { 84 if (pool != nullptr) { 85 pool->DecRC(idx); 86 Reset(); 87 } 88 } 89 90 T &operator*() 91 { 92 return pool->Storage[idx]; 93 } 94 95 const T &operator*() const 96 { 97 return pool->Storage[idx]; 98 } 99 100 operator bool() const 101 { 102 return pool != nullptr; 103 } 104 Free()105 void Free() 106 { 107 if (pool != nullptr) { 108 pool->DecRC(idx); 109 Reset(); 110 } 111 } 112 113 private: Reset()114 void Reset() 115 { 116 idx = 0; 117 pool = nullptr; 118 } 119 120 std::size_t idx {0}; 121 ObjPool *pool {nullptr}; 122 }; 123 ObjPool(InitializerType initializer,CleanerType cleaner)124 ObjPool(InitializerType initializer, CleanerType cleaner) : Initializer {initializer}, Cleaner {cleaner} {} ObjPool(InitializerType initializer)125 ObjPool(InitializerType initializer) : Initializer {initializer}, Cleaner {[](T &) { return; }} {} ObjPool()126 ObjPool() : Initializer {[](T &, std::size_t) { return; }}, Cleaner {[](T &) { return; }} {} 127 ~ObjPool() = default; 128 DEFAULT_COPY_SEMANTIC(ObjPool); 129 DEFAULT_MOVE_SEMANTIC(ObjPool); 130 New()131 Accessor New() 132 { 133 std::size_t idx; 134 if (FreeCount() > 0) { 135 idx = Free.back(); 136 Free.pop_back(); 137 } else { 138 idx = Storage.size(); 139 Storage.emplace_back(); 140 RC.emplace_back(0); 141 } 142 Initializer(Storage[idx], idx); 143 return {idx, this}; 144 } 145 FreeCount()146 std::size_t FreeCount() const 147 { 148 return Free.size(); 149 } 150 Count()151 std::size_t Count() const 152 { 153 return Storage.size(); 154 } 155 AllObjects()156 auto AllObjects() 157 { 158 return [this, idx {static_cast<size_t>(0)}]() mutable -> std::optional<Accessor> { 159 while (idx < Storage.size() && RC[idx] == 0) { 160 ++idx; 161 } 162 if (idx >= Storage.size()) { 163 return std::nullopt; 164 } 165 return {Accessor {idx++, this}}; 166 }; 167 } 168 169 private: IncRC(std::size_t idx)170 void IncRC(std::size_t idx) 171 { 172 ++RC[idx]; 173 } 174 DecRC(std::size_t idx)175 void DecRC(std::size_t idx) 176 { 177 if (--RC[idx] == 0) { 178 Cleaner(Storage[idx]); 179 Free.push_back(idx); 180 } 181 } 182 183 InitializerType Initializer; 184 CleanerType Cleaner; 185 186 Vector<T> Storage; 187 Vector<std::size_t> Free; 188 Vector<std::size_t> RC; 189 }; 190 191 } // namespace panda::verifier 192 193 #endif // PANDA_VERIFICATION_UTIL_OBJ_POOL_H_ 194