• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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