Home | History | Annotate | Download | only in base
      1 /*
      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 
     17 #ifndef ART_RUNTIME_BASE_ARENA_CONTAINERS_H_
     18 #define ART_RUNTIME_BASE_ARENA_CONTAINERS_H_
     19 
     20 #include <deque>
     21 #include <queue>
     22 #include <set>
     23 #include <utility>
     24 
     25 #include "arena_allocator.h"
     26 #include "base/dchecked_vector.h"
     27 #include "hash_map.h"
     28 #include "hash_set.h"
     29 #include "safe_map.h"
     30 
     31 namespace art {
     32 
     33 // Adapter for use of ArenaAllocator in STL containers.
     34 // Use ArenaAllocator::Adapter() to create an adapter to pass to container constructors.
     35 // For example,
     36 //   struct Foo {
     37 //     explicit Foo(ArenaAllocator* allocator)
     38 //         : foo_vector(allocator->Adapter(kArenaAllocMisc)),
     39 //           foo_map(std::less<int>(), allocator->Adapter()) {
     40 //     }
     41 //     ArenaVector<int> foo_vector;
     42 //     ArenaSafeMap<int, int> foo_map;
     43 //   };
     44 template <typename T>
     45 class ArenaAllocatorAdapter;
     46 
     47 template <typename T>
     48 using ArenaDeque = std::deque<T, ArenaAllocatorAdapter<T>>;
     49 
     50 template <typename T>
     51 using ArenaQueue = std::queue<T, ArenaDeque<T>>;
     52 
     53 template <typename T>
     54 using ArenaVector = dchecked_vector<T, ArenaAllocatorAdapter<T>>;
     55 
     56 template <typename T, typename Comparator = std::less<T>>
     57 using ArenaSet = std::set<T, Comparator, ArenaAllocatorAdapter<T>>;
     58 
     59 template <typename K, typename V, typename Comparator = std::less<K>>
     60 using ArenaSafeMap =
     61     SafeMap<K, V, Comparator, ArenaAllocatorAdapter<std::pair<const K, V>>>;
     62 
     63 template <typename T,
     64           typename EmptyFn = DefaultEmptyFn<T>,
     65           typename HashFn = std::hash<T>,
     66           typename Pred = std::equal_to<T>>
     67 using ArenaHashSet = HashSet<T, EmptyFn, HashFn, Pred, ArenaAllocatorAdapter<T>>;
     68 
     69 template <typename Key,
     70           typename Value,
     71           typename EmptyFn = DefaultEmptyFn<std::pair<Key, Value>>,
     72           typename HashFn = std::hash<Key>,
     73           typename Pred = std::equal_to<Key>>
     74 using ArenaHashMap = HashMap<Key,
     75                              Value,
     76                              EmptyFn,
     77                              HashFn,
     78                              Pred,
     79                              ArenaAllocatorAdapter<std::pair<Key, Value>>>;
     80 
     81 // Implementation details below.
     82 
     83 template <bool kCount>
     84 class ArenaAllocatorAdapterKindImpl;
     85 
     86 template <>
     87 class ArenaAllocatorAdapterKindImpl<false> {
     88  public:
     89   // Not tracking allocations, ignore the supplied kind and arbitrarily provide kArenaAllocSTL.
     90   explicit ArenaAllocatorAdapterKindImpl(ArenaAllocKind kind ATTRIBUTE_UNUSED) {}
     91   ArenaAllocatorAdapterKindImpl(const ArenaAllocatorAdapterKindImpl&) = default;
     92   ArenaAllocatorAdapterKindImpl& operator=(const ArenaAllocatorAdapterKindImpl&) = default;
     93   ArenaAllocKind Kind() { return kArenaAllocSTL; }
     94 };
     95 
     96 template <bool kCount>
     97 class ArenaAllocatorAdapterKindImpl {
     98  public:
     99   explicit ArenaAllocatorAdapterKindImpl(ArenaAllocKind kind) : kind_(kind) { }
    100   ArenaAllocatorAdapterKindImpl(const ArenaAllocatorAdapterKindImpl&) = default;
    101   ArenaAllocatorAdapterKindImpl& operator=(const ArenaAllocatorAdapterKindImpl&) = default;
    102   ArenaAllocKind Kind() { return kind_; }
    103 
    104  private:
    105   ArenaAllocKind kind_;
    106 };
    107 
    108 typedef ArenaAllocatorAdapterKindImpl<kArenaAllocatorCountAllocations> ArenaAllocatorAdapterKind;
    109 
    110 template <>
    111 class ArenaAllocatorAdapter<void> : private ArenaAllocatorAdapterKind {
    112  public:
    113   typedef void value_type;
    114   typedef void* pointer;
    115   typedef const void* const_pointer;
    116 
    117   template <typename U>
    118   struct rebind {
    119     typedef ArenaAllocatorAdapter<U> other;
    120   };
    121 
    122   explicit ArenaAllocatorAdapter(ArenaAllocator* arena_allocator,
    123                                  ArenaAllocKind kind = kArenaAllocSTL)
    124       : ArenaAllocatorAdapterKind(kind),
    125         arena_allocator_(arena_allocator) {
    126   }
    127   template <typename U>
    128   ArenaAllocatorAdapter(const ArenaAllocatorAdapter<U>& other)
    129       : ArenaAllocatorAdapterKind(other),
    130         arena_allocator_(other.arena_allocator_) {
    131   }
    132   ArenaAllocatorAdapter(const ArenaAllocatorAdapter&) = default;
    133   ArenaAllocatorAdapter& operator=(const ArenaAllocatorAdapter&) = default;
    134   ~ArenaAllocatorAdapter() = default;
    135 
    136  private:
    137   ArenaAllocator* arena_allocator_;
    138 
    139   template <typename U>
    140   friend class ArenaAllocatorAdapter;
    141 };
    142 
    143 template <typename T>
    144 class ArenaAllocatorAdapter : private ArenaAllocatorAdapterKind {
    145  public:
    146   typedef T value_type;
    147   typedef T* pointer;
    148   typedef T& reference;
    149   typedef const T* const_pointer;
    150   typedef const T& const_reference;
    151   typedef size_t size_type;
    152   typedef ptrdiff_t difference_type;
    153 
    154   template <typename U>
    155   struct rebind {
    156     typedef ArenaAllocatorAdapter<U> other;
    157   };
    158 
    159   ArenaAllocatorAdapter(ArenaAllocator* arena_allocator, ArenaAllocKind kind)
    160       : ArenaAllocatorAdapterKind(kind),
    161         arena_allocator_(arena_allocator) {
    162   }
    163   template <typename U>
    164   ArenaAllocatorAdapter(const ArenaAllocatorAdapter<U>& other)
    165       : ArenaAllocatorAdapterKind(other),
    166         arena_allocator_(other.arena_allocator_) {
    167   }
    168   ArenaAllocatorAdapter(const ArenaAllocatorAdapter&) = default;
    169   ArenaAllocatorAdapter& operator=(const ArenaAllocatorAdapter&) = default;
    170   ~ArenaAllocatorAdapter() = default;
    171 
    172   size_type max_size() const {
    173     return static_cast<size_type>(-1) / sizeof(T);
    174   }
    175 
    176   pointer address(reference x) const { return &x; }
    177   const_pointer address(const_reference x) const { return &x; }
    178 
    179   pointer allocate(size_type n,
    180                    ArenaAllocatorAdapter<void>::pointer hint ATTRIBUTE_UNUSED = nullptr) {
    181     DCHECK_LE(n, max_size());
    182     return arena_allocator_->AllocArray<T>(n, ArenaAllocatorAdapterKind::Kind());
    183   }
    184   void deallocate(pointer p, size_type n) {
    185     arena_allocator_->MakeInaccessible(p, sizeof(T) * n);
    186   }
    187 
    188   template <typename U, typename... Args>
    189   void construct(U* p, Args&&... args) {
    190     ::new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
    191   }
    192   template <typename U>
    193   void destroy(U* p) {
    194     p->~U();
    195   }
    196 
    197  private:
    198   ArenaAllocator* arena_allocator_;
    199 
    200   template <typename U>
    201   friend class ArenaAllocatorAdapter;
    202 
    203   template <typename U>
    204   friend bool operator==(const ArenaAllocatorAdapter<U>& lhs,
    205                          const ArenaAllocatorAdapter<U>& rhs);
    206 };
    207 
    208 template <typename T>
    209 inline bool operator==(const ArenaAllocatorAdapter<T>& lhs,
    210                        const ArenaAllocatorAdapter<T>& rhs) {
    211   return lhs.arena_allocator_ == rhs.arena_allocator_;
    212 }
    213 
    214 template <typename T>
    215 inline bool operator!=(const ArenaAllocatorAdapter<T>& lhs,
    216                        const ArenaAllocatorAdapter<T>& rhs) {
    217   return !(lhs == rhs);
    218 }
    219 
    220 inline ArenaAllocatorAdapter<void> ArenaAllocator::Adapter(ArenaAllocKind kind) {
    221   return ArenaAllocatorAdapter<void>(this, kind);
    222 }
    223 
    224 }  // namespace art
    225 
    226 #endif  // ART_RUNTIME_BASE_ARENA_CONTAINERS_H_
    227