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