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