1 /*
2 * Copyright (c) 2023 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 MEMPOOL_INCLUDE_MEMPOOL_ALLOCATOR_H
17 #define MEMPOOL_INCLUDE_MEMPOOL_ALLOCATOR_H
18 #include <cstddef>
19 #include <limits>
20 #include <vector>
21 #include <deque>
22 #include <queue>
23 #include <set>
24 #include <unordered_set>
25 #include <map>
26 #include <unordered_map>
27 #include <forward_list>
28 #include "mempool.h"
29
30 namespace maple {
31 template <typename T>
32 class MapleAllocatorAdapter; // circular dependency exists, no other choice
33 class MapleAllocator {
34 public:
MapleAllocator(MemPool * m)35 explicit MapleAllocator(MemPool *m) : memPool(m) {}
36 virtual ~MapleAllocator() = default;
37
38 // Get adapter for use in STL containers. See arena_containers.h .
39 MapleAllocatorAdapter<void> Adapter();
Alloc(size_t bytes)40 virtual void *Alloc(size_t bytes)
41 {
42 return (memPool != nullptr) ? memPool->Malloc(bytes) : nullptr;
43 }
44
45 template <class T, typename... Arguments>
New(Arguments &&...args)46 T *New(Arguments &&... args)
47 {
48 void *p = memPool->Malloc(sizeof(T));
49 DEBUG_ASSERT(p != nullptr, "ERROR: New error");
50 p = new (p) T(std::forward<Arguments>(args)...);
51 return static_cast<T *>(p);
52 }
53
GetMemPool()54 MemPool *GetMemPool() const
55 {
56 return memPool;
57 }
58
SetMemPool(MemPool * m)59 void SetMemPool(MemPool *m)
60 {
61 memPool = m;
62 }
63
64 protected:
65 MemPool *memPool;
66 template <typename U>
67 friend class MapleAllocatorAdapter;
68 }; // MapleAllocator
69
70 // must be destroyed, otherwise there will be memory leak
71 // only one allocater can be used at the same time
72 class LocalMapleAllocator : public MapleAllocator {
73 public:
LocalMapleAllocator(StackMemPool & m)74 explicit LocalMapleAllocator(StackMemPool &m)
75 : MapleAllocator(&m),
76 fixedStackTopMark(m.fixedMemStackTop),
77 bigStackTopMark(m.bigMemStackTop),
78 fixedCurPtrMark(m.curPtr),
79 bigCurPtrMark(m.bigCurPtr)
80 {
81 m.PushAllocator(this);
82 }
~LocalMapleAllocator()83 ~LocalMapleAllocator() override
84 {
85 static_cast<StackMemPool *>(memPool)->ResetStackTop(this, fixedCurPtrMark, fixedStackTopMark, bigCurPtrMark,
86 bigStackTopMark);
87 };
88
GetStackMemPool()89 StackMemPool &GetStackMemPool() const
90 {
91 return static_cast<StackMemPool &>(*memPool);
92 }
93
94 MemPool *GetMemPool() const = delete;
95
Alloc(size_t bytes)96 void *Alloc(size_t bytes) override
97 {
98 static_cast<StackMemPool *>(memPool)->CheckTopAllocator(this);
99 return memPool->Malloc(bytes);
100 }
101
102 private:
103 using MapleAllocator::MapleAllocator;
104 MemBlock *const fixedStackTopMark;
105 MemBlock *const bigStackTopMark;
106 uint8_t *const fixedCurPtrMark;
107 uint8_t *const bigCurPtrMark;
108 };
109
110 template <typename T>
111 class MapleAllocatorAdapter; // circular dependency exists, no other choice
112
113 template <typename T>
114 using MapleQueue = std::deque<T, MapleAllocatorAdapter<T>>;
115
116 template <typename T>
117 using MapleVector = std::vector<T, MapleAllocatorAdapter<T>>;
118
119 template <typename T>
120 class MapleStack {
121 public:
122 using size_type = typename MapleVector<T>::size_type;
123 using iterator = typename MapleVector<T>::iterator;
124
MapleStack(MapleAllocatorAdapter<T> adapter)125 MapleStack(MapleAllocatorAdapter<T> adapter) : vect(adapter) {}
126
127 ~MapleStack() = default;
128
GetVector()129 MapleVector<T> &GetVector()
130 {
131 return vect;
132 }
133
empty()134 bool empty() const
135 {
136 return vect.empty();
137 }
138
size()139 size_type size() const
140 {
141 return vect.size();
142 }
143
begin()144 iterator begin()
145 {
146 return vect.begin();
147 }
148
end()149 iterator end()
150 {
151 return vect.end();
152 }
153
push(T x)154 void push(T x)
155 {
156 vect.push_back(x);
157 }
158
pop()159 void pop()
160 {
161 vect.pop_back();
162 }
163
top()164 T top()
165 {
166 return vect.back();
167 }
168
clear()169 void clear()
170 {
171 vect.resize(0);
172 }
173
174 private:
175 MapleVector<T> vect;
176 };
177
178 template <typename T>
179 using MapleList = std::list<T, MapleAllocatorAdapter<T>>;
180
181 template <typename T>
182 using MapleForwardList = std::forward_list<T, MapleAllocatorAdapter<T>>;
183
184 template <typename T, typename Comparator = std::less<T>>
185 using MapleSet = std::set<T, Comparator, MapleAllocatorAdapter<T>>;
186
187 template <typename T, typename Hash = std::hash<T>, typename Equal = std::equal_to<T>>
188 using MapleUnorderedSet = std::unordered_set<T, Hash, Equal, MapleAllocatorAdapter<T>>;
189
190 template <typename K, typename V, typename Comparator = std::less<K>>
191 using MapleMap = std::map<K, V, Comparator, MapleAllocatorAdapter<std::pair<const K, V>>>;
192
193 template <typename K, typename V, typename Comparator = std::less<K>>
194 using MapleMultiMap = std::multimap<K, V, Comparator, MapleAllocatorAdapter<std::pair<const K, V>>>;
195
196 template <typename T, typename Comparator = std::less<T>>
197 using MapleMultiSet = std::multiset<T, Comparator, MapleAllocatorAdapter<T>>;
198
199 template <typename K, typename V, typename Hash = std::hash<K>, typename Equal = std::equal_to<K>>
200 using MapleUnorderedMap = std::unordered_map<K, V, Hash, Equal, MapleAllocatorAdapter<std::pair<const K, V>>>;
201
202 template <typename K, typename V, typename Hash = std::hash<K>, typename Equal = std::equal_to<K>>
203 using MapleUnorderedMultiMap = std::unordered_multimap<K, V, Hash, Equal, MapleAllocatorAdapter<std::pair<const K, V>>>;
204
205 // Implementation details below.
206 template <>
207 class MapleAllocatorAdapter<void> {
208 public:
209 using value_type = void;
210 using pointer = void *;
211 using const_pointer = const void *;
212 template <typename U>
213 struct rebind {
214 using other = MapleAllocatorAdapter<U>;
215 };
216
MapleAllocatorAdapter(MapleAllocator & currMapleAllocator)217 explicit MapleAllocatorAdapter(MapleAllocator &currMapleAllocator) : mapleAllocator(&currMapleAllocator) {}
218
219 template <typename U>
MapleAllocatorAdapter(const MapleAllocatorAdapter<U> & other)220 MapleAllocatorAdapter(const MapleAllocatorAdapter<U> &other) : mapleAllocator(other.mapleAllocator)
221 {
222 }
223
224 MapleAllocatorAdapter(const MapleAllocatorAdapter &other) = default;
225 MapleAllocatorAdapter &operator=(const MapleAllocatorAdapter &other) = default;
226 ~MapleAllocatorAdapter() = default;
227
228 private:
229 template <typename U>
230 friend class MapleAllocatorAdapter;
231 MapleAllocator *mapleAllocator;
232 };
233
234 template <typename T>
235 class MapleAllocatorAdapter {
236 public:
237 using value_type = T;
238 using pointer = T *;
239 using reference = T &;
240 using const_pointer = const T *;
241 using const_reference = const T &;
242 using size_type = size_t;
243 using difference_type = std::ptrdiff_t;
244 template <typename U>
245 struct rebind {
246 using other = MapleAllocatorAdapter<U>;
247 };
248
MapleAllocatorAdapter(MapleAllocator & currMapleAllocator)249 explicit MapleAllocatorAdapter(MapleAllocator &currMapleAllocator) : mapleAllocator(&currMapleAllocator) {}
250
251 template <typename U>
MapleAllocatorAdapter(const MapleAllocatorAdapter<U> & other)252 MapleAllocatorAdapter(const MapleAllocatorAdapter<U> &other) : mapleAllocator(other.mapleAllocator)
253 {
254 }
255
256 MapleAllocatorAdapter(const MapleAllocatorAdapter &other) = default;
257 MapleAllocatorAdapter &operator=(const MapleAllocatorAdapter &other) = default;
258 ~MapleAllocatorAdapter() = default;
max_size()259 size_type max_size() const
260 {
261 return static_cast<size_type>(-1) / sizeof(T);
262 }
263
address(reference x)264 pointer address(reference x) const
265 {
266 return &x;
267 }
268
address(const_reference x)269 const_pointer address(const_reference x) const
270 {
271 return &x;
272 }
273
allocate(size_type n)274 pointer allocate(size_type n)
275 {
276 return reinterpret_cast<T *>(mapleAllocator->Alloc(n * sizeof(T)));
277 }
278
deallocate(pointer,size_type)279 void deallocate(pointer, size_type) {}
280
construct(const pointer p,const_reference val)281 void construct(const pointer p, const_reference val)
282 {
283 new (static_cast<void *>(p)) value_type(val);
284 }
285
destroy(const pointer p)286 void destroy(const pointer p)
287 {
288 CHECK_NULL_FATAL(p);
289 p->~value_type();
290 }
291
292 private:
293 template <typename U>
294 friend class MapleAllocatorAdapter;
295 template <typename U>
296 friend bool operator==(const MapleAllocatorAdapter<U> &lhs, const MapleAllocatorAdapter<U> &rhs);
297 MapleAllocator *mapleAllocator;
298 };
299
300 template <typename T>
301 inline bool operator==(const MapleAllocatorAdapter<T> &lhs, const MapleAllocatorAdapter<T> &rhs)
302 {
303 return lhs.mapleAllocator == rhs.mapleAllocator;
304 }
305
306 template <typename T>
307 inline bool operator!=(const MapleAllocatorAdapter<T> &lhs, const MapleAllocatorAdapter<T> &rhs)
308 {
309 return !(lhs == rhs);
310 }
311
Adapter()312 inline MapleAllocatorAdapter<void> MapleAllocator::Adapter()
313 {
314 return MapleAllocatorAdapter<void>(*this);
315 }
316 } // namespace maple
317 #endif // MEMPOOL_INCLUDE_MEMPOOL_ALLOCATOR_H
318