/* * 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_RUNTIME_BASE_ARENA_CONTAINERS_H_ #define ART_RUNTIME_BASE_ARENA_CONTAINERS_H_ #include #include #include #include #include "arena_allocator.h" #include "base/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 ArenaQueue = std::queue>; template using ArenaVector = dchecked_vector>; template > using ArenaSet = std::set>; template > using ArenaSafeMap = SafeMap>>; template , typename HashFn = std::hash, typename Pred = std::equal_to> using ArenaHashSet = HashSet>; template >, typename HashFn = std::hash, typename Pred = std::equal_to> using ArenaHashMap = HashMap>>; // 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_; }; typedef ArenaAllocatorAdapterKindImpl ArenaAllocatorAdapterKind; template <> class ArenaAllocatorAdapter : private ArenaAllocatorAdapterKind { public: typedef void value_type; typedef void* pointer; typedef const void* const_pointer; template struct rebind { typedef ArenaAllocatorAdapter other; }; explicit ArenaAllocatorAdapter(ArenaAllocator* arena_allocator, ArenaAllocKind kind = kArenaAllocSTL) : ArenaAllocatorAdapterKind(kind), arena_allocator_(arena_allocator) { } template ArenaAllocatorAdapter(const ArenaAllocatorAdapter& other) : ArenaAllocatorAdapterKind(other), arena_allocator_(other.arena_allocator_) { } ArenaAllocatorAdapter(const ArenaAllocatorAdapter&) = default; ArenaAllocatorAdapter& operator=(const ArenaAllocatorAdapter&) = default; ~ArenaAllocatorAdapter() = default; private: ArenaAllocator* arena_allocator_; template friend class ArenaAllocatorAdapter; }; template class ArenaAllocatorAdapter : private ArenaAllocatorAdapterKind { public: typedef T value_type; typedef T* pointer; typedef T& reference; typedef const T* const_pointer; typedef const T& const_reference; typedef size_t size_type; typedef ptrdiff_t difference_type; template struct rebind { typedef ArenaAllocatorAdapter other; }; ArenaAllocatorAdapter(ArenaAllocator* arena_allocator, ArenaAllocKind kind) : ArenaAllocatorAdapterKind(kind), arena_allocator_(arena_allocator) { } template ArenaAllocatorAdapter(const ArenaAllocatorAdapter& other) : ArenaAllocatorAdapterKind(other), arena_allocator_(other.arena_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 arena_allocator_->AllocArray(n, ArenaAllocatorAdapterKind::Kind()); } void deallocate(pointer p, size_type n) { arena_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* arena_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.arena_allocator_ == rhs.arena_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_RUNTIME_BASE_ARENA_CONTAINERS_H_