blob: 7c64449dd9e76a7d924fba1cd68ba0f3cdec6620 [file] [log] [blame]
Vladimir Marko69f08ba2014-04-11 12:28:11 +01001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mathieu Chartierb666f482015-02-18 14:33:14 -080017#ifndef ART_RUNTIME_BASE_SCOPED_ARENA_CONTAINERS_H_
18#define ART_RUNTIME_BASE_SCOPED_ARENA_CONTAINERS_H_
Vladimir Marko69f08ba2014-04-11 12:28:11 +010019
Vladimir Marko622bdbe2014-06-19 14:59:05 +010020#include <deque>
21#include <queue>
Vladimir Marko69f08ba2014-04-11 12:28:11 +010022#include <set>
Mathieu Chartiere401d142015-04-22 13:56:20 -070023#include <unordered_map>
Vladimir Marko1f497642015-10-05 20:34:42 +010024#include <utility>
Vladimir Marko69f08ba2014-04-11 12:28:11 +010025
Mathieu Chartierb666f482015-02-18 14:33:14 -080026#include "arena_containers.h" // For ArenaAllocatorAdapterKind.
Vladimir Markoec7802a2015-10-01 20:57:57 +010027#include "base/dchecked_vector.h"
Mathieu Chartierb666f482015-02-18 14:33:14 -080028#include "scoped_arena_allocator.h"
Vladimir Marko69f08ba2014-04-11 12:28:11 +010029#include "safe_map.h"
30
31namespace art {
32
Vladimir Marko8081d2b2014-07-31 15:33:43 +010033// Adapter for use of ScopedArenaAllocator in STL containers.
34// Use ScopedArenaAllocator::Adapter() to create an adapter to pass to container constructors.
35// For example,
36// void foo(ScopedArenaAllocator* allocator) {
37// ScopedArenaVector<int> foo_vector(allocator->Adapter(kArenaAllocMisc));
38// ScopedArenaSafeMap<int, int> foo_map(std::less<int>(), allocator->Adapter());
39// // Use foo_vector and foo_map...
40// }
41template <typename T>
42class ScopedArenaAllocatorAdapter;
43
Vladimir Marko69f08ba2014-04-11 12:28:11 +010044template <typename T>
Vladimir Marko622bdbe2014-06-19 14:59:05 +010045using ScopedArenaDeque = std::deque<T, ScopedArenaAllocatorAdapter<T>>;
46
47template <typename T>
48using ScopedArenaQueue = std::queue<T, ScopedArenaDeque<T>>;
49
50template <typename T>
Vladimir Markoec7802a2015-10-01 20:57:57 +010051using ScopedArenaVector = dchecked_vector<T, ScopedArenaAllocatorAdapter<T>>;
Vladimir Marko69f08ba2014-04-11 12:28:11 +010052
Ian Rogers700a4022014-05-19 16:49:03 -070053template <typename T, typename Comparator = std::less<T>>
54using ScopedArenaSet = std::set<T, Comparator, ScopedArenaAllocatorAdapter<T>>;
Vladimir Marko69f08ba2014-04-11 12:28:11 +010055
Ian Rogers700a4022014-05-19 16:49:03 -070056template <typename K, typename V, typename Comparator = std::less<K>>
Vladimir Marko69f08ba2014-04-11 12:28:11 +010057using ScopedArenaSafeMap =
Ian Rogers700a4022014-05-19 16:49:03 -070058 SafeMap<K, V, Comparator, ScopedArenaAllocatorAdapter<std::pair<const K, V>>>;
Vladimir Marko69f08ba2014-04-11 12:28:11 +010059
Mathieu Chartiere401d142015-04-22 13:56:20 -070060template <typename K, typename V, class Hash = std::hash<K>, class KeyEqual = std::equal_to<K>>
61using ScopedArenaUnorderedMap =
62 std::unordered_map<K, V, Hash, KeyEqual, ScopedArenaAllocatorAdapter<std::pair<const K, V>>>;
63
64
Vladimir Marko8081d2b2014-07-31 15:33:43 +010065// Implementation details below.
66
67template <>
68class ScopedArenaAllocatorAdapter<void>
69 : private DebugStackReference, private DebugStackIndirectTopRef,
70 private ArenaAllocatorAdapterKind {
71 public:
72 typedef void value_type;
73 typedef void* pointer;
74 typedef const void* const_pointer;
75
76 template <typename U>
77 struct rebind {
78 typedef ScopedArenaAllocatorAdapter<U> other;
79 };
80
81 explicit ScopedArenaAllocatorAdapter(ScopedArenaAllocator* arena_allocator,
82 ArenaAllocKind kind = kArenaAllocSTL)
83 : DebugStackReference(arena_allocator),
84 DebugStackIndirectTopRef(arena_allocator),
85 ArenaAllocatorAdapterKind(kind),
86 arena_stack_(arena_allocator->arena_stack_) {
87 }
88 template <typename U>
89 ScopedArenaAllocatorAdapter(const ScopedArenaAllocatorAdapter<U>& other)
90 : DebugStackReference(other),
91 DebugStackIndirectTopRef(other),
92 ArenaAllocatorAdapterKind(other),
93 arena_stack_(other.arena_stack_) {
94 }
Andreas Gampec801f0d2015-02-24 20:55:16 -080095 ScopedArenaAllocatorAdapter(const ScopedArenaAllocatorAdapter&) = default;
96 ScopedArenaAllocatorAdapter& operator=(const ScopedArenaAllocatorAdapter&) = default;
Vladimir Marko8081d2b2014-07-31 15:33:43 +010097 ~ScopedArenaAllocatorAdapter() = default;
98
99 private:
100 ArenaStack* arena_stack_;
101
102 template <typename U>
103 friend class ScopedArenaAllocatorAdapter;
104};
105
106template <typename T>
107class ScopedArenaAllocatorAdapter
108 : private DebugStackReference, private DebugStackIndirectTopRef,
109 private ArenaAllocatorAdapterKind {
110 public:
111 typedef T value_type;
112 typedef T* pointer;
113 typedef T& reference;
114 typedef const T* const_pointer;
115 typedef const T& const_reference;
116 typedef size_t size_type;
117 typedef ptrdiff_t difference_type;
118
119 template <typename U>
120 struct rebind {
121 typedef ScopedArenaAllocatorAdapter<U> other;
122 };
123
124 explicit ScopedArenaAllocatorAdapter(ScopedArenaAllocator* arena_allocator,
125 ArenaAllocKind kind = kArenaAllocSTL)
126 : DebugStackReference(arena_allocator),
127 DebugStackIndirectTopRef(arena_allocator),
128 ArenaAllocatorAdapterKind(kind),
129 arena_stack_(arena_allocator->arena_stack_) {
130 }
131 template <typename U>
132 ScopedArenaAllocatorAdapter(const ScopedArenaAllocatorAdapter<U>& other)
133 : DebugStackReference(other),
134 DebugStackIndirectTopRef(other),
135 ArenaAllocatorAdapterKind(other),
136 arena_stack_(other.arena_stack_) {
137 }
Andreas Gampec801f0d2015-02-24 20:55:16 -0800138 ScopedArenaAllocatorAdapter(const ScopedArenaAllocatorAdapter&) = default;
139 ScopedArenaAllocatorAdapter& operator=(const ScopedArenaAllocatorAdapter&) = default;
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100140 ~ScopedArenaAllocatorAdapter() = default;
141
142 size_type max_size() const {
143 return static_cast<size_type>(-1) / sizeof(T);
144 }
145
146 pointer address(reference x) const { return &x; }
147 const_pointer address(const_reference x) const { return &x; }
148
149 pointer allocate(size_type n, ScopedArenaAllocatorAdapter<void>::pointer hint = nullptr) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700150 UNUSED(hint);
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100151 DCHECK_LE(n, max_size());
152 DebugStackIndirectTopRef::CheckTop();
153 return reinterpret_cast<T*>(arena_stack_->Alloc(n * sizeof(T),
154 ArenaAllocatorAdapterKind::Kind()));
155 }
156 void deallocate(pointer p, size_type n) {
157 DebugStackIndirectTopRef::CheckTop();
Vladimir Marko2a408a32015-09-18 14:11:00 +0100158 arena_stack_->MakeInaccessible(p, sizeof(T) * n);
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100159 }
160
Vladimir Marko1f497642015-10-05 20:34:42 +0100161 template <typename U, typename... Args>
162 void construct(U* p, Args&&... args) {
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100163 // Don't CheckTop(), allow reusing existing capacity of a vector/deque below the top.
Vladimir Marko1f497642015-10-05 20:34:42 +0100164 ::new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100165 }
Vladimir Marko1f497642015-10-05 20:34:42 +0100166 template <typename U>
167 void destroy(U* p) {
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100168 // Don't CheckTop(), allow reusing existing capacity of a vector/deque below the top.
Vladimir Marko1f497642015-10-05 20:34:42 +0100169 p->~U();
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100170 }
171
172 private:
173 ArenaStack* arena_stack_;
174
175 template <typename U>
176 friend class ScopedArenaAllocatorAdapter;
177
178 template <typename U>
179 friend bool operator==(const ScopedArenaAllocatorAdapter<U>& lhs,
180 const ScopedArenaAllocatorAdapter<U>& rhs);
181};
182
183template <typename T>
184inline bool operator==(const ScopedArenaAllocatorAdapter<T>& lhs,
185 const ScopedArenaAllocatorAdapter<T>& rhs) {
186 return lhs.arena_stack_ == rhs.arena_stack_;
187}
188
189template <typename T>
190inline bool operator!=(const ScopedArenaAllocatorAdapter<T>& lhs,
191 const ScopedArenaAllocatorAdapter<T>& rhs) {
192 return !(lhs == rhs);
193}
194
195inline ScopedArenaAllocatorAdapter<void> ScopedArenaAllocator::Adapter(ArenaAllocKind kind) {
196 return ScopedArenaAllocatorAdapter<void>(this, kind);
197}
198
Vladimir Marko69f08ba2014-04-11 12:28:11 +0100199} // namespace art
200
Mathieu Chartierb666f482015-02-18 14:33:14 -0800201#endif // ART_RUNTIME_BASE_SCOPED_ARENA_CONTAINERS_H_