Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2015 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_VARIANT_MAP_H_
     18 #define ART_RUNTIME_BASE_VARIANT_MAP_H_
     19 
     20 #include <memory.h>
     21 #include <map>
     22 #include <type_traits>
     23 #include <utility>
     24 
     25 #include "base/stl_util.h"
     26 
     27 namespace art {
     28 
     29 //
     30 // A variant map is a heterogenous, type safe key->value map. It allows
     31 // for multiple different value types to be stored dynamically in the same map.
     32 //
     33 // It provides the following interface in a nutshell:
     34 //
     35 // struct VariantMap {
     36 //   template <typename TValue>
     37 //   TValue* Get(Key<T> key);  // null if the value was never set, otherwise the value.
     38 //
     39 //   template <typename TValue>
     40 //   void Set(Key<T> key, TValue value);
     41 // };
     42 //
     43 // Since the key is strongly typed at compile-time, it is impossible to accidentally
     44 // read/write a value with a different type than the key at either compile-time or run-time.
     45 //
     46 // Do not use VariantMap/VariantMapKey directly. Instead subclass each of them and use
     47 // the subclass, for example:
     48 //
     49 // template <typename TValue>
     50 // struct FruitMapKey : VariantMapKey<TValue> {
     51 //   FruitMapKey() {}
     52 // };
     53 //
     54 // struct FruitMap : VariantMap<FruitMap, FruitMapKey> {
     55 //   // This 'using' line is necessary to inherit the variadic constructor.
     56 //   using VariantMap<FruitMap, FruitMapKey>::VariantMap;
     57 //
     58 //   // Make the next '4' usages of Key slightly shorter to type.
     59 //   template <typename TValue>
     60 //   using Key = FruitMapKey<TValue>;
     61 //
     62 //   static const Key<int> Apple;
     63 //   static const Key<double> Orange;
     64 //   static const Key<std::string> Banana;
     65 // };
     66 //
     67 // const FruitMap::Key<int> FruitMap::Apple;
     68 // const FruitMap::Key<double> FruitMap::Orange;
     69 // const FruitMap::Key<std::string> Banana;
     70 //
     71 // See variant_map_test.cc for more examples.
     72 //
     73 
     74 // Implementation details for VariantMap.
     75 namespace detail {
     76   // Allocate a unique counter value each time it's called.
     77   struct VariantMapKeyCounterAllocator {
     78     static size_t AllocateCounter() {
     79       static size_t counter = 0;
     80       counter++;
     81 
     82       return counter;
     83     }
     84   };
     85 
     86   // Type-erased version of VariantMapKey<T>
     87   struct VariantMapKeyRaw {
     88     // TODO: this may need to call a virtual function to support string comparisons
     89     bool operator<(const VariantMapKeyRaw& other) const {
     90       return key_counter_ < other.key_counter_;
     91     }
     92 
     93     // The following functions need to be virtual since we don't know the compile-time type anymore:
     94 
     95     // Clone the key, creating a copy of the contents.
     96     virtual VariantMapKeyRaw* Clone() const = 0;
     97 
     98     // Delete a value whose runtime type is that of the non-erased key's TValue.
     99     virtual void ValueDelete(void* value) const = 0;
    100 
    101     // Clone a value whose runtime type is that of the non-erased key's TValue.
    102     virtual void* ValueClone(void* value) const = 0;
    103 
    104     // Compare one key to another (same as operator<).
    105     virtual bool Compare(const VariantMapKeyRaw* other) const {
    106       if (other == nullptr) {
    107         return false;
    108       }
    109       return key_counter_ < other->key_counter_;
    110     }
    111 
    112     virtual ~VariantMapKeyRaw() {}
    113 
    114    protected:
    115     VariantMapKeyRaw()
    116         : key_counter_(VariantMapKeyCounterAllocator::AllocateCounter()) {}
    117     // explicit VariantMapKeyRaw(size_t counter)
    118     //     : key_counter_(counter) {}
    119 
    120     size_t GetCounter() const {
    121       return key_counter_;
    122     }
    123 
    124    protected:
    125     // Avoid the object slicing problem; use Clone() instead.
    126     VariantMapKeyRaw(const VariantMapKeyRaw&) = default;
    127     VariantMapKeyRaw(VariantMapKeyRaw&&) = default;
    128 
    129    private:
    130     size_t key_counter_;  // Runtime type ID. Unique each time a new type is reified.
    131   };
    132 }  // namespace detail
    133 
    134 // The base type for keys used by the VariantMap. Users must subclass this type.
    135 template <typename TValue>
    136 struct VariantMapKey : detail::VariantMapKeyRaw {
    137   // Instantiate a default value for this key. If an explicit default value was provided
    138   // then that is used. Otherwise, the default value for the type TValue{} is returned.
    139   TValue CreateDefaultValue() const {
    140     if (default_value_ == nullptr) {
    141       return TValue{};  // NOLINT [readability/braces] [4]
    142     } else {
    143       return TValue(*default_value_);
    144     }
    145   }
    146 
    147  protected:
    148   // explicit VariantMapKey(size_t counter) : detail::VariantMapKeyRaw(counter) {}
    149   explicit VariantMapKey(const TValue& default_value)
    150     : default_value_(std::make_shared<TValue>(default_value)) {}
    151   explicit VariantMapKey(TValue&& default_value)
    152     : default_value_(std::make_shared<TValue>(default_value)) {}
    153   VariantMapKey() {}
    154   virtual ~VariantMapKey() {}
    155 
    156  private:
    157   virtual VariantMapKeyRaw* Clone() const {
    158     return new VariantMapKey<TValue>(*this);
    159   }
    160 
    161   virtual void* ValueClone(void* value) const {
    162     if (value == nullptr) {
    163       return nullptr;
    164     }
    165 
    166     TValue* strong_value = reinterpret_cast<TValue*>(value);
    167     return new TValue(*strong_value);
    168   }
    169 
    170   virtual void ValueDelete(void* value) const {
    171     if (value == nullptr) {
    172       return;
    173     }
    174 
    175     // Smartly invoke the proper delete/delete[]/etc
    176     const std::default_delete<TValue> deleter = std::default_delete<TValue>();
    177     deleter(reinterpret_cast<TValue*>(value));
    178   }
    179 
    180   VariantMapKey(const VariantMapKey&) = default;
    181   VariantMapKey(VariantMapKey&&) = default;
    182 
    183   template <typename Base, template <typename TV> class TKey> friend struct VariantMap;
    184 
    185   // Store a prototype of the key's default value, for usage with VariantMap::GetOrDefault
    186   std::shared_ptr<TValue> default_value_;
    187 };
    188 
    189 // Implementation details for a stringified VariantMapStringKey.
    190 namespace detail {
    191   struct VariantMapStringKeyRegistry {
    192     // TODO
    193   };
    194 }  // namespace detail
    195 
    196 // Alternative base type for all keys used by VariantMap, supports runtime strings as the name.
    197 template <typename TValue>
    198 struct VariantMapStringKey : VariantMapKey<TValue> {
    199   explicit VariantMapStringKey(const char* name)
    200       :   // VariantMapKey(/*std::hash<std::string>()(name)*/),
    201         name_(name) {
    202   }
    203 
    204  private:
    205   const char* name_;
    206 };
    207 
    208 // A variant map allows type-safe heteregeneous key->value mappings.
    209 // All possible key types must be specified at compile-time. Values may be added/removed
    210 // at runtime.
    211 template <typename Base, template <typename TV> class TKey>
    212 struct VariantMap {
    213   // Allow users of this static interface to use the key type.
    214   template <typename TValue>
    215   using Key = TKey<TValue>;
    216 
    217   // Look up the value from the key. The pointer becomes invalid if this key is overwritten/removed.
    218   // A null value is returned only when the key does not exist in this map.
    219   template <typename TValue>
    220   const TValue* Get(const TKey<TValue>& key) const {
    221     return GetValuePtr(key);
    222   }
    223 
    224   // Look up the value from the key. The pointer becomes invalid if this key is overwritten/removed.
    225   // A null value is returned only when the key does not exist in this map.
    226   template <typename TValue>
    227   TValue* Get(const TKey<TValue>& key) {
    228     return GetValuePtr(key);
    229   }
    230 
    231   // Lookup the value from the key. If it was not set in the map, return the default value.
    232   // The default value is either the key's default, or TValue{} if the key doesn't have a default.
    233   template <typename TValue>
    234   TValue GetOrDefault(const TKey<TValue>& key) const {
    235     auto* ptr = Get(key);
    236     return (ptr == nullptr) ? key.CreateDefaultValue() : *ptr;
    237   }
    238 
    239  private:
    240   // TODO: move to detail, or make it more generic like a ScopeGuard(function)
    241   template <typename TValue>
    242   struct ScopedRemove {
    243     ScopedRemove(VariantMap& map, const TKey<TValue>& key) : map_(map), key_(key) {}
    244     ~ScopedRemove() {
    245       map_.Remove(key_);
    246     }
    247 
    248     VariantMap& map_;
    249     const TKey<TValue>& key_;
    250   };
    251 
    252  public:
    253   // Release the value from the key. If it was not set in the map, returns the default value.
    254   // If the key was set, it is removed as a side effect.
    255   template <typename TValue>
    256   TValue ReleaseOrDefault(const TKey<TValue>& key) {
    257     ScopedRemove<TValue> remove_on_return(*this, key);
    258 
    259     TValue* ptr = Get(key);
    260     if (ptr != nullptr) {
    261       return std::move(*ptr);
    262     } else {
    263       return key.CreateDefaultValue();
    264     }
    265   }
    266 
    267   // See if a value is stored for this key.
    268   template <typename TValue>
    269   bool Exists(const TKey<TValue>& key) const {
    270     return GetKeyValueIterator(key) != storage_map_.end();
    271   }
    272 
    273   // Set a value for a given key, overwriting the previous value if any.
    274   // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument.
    275   template <typename TValue>
    276   void Set(const TKey<TValue>& key, const typename Identity<TValue>::type& value) {
    277     // Clone the value first, to protect against &value == GetValuePtr(key).
    278     auto* new_value = new TValue(value);
    279 
    280     Remove(key);
    281     storage_map_.insert({{key.Clone(), new_value}});
    282   }
    283 
    284   // Set a value for a given key, only if there was no previous value before.
    285   // Returns true if the value was set, false if a previous value existed.
    286   // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument.
    287   template <typename TValue>
    288   bool SetIfMissing(const TKey<TValue>& key, const typename Identity<TValue>::type& value) {
    289     TValue* ptr = Get(key);
    290     if (ptr == nullptr) {
    291       Set(key, value);
    292       return true;
    293     }
    294     return false;
    295   }
    296 
    297   // Remove the value for a given key, or a no-op if there was no previously set value.
    298   template <typename TValue>
    299   void Remove(const TKey<TValue>& key) {
    300     StaticAssertKeyType<TValue>();
    301 
    302     auto&& it = GetKeyValueIterator(key);
    303     if (it != storage_map_.end()) {
    304       key.ValueDelete(it->second);
    305       delete it->first;
    306       storage_map_.erase(it);
    307     }
    308   }
    309 
    310   // Remove all key/value pairs.
    311   void Clear() {
    312     DeleteStoredValues();
    313     storage_map_.clear();
    314   }
    315 
    316   // How many key/value pairs are stored in this map.
    317   size_t Size() const {
    318     return storage_map_.size();
    319   }
    320 
    321   // Construct an empty map.
    322   explicit VariantMap() {}
    323 
    324   template <typename ... TKeyValue>
    325   explicit VariantMap(const TKeyValue& ... key_value_list) {
    326     static_assert(sizeof...(TKeyValue) % 2 == 0, "Must be an even number of key/value elements");
    327     InitializeParameters(key_value_list...);
    328   }
    329 
    330   // Create a new map from an existing map, copying all the key/value pairs.
    331   VariantMap(const VariantMap& other) {
    332     operator=(other);
    333   }
    334 
    335   // Copy the key/value pairs from the other map into this one. Existing key/values are cleared.
    336   VariantMap& operator=(const VariantMap& other) {
    337     if (this == &other) {
    338       return *this;
    339     }
    340 
    341     Clear();
    342 
    343     for (auto&& kv_pair : other.storage_map_) {
    344       const detail::VariantMapKeyRaw* raw_key_other = kv_pair.first;
    345       void* value = kv_pair.second;
    346 
    347       detail::VariantMapKeyRaw* cloned_raw_key = raw_key_other->Clone();
    348       void* cloned_value = raw_key_other->ValueClone(value);
    349 
    350       storage_map_.insert({{ cloned_raw_key, cloned_value }});
    351     }
    352 
    353     return *this;
    354   }
    355 
    356   // Create a new map by moving an existing map into this one. The other map becomes empty.
    357   VariantMap(VariantMap&& other) {
    358     operator=(std::forward<VariantMap>(other));
    359   }
    360 
    361   // Move the existing map's key/value pairs into this one. The other map becomes empty.
    362   VariantMap& operator=(VariantMap&& other) {
    363     if (this != &other) {
    364       Clear();
    365       storage_map_.swap(other.storage_map_);
    366       other.storage_map_.clear();
    367     }
    368     return *this;
    369   }
    370 
    371   ~VariantMap() {
    372     DeleteStoredValues();
    373   }
    374 
    375  private:
    376   void InitializeParameters() {}
    377 
    378   template <typename TK, typename TValue, typename ... Rest>
    379   void InitializeParameters(const TK& key, const TValue& value, const Rest& ... rest) {
    380     static_assert(
    381         std::is_same<TK, TKey<TValue>>::value, "The 0th/2nd/4th/etc parameters must be a key");
    382 
    383     const TKey<TValue>& key_refined = key;
    384 
    385     Set(key_refined, value);
    386     InitializeParameters(rest...);
    387   }
    388 
    389   // Custom key comparator for std::map, needed since we are storing raw pointers as the keys.
    390   struct KeyComparator {
    391     bool operator()(const detail::VariantMapKeyRaw* lhs,
    392                     const detail::VariantMapKeyRaw* rhs) const {
    393       if (lhs == nullptr) {
    394         return lhs != rhs;
    395       }
    396 
    397       return lhs->Compare(rhs);
    398     }
    399   };
    400 
    401   // Map of key pointers to value pointers. Pointers are never null.
    402   using StorageMap = std::map<const detail::VariantMapKeyRaw*, void*, KeyComparator>;
    403 
    404   template <typename TValue>
    405   typename StorageMap::iterator GetKeyValueIterator(const TKey<TValue>& key) {
    406     StaticAssertKeyType<TValue>();
    407 
    408     const TKey<TValue>* key_ptr = &key;
    409     const detail::VariantMapKeyRaw* raw_ptr = key_ptr;
    410     return storage_map_.find(raw_ptr);
    411   }
    412 
    413   template <typename TValue>
    414   typename StorageMap::const_iterator GetKeyValueIterator(const TKey<TValue>& key) const {
    415     StaticAssertKeyType<TValue>();
    416 
    417     const TKey<TValue>* key_ptr = &key;
    418     const detail::VariantMapKeyRaw* raw_ptr = key_ptr;
    419     return storage_map_.find(raw_ptr);
    420   }
    421 
    422   template <typename TValue>
    423   TValue* GetValuePtr(const TKey<TValue>& key) {
    424     return const_cast<TValue*>(GetValueConstPtr(key));
    425   }
    426 
    427   template <typename TValue>
    428   const TValue* GetValuePtr(const TKey<TValue>& key) const {
    429     return GetValueConstPtr(key);
    430   }
    431 
    432   template <typename TValue>
    433   const TValue* GetValueConstPtr(const TKey<TValue>& key) const {
    434     auto&& it = GetKeyValueIterator(key);
    435     if (it == storage_map_.end()) {
    436       return nullptr;
    437     }
    438 
    439     return reinterpret_cast<const TValue*>(it->second);
    440   }
    441 
    442   template <typename TValue>
    443   static void StaticAssertKeyType() {
    444     static_assert(std::is_base_of<VariantMapKey<TValue>, TKey<TValue>>::value,
    445                   "The provided key type (TKey) must be a subclass of VariantMapKey");
    446   }
    447 
    448   void DeleteStoredValues() {
    449     for (auto&& kv_pair : storage_map_) {
    450       kv_pair.first->ValueDelete(kv_pair.second);
    451       delete kv_pair.first;
    452     }
    453   }
    454 
    455   StorageMap storage_map_;
    456 };
    457 
    458 }  // namespace art
    459 
    460 #endif  // ART_RUNTIME_BASE_VARIANT_MAP_H_
    461