blob: fdb60c414123f3db13f513c22b35e0f0cf6c92a4 [file] [log] [blame]
Igor Murashkinaaebaa02015-01-26 10:55:53 -08001/*
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>
Vladimir Marko88b2b802015-12-04 14:19:04 +000022#include <type_traits>
Igor Murashkinaaebaa02015-01-26 10:55:53 -080023#include <utility>
24
Andreas Gampe5678db52017-06-08 14:11:18 -070025#include "base/stl_util_identity.h"
Vladimir Marko88b2b802015-12-04 14:19:04 +000026
Igor Murashkinaaebaa02015-01-26 10:55:53 -080027namespace 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>
Mathieu Chartier2cebb242015-04-21 16:50:40 -070037// TValue* Get(Key<T> key); // null if the value was never set, otherwise the value.
Igor Murashkinaaebaa02015-01-26 10:55:53 -080038//
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.
75namespace 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.
Andreas Gampec801f0d2015-02-24 20:55:16 -0800126 VariantMapKeyRaw(const VariantMapKeyRaw&) = default;
127 VariantMapKeyRaw(VariantMapKeyRaw&&) = default;
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800128
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.
135template <typename TValue>
136struct 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
Andreas Gampec801f0d2015-02-24 20:55:16 -0800180 VariantMapKey(const VariantMapKey&) = default;
181 VariantMapKey(VariantMapKey&&) = default;
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800182
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.
190namespace 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.
197template <typename TValue>
198struct 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.
211template <typename Base, template <typename TV> class TKey>
212struct 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 {
Pirama Arumuga Nainar68cad902015-09-12 16:04:42 -0700263 return key.CreateDefaultValue();
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800264 }
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.
Vladimir Marko88b2b802015-12-04 14:19:04 +0000274 // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument.
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800275 template <typename TValue>
Vladimir Marko88b2b802015-12-04 14:19:04 +0000276 void Set(const TKey<TValue>& key, const typename Identity<TValue>::type& value) {
Igor Murashkin2798da12015-02-06 17:59:39 -0800277 // Clone the value first, to protect against &value == GetValuePtr(key).
278 auto* new_value = new TValue(value);
279
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800280 Remove(key);
Igor Murashkin2798da12015-02-06 17:59:39 -0800281 storage_map_.insert({{key.Clone(), new_value}});
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800282 }
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.
Vladimir Marko88b2b802015-12-04 14:19:04 +0000286 // Note: Omit the `value` from TValue type deduction, deduce only from the `key` argument.
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800287 template <typename TValue>
Vladimir Marko88b2b802015-12-04 14:19:04 +0000288 bool SetIfMissing(const TKey<TValue>& key, const typename Identity<TValue>::type& value) {
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800289 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_