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 "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 { AllocateCounterVariantMapKeyCounterAllocator79 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<). CompareVariantMapKeyRaw106 virtual bool Compare(const VariantMapKeyRaw* other) const { 107 if (other == nullptr) { 108 return false; 109 } 110 return key_counter_ < other->key_counter_; 111 } 112 ~VariantMapKeyRawVariantMapKeyRaw113 virtual ~VariantMapKeyRaw() {} 114 115 protected: VariantMapKeyRawVariantMapKeyRaw116 VariantMapKeyRaw() 117 : key_counter_(VariantMapKeyCounterAllocator::AllocateCounter()) {} 118 // explicit VariantMapKeyRaw(size_t counter) 119 // : key_counter_(counter) {} 120 GetCounterVariantMapKeyRaw121 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. CreateDefaultValueVariantMapKey140 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) {} VariantMapKeyVariantMapKey150 explicit VariantMapKey(const TValue& default_value) 151 : default_value_(std::make_shared<TValue>(default_value)) {} VariantMapKeyVariantMapKey152 explicit VariantMapKey(TValue&& default_value) 153 : default_value_(std::make_shared<TValue>(default_value)) {} VariantMapKeyVariantMapKey154 VariantMapKey() {} ~VariantMapKeyVariantMapKey155 virtual ~VariantMapKey() {} 156 157 private: CloneVariantMapKey158 virtual VariantMapKeyRaw* Clone() const { 159 return new VariantMapKey<TValue>(*this); 160 } 161 ValueCloneVariantMapKey162 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 ValueDeleteVariantMapKey171 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> { VariantMapStringKeyVariantMapStringKey200 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> GetVariantMap221 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> GetVariantMap228 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> GetOrDefaultVariantMap235 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> AssignIfExistsVariantMap241 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 { ScopedRemoveVariantMap::ScopedRemove252 ScopedRemove(VariantMap& map, const TKey<TValue>& key) : map_(map), key_(key) {} ~ScopedRemoveVariantMap::ScopedRemove253 ~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> ReleaseOrDefaultVariantMap265 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> ExistsVariantMap278 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> SetVariantMap285 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> SetIfMissingVariantMap298 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> RemoveVariantMap309 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. ClearVariantMap321 void Clear() { 322 DeleteStoredValues(); 323 storage_map_.clear(); 324 } 325 326 // How many key/value pairs are stored in this map. SizeVariantMap327 size_t Size() const { 328 return storage_map_.size(); 329 } 330 331 // Construct an empty map. VariantMapVariantMap332 VariantMap() {} 333 334 template <typename ... TKeyValue> VariantMapVariantMap335 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. VariantMapVariantMap341 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. VariantMapVariantMap367 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 ~VariantMapVariantMap381 ~VariantMap() { 382 DeleteStoredValues(); 383 } 384 385 private: InitializeParametersVariantMap386 void InitializeParameters() {} 387 388 template <typename TK, typename TValue, typename ... Rest> InitializeParametersVariantMap389 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 { operatorVariantMap::KeyComparator401 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> GetKeyValueIteratorVariantMap415 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> GetKeyValueIteratorVariantMap424 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> GetValuePtrVariantMap433 TValue* GetValuePtr(const TKey<TValue>& key) { 434 return const_cast<TValue*>(GetValueConstPtr(key)); 435 } 436 437 template <typename TValue> GetValuePtrVariantMap438 const TValue* GetValuePtr(const TKey<TValue>& key) const { 439 return GetValueConstPtr(key); 440 } 441 442 template <typename TValue> GetValueConstPtrVariantMap443 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> StaticAssertKeyTypeVariantMap453 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 DeleteStoredValuesVariantMap458 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