/* * Copyright (C) 2014 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 ART_LIBARTBASE_BASE_ARENA_CONTAINERS_H_ #define ART_LIBARTBASE_BASE_ARENA_CONTAINERS_H_ #include #include #include #include #include #include #include #include "arena_allocator.h" #include "dchecked_vector.h" #include "hash_map.h" #include "hash_set.h" #include "safe_map.h" namespace art { // Adapter for use of ArenaAllocator in STL containers. // Use ArenaAllocator::Adapter() to create an adapter to pass to container constructors. // For example, // struct Foo { // explicit Foo(ArenaAllocator* allocator) // : foo_vector(allocator->Adapter(kArenaAllocMisc)), // foo_map(std::less(), allocator->Adapter()) { // } // ArenaVector foo_vector; // ArenaSafeMap foo_map; // }; template class ArenaAllocatorAdapter; template using ArenaDeque = std::deque>; template using ArenaForwardList = std::forward_list>; template using ArenaQueue = std::queue>; template using ArenaVector = dchecked_vector>; template > using ArenaPriorityQueue = std::priority_queue, Comparator>; template using ArenaStdStack = std::stack>; template > using ArenaSet = std::set>; template > using ArenaSafeMap = SafeMap>>; template , typename HashFn = DefaultHashFn, typename Pred = DefaultPred> using ArenaHashSet = HashSet>; template >, typename HashFn = DefaultHashFn, typename Pred = DefaultPred> using ArenaHashMap = HashMap>>; template , typename Pred = std::equal_to> using ArenaUnorderedMap = std::unordered_map>>; // Implementation details below. template class ArenaAllocatorAdapterKindImpl; template <> class ArenaAllocatorAdapterKindImpl { public: // Not tracking allocations, ignore the supplied kind and arbitrarily provide kArenaAllocSTL. explicit ArenaAllocatorAdapterKindImpl(ArenaAllocKind kind ATTRIBUTE_UNUSED) {} ArenaAllocatorAdapterKindImpl(const ArenaAllocatorAdapterKindImpl&) = default; ArenaAllocatorAdapterKindImpl& operator=(const ArenaAllocatorAdapterKindImpl&) = default; ArenaAllocKind Kind() { return kArenaAllocSTL; } }; template class ArenaAllocatorAdapterKindImpl { public: explicit ArenaAllocatorAdapterKindImpl(ArenaAllocKind kind) : kind_(kind) { } ArenaAllocatorAdapterKindImpl(const ArenaAllocatorAdapterKindImpl&) = default; ArenaAllocatorAdapterKindImpl& operator=(const ArenaAllocatorAdapterKindImpl&) = default; ArenaAllocKind Kind() { return kind_; } private: ArenaAllocKind kind_; }; using ArenaAllocatorAdapterKind = ArenaAllocatorAdapterKindImpl; template <> class ArenaAllocatorAdapter : private ArenaAllocatorAdapterKind { public: using value_type = void; using pointer = void*; using const_pointer = const void*; template struct rebind { using other = ArenaAllocatorAdapter; }; explicit ArenaAllocatorAdapter(ArenaAllocator* allocator, ArenaAllocKind kind = kArenaAllocSTL) : ArenaAllocatorAdapterKind(kind), allocator_(allocator) { } template ArenaAllocatorAdapter(const ArenaAllocatorAdapter& other) : ArenaAllocatorAdapterKind(other), allocator_(other.allocator_) { } ArenaAllocatorAdapter(const ArenaAllocatorAdapter&) = default; ArenaAllocatorAdapter& operator=(const ArenaAllocatorAdapter&) = default; ~ArenaAllocatorAdapter() = default; private: ArenaAllocator* allocator_; template friend class ArenaAllocatorAdapter; }; template class ArenaAllocatorAdapter : private ArenaAllocatorAdapterKind { 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 = ptrdiff_t; template struct rebind { using other = ArenaAllocatorAdapter; }; ArenaAllocatorAdapter(ArenaAllocator* allocator, ArenaAllocKind kind) : ArenaAllocatorAdapterKind(kind), allocator_(allocator) { } template ArenaAllocatorAdapter(const ArenaAllocatorAdapter& other) : ArenaAllocatorAdapterKind(other), allocator_(other.allocator_) { } ArenaAllocatorAdapter(const ArenaAllocatorAdapter&) = default; ArenaAllocatorAdapter& operator=(const ArenaAllocatorAdapter&) = default; ~ArenaAllocatorAdapter() = 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, ArenaAllocatorAdapter::pointer hint ATTRIBUTE_UNUSED = nullptr) { DCHECK_LE(n, max_size()); return allocator_->AllocArray(n, ArenaAllocatorAdapterKind::Kind()); } void deallocate(pointer p, size_type n) { allocator_->MakeInaccessible(p, sizeof(T) * n); } template void construct(U* p, Args&&... args) { ::new (static_cast(p)) U(std::forward(args)...); } template void destroy(U* p) { p->~U(); } private: ArenaAllocator* allocator_; template friend class ArenaAllocatorAdapter; template friend bool operator==(const ArenaAllocatorAdapter& lhs, const ArenaAllocatorAdapter& rhs); }; template inline bool operator==(const ArenaAllocatorAdapter& lhs, const ArenaAllocatorAdapter& rhs) { return lhs.allocator_ == rhs.allocator_; } template inline bool operator!=(const ArenaAllocatorAdapter& lhs, const ArenaAllocatorAdapter& rhs) { return !(lhs == rhs); } inline ArenaAllocatorAdapter ArenaAllocator::Adapter(ArenaAllocKind kind) { return ArenaAllocatorAdapter(this, kind); } } // namespace art #endif // ART_LIBARTBASE_BASE_ARENA_CONTAINERS_H_