/* * Copyright (C) 2016 The Android Open Source Project * * 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 LIBMEMUNREACHABLE_ALLOCATOR_H_ #define LIBMEMUNREACHABLE_ALLOCATOR_H_ #include #include #include #include #include #include #include #include #include #include extern std::atomic heap_count; class HeapImpl; template class Allocator; // Non-templated class that implements wraps HeapImpl to keep // implementation out of the header file class Heap { public: Heap(); ~Heap(); // Copy constructor that does not take ownership of impl_ Heap(const Heap& other) : impl_(other.impl_), owns_impl_(false) {} // Assignment disabled Heap& operator=(const Heap&) = delete; // Allocate size bytes void* allocate(size_t size); // Deallocate allocation returned by allocate void deallocate(void*); bool empty(); static void deallocate(HeapImpl* impl, void* ptr); // Allocate a class of type T template T* allocate() { return reinterpret_cast(allocate(sizeof(T))); } // Comparators, copied objects will be equal bool operator ==(const Heap& other) const { return impl_ == other.impl_; } bool operator !=(const Heap& other) const { return !(*this == other); } // std::unique_ptr wrapper that allocates using allocate and deletes using // deallocate template using unique_ptr = std::unique_ptr>; template unique_ptr make_unique(Args&&... args) { HeapImpl* impl = impl_; return unique_ptr(new (allocate()) T(std::forward(args)...), [impl](void* ptr) { reinterpret_cast(ptr)->~T(); deallocate(impl, ptr); }); } // std::unique_ptr wrapper that allocates using allocate and deletes using // deallocate template using shared_ptr = std::shared_ptr; template shared_ptr make_shared(Args&&... args); protected: HeapImpl* impl_; bool owns_impl_; }; // STLAllocator implements the std allocator interface on top of a Heap template class STLAllocator { public: using value_type = T; ~STLAllocator() { } // Construct an STLAllocator on top of a Heap STLAllocator(const Heap& heap) : heap_(heap) { } // Rebind an STLAllocator from an another STLAllocator template STLAllocator(const STLAllocator& other) : heap_(other.heap_) { } STLAllocator(const STLAllocator&) = default; STLAllocator& operator=(const STLAllocator&) = default; T* allocate(std::size_t n) { return reinterpret_cast(heap_.allocate(n * sizeof(T))); } void deallocate(T* ptr, std::size_t) { heap_.deallocate(ptr); } template bool operator ==(const STLAllocator& other) const { return heap_ == other.heap_; } template inline bool operator !=(const STLAllocator& other) const { return !(this == other); } template friend class STLAllocator; protected: Heap heap_; }; // Allocator extends STLAllocator with some convenience methods for allocating // a single object and for constructing unique_ptr and shared_ptr objects with // appropriate deleters. template class Allocator : public STLAllocator { public: ~Allocator() {} Allocator(const Heap& other) : STLAllocator(other) { } template Allocator(const STLAllocator& other) : STLAllocator(other) { } Allocator(const Allocator&) = default; Allocator& operator=(const Allocator&) = default; using STLAllocator::allocate; using STLAllocator::deallocate; using STLAllocator::heap_; T* allocate() { return STLAllocator::allocate(1); } void deallocate(void* ptr) { heap_.deallocate(ptr); } using shared_ptr = Heap::shared_ptr; template shared_ptr make_shared(Args&& ...args) { return heap_.template make_shared(std::forward(args)...); } using unique_ptr = Heap::unique_ptr; template unique_ptr make_unique(Args&& ...args) { return heap_.template make_unique(std::forward(args)...); } }; // std::unique_ptr wrapper that allocates using allocate and deletes using // deallocate. Implemented outside class definition in order to pass // Allocator to shared_ptr. template inline Heap::shared_ptr Heap::make_shared(Args&&... args) { return std::allocate_shared, Args...>(Allocator(*this), std::forward(args)...); } namespace allocator { template using vector = std::vector>; template using list = std::list>; template> using map = std::map>>; template, class KeyEqual = std::equal_to> using unordered_map = std::unordered_map>>; template, class KeyEqual = std::equal_to> using unordered_set = std::unordered_set>; template> using set = std::set>; using string = std::basic_string, Allocator>; } #endif