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