/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef MEMPOOL_INCLUDE_MEMPOOL_ALLOCATOR_H #define MEMPOOL_INCLUDE_MEMPOOL_ALLOCATOR_H #include #include #include #include #include #include #include #include #include #include #include "mempool.h" namespace maple { template class MapleAllocatorAdapter; // circular dependency exists, no other choice class MapleAllocator { public: explicit MapleAllocator(MemPool *m) : memPool(m) {} virtual ~MapleAllocator() = default; // Get adapter for use in STL containers. See arena_containers.h . MapleAllocatorAdapter Adapter(); virtual void *Alloc(size_t bytes) { return (memPool != nullptr) ? memPool->Malloc(bytes) : nullptr; } template T *New(Arguments &&... args) { void *p = memPool->Malloc(sizeof(T)); DEBUG_ASSERT(p != nullptr, "ERROR: New error"); p = new (p) T(std::forward(args)...); return static_cast(p); } MemPool *GetMemPool() const { return memPool; } void SetMemPool(MemPool *m) { memPool = m; } protected: MemPool *memPool; template friend class MapleAllocatorAdapter; }; // MapleAllocator // must be destroyed, otherwise there will be memory leak // only one allocater can be used at the same time class LocalMapleAllocator : public MapleAllocator { public: explicit LocalMapleAllocator(StackMemPool &m) : MapleAllocator(&m), fixedStackTopMark(m.fixedMemStackTop), bigStackTopMark(m.bigMemStackTop), fixedCurPtrMark(m.curPtr), bigCurPtrMark(m.bigCurPtr) { m.PushAllocator(this); } ~LocalMapleAllocator() override { static_cast(memPool)->ResetStackTop(this, fixedCurPtrMark, fixedStackTopMark, bigCurPtrMark, bigStackTopMark); }; StackMemPool &GetStackMemPool() const { return static_cast(*memPool); } MemPool *GetMemPool() const = delete; void *Alloc(size_t bytes) override { static_cast(memPool)->CheckTopAllocator(this); return memPool->Malloc(bytes); } private: using MapleAllocator::MapleAllocator; MemBlock *const fixedStackTopMark; MemBlock *const bigStackTopMark; uint8_t *const fixedCurPtrMark; uint8_t *const bigCurPtrMark; }; template class MapleAllocatorAdapter; // circular dependency exists, no other choice template using MapleQueue = std::deque>; template using MapleVector = std::vector>; template class MapleStack { public: using size_type = typename MapleVector::size_type; using iterator = typename MapleVector::iterator; MapleStack(MapleAllocatorAdapter adapter) : vect(adapter) {} ~MapleStack() = default; MapleVector &GetVector() { return vect; } bool empty() const { return vect.empty(); } size_type size() const { return vect.size(); } iterator begin() { return vect.begin(); } iterator end() { return vect.end(); } void push(T x) { vect.push_back(x); } void pop() { vect.pop_back(); } T top() { return vect.back(); } void clear() { vect.resize(0); } private: MapleVector vect; }; template using MapleList = std::list>; template using MapleForwardList = std::forward_list>; template > using MapleSet = std::set>; template , typename Equal = std::equal_to> using MapleUnorderedSet = std::unordered_set>; template > using MapleMap = std::map>>; template > using MapleMultiMap = std::multimap>>; template > using MapleMultiSet = std::multiset>; template , typename Equal = std::equal_to> using MapleUnorderedMap = std::unordered_map>>; template , typename Equal = std::equal_to> using MapleUnorderedMultiMap = std::unordered_multimap>>; // Implementation details below. template <> class MapleAllocatorAdapter { public: using value_type = void; using pointer = void *; using const_pointer = const void *; template struct rebind { using other = MapleAllocatorAdapter; }; explicit MapleAllocatorAdapter(MapleAllocator &currMapleAllocator) : mapleAllocator(&currMapleAllocator) {} template MapleAllocatorAdapter(const MapleAllocatorAdapter &other) : mapleAllocator(other.mapleAllocator) { } MapleAllocatorAdapter(const MapleAllocatorAdapter &other) = default; MapleAllocatorAdapter &operator=(const MapleAllocatorAdapter &other) = default; ~MapleAllocatorAdapter() = default; private: template friend class MapleAllocatorAdapter; MapleAllocator *mapleAllocator; }; template class MapleAllocatorAdapter { public: using value_type = T; using pointer = T *; using reference = T &; using const_pointer = const T *; using const_reference = const T &; using size_type = size_t; using difference_type = std::ptrdiff_t; template struct rebind { using other = MapleAllocatorAdapter; }; explicit MapleAllocatorAdapter(MapleAllocator &currMapleAllocator) : mapleAllocator(&currMapleAllocator) {} template MapleAllocatorAdapter(const MapleAllocatorAdapter &other) : mapleAllocator(other.mapleAllocator) { } MapleAllocatorAdapter(const MapleAllocatorAdapter &other) = default; MapleAllocatorAdapter &operator=(const MapleAllocatorAdapter &other) = default; ~MapleAllocatorAdapter() = default; size_type max_size() const { return static_cast(-1) / sizeof(T); } pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } pointer allocate(size_type n) { return reinterpret_cast(mapleAllocator->Alloc(n * sizeof(T))); } void deallocate(pointer, size_type) {} void construct(const pointer p, const_reference val) { new (static_cast(p)) value_type(val); } void destroy(const pointer p) { CHECK_NULL_FATAL(p); p->~value_type(); } private: template friend class MapleAllocatorAdapter; template friend bool operator==(const MapleAllocatorAdapter &lhs, const MapleAllocatorAdapter &rhs); MapleAllocator *mapleAllocator; }; template inline bool operator==(const MapleAllocatorAdapter &lhs, const MapleAllocatorAdapter &rhs) { return lhs.mapleAllocator == rhs.mapleAllocator; } template inline bool operator!=(const MapleAllocatorAdapter &lhs, const MapleAllocatorAdapter &rhs) { return !(lhs == rhs); } inline MapleAllocatorAdapter MapleAllocator::Adapter() { return MapleAllocatorAdapter(*this); } } // namespace maple #endif // MEMPOOL_INCLUDE_MEMPOOL_ALLOCATOR_H