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