HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
typeInfoMap.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_TF_TYPE_INFO_MAP_H
8 #define PXR_BASE_TF_TYPE_INFO_MAP_H
9 
10 /// \file tf/typeInfoMap.h
11 /// \ingroup group_tf_RuntimeTyping
12 /// \ingroup group_tf_Containers
13 
14 #include "pxr/pxr.h"
15 
16 #include "pxr/base/tf/hash.h"
17 #include "pxr/base/tf/iterator.h"
18 
19 #include "pxr/base/tf/hashmap.h"
20 
21 #include <typeinfo>
22 #include <string>
23 #include <list>
24 
26 
27 /// \class TfTypeInfoMap
28 /// \ingroup group_tf_RuntimeTyping
29 /// \ingroup group_tf_Containers
30 ///
31 /// A map whose key is a const std::type_info&, or a string alias.
32 ///
33 /// A \c TfTypeInfoMap stores values of arbitrary type (template parameter
34 /// VALUE) under a key that is either a \c const \c std::type_info&, or an \c
35 /// std::string. Note that the \c std::type_info structure is many-to-one
36 /// with respect to its name, i.e. two distinct instances of a \c
37 /// std::type_info can represent the same type. Thus, a naive implementation
38 /// that does pointer comparison on the address of a \c std::type_info can
39 /// fail. The \c TfTypeInfoMap takes care of this aliasing.
40 ///
41 /// Additionally, the table lets one create additional string aliases for a
42 /// given entry.
43 ///
44 template <class VALUE>
46  TfTypeInfoMap(const TfTypeInfoMap&) = delete;
47  TfTypeInfoMap& operator=(const TfTypeInfoMap&) = delete;
48 public:
49 
50  // Default constructor passes 0 to TfHashMap constructors to keep size
51  // small. This is good since each defined TfType has one of these maps in it.
52  TfTypeInfoMap() : _nameMap(0), _stringCache(0) {}
53 
54  /// Return true if the given key is present in the map.
55  bool Exists(const std::type_info& key) const {
56  return Find(key) != NULL;
57  }
58 
59  /// Return true if the given key is present in the map.
60  ///
61  /// Note that lookup by \c std::type_info is preferable for speed reasons.
62  bool Exists(const std::string& key) const {
63  return Find(key) != NULL;
64  }
65 
66  /// Return a pointer to the value stored under \p key, and NULL if \p key
67  /// is not a key in the map.
68  VALUE* Find(const std::type_info& key) const {
69  typename _TypeInfoCache::const_iterator i = _typeInfoCache.find(&key);
70  if (i != _typeInfoCache.end())
71  return &i->second->value;
72  else if (VALUE* v = Find(key.name())) {
73  return v;
74  }
75  return NULL;
76  }
77 
78  /// Return a pointer to the value stored under \p key, and NULL if \p key
79  /// is not a key in the map. For efficiency of future lookups this will
80  /// cache the result if it falls back to a string based lookup. In that
81  /// case before updating the cache it will call the functor \p upgrader
82  /// to allow the client to upgrade any lock to exclusive access.
83  template <class Upgrader>
84  VALUE* Find(const std::type_info& key, Upgrader& upgrader) {
85  typename _TypeInfoCache::const_iterator i = _typeInfoCache.find(&key);
86  if (i != _typeInfoCache.end())
87  return &i->second->value;
88  else if (VALUE* v = Find(key.name())) {
89  upgrader();
90  _CreateAlias(key, key.name());
91  return v;
92  }
93  return NULL;
94  }
95 
96  /// Return a pointer to the value stored under \p key, and NULL if \p key
97  /// is not a key in the map.
98  ///
99  /// Note that lookup by \c std::type_info is preferable for speed reasons.
100  VALUE* Find(const std::string& key) const {
101  typename _StringCache::const_iterator i = _stringCache.find(key);
102  return (i == _stringCache.end()) ? NULL : &i->second->value;
103  }
104 
105  /// Set the value for a given key.
106  ///
107  /// Note that if \p key is not already in the table, this creates a new
108  /// entry. Also, \p key.name() is automatically made linked with this
109  /// entry, so that future queries can be made via \p key.name(), though
110  /// lookup by \c std::type_info is greatly preferred.
111  void Set(const std::type_info& key, const VALUE& value) {
112  if (VALUE* v = Find(key))
113  *v = value;
114  else {
115  Set(key.name(), value);
116  _CreateAlias(key, key.name());
117  }
118  }
119 
120  /// Set the value for a given key.
121  ///
122  /// Note that if \p key is not already in the table, this creates a new
123  /// entry. Also, lookup by \c std::type_info is preferable for speed
124  /// reasons.
125  void Set(const std::string& key, const VALUE& value) {
126  typename _StringCache::iterator i = _stringCache.find(key);
127 
128  if (i != _stringCache.end())
129  i->second->value = value;
130  else {
131  _Entry* e = &_nameMap[key];
132  e->primaryKey = key;
133  e->value = value;
134 
135  _stringCache[key] = e;
136  e->stringAliases.push_back(key);
137  }
138  }
139 
140  /// Create an alias for a key.
141  ///
142  /// Queries with a key of \p alias will return the same data associated
143  /// with queries for \p key.
144  ///
145  /// If \p key is not presently a member of the map, this function does
146  /// nothing and returns \c false.
147  bool CreateAlias(const std::string& alias, const std::string& key) {
148  typename _StringCache::iterator i = _stringCache.find(key);
149  if (i != _stringCache.end())
150  return (_CreateAlias(alias, i->second), true);
151  else
152  return false;
153  }
154 
155  /// \overload
156  bool CreateAlias(const std::string& alias, const std::type_info& key) {
157  typename _TypeInfoCache::iterator i = _typeInfoCache.find(&key);
158  if (i != _typeInfoCache.end())
159  return (_CreateAlias(alias, i->second), true);
160  else
161  return false;
162  }
163 
164  /// Remove this key (and any aliases associated with it).
165  void Remove(const std::type_info& key) {
166  Remove(key.name());
167  }
168 
169  /// Remove this key (and any aliases associated with it).
170  void Remove(const std::string& key) {
171  typename _StringCache::iterator i = _stringCache.find(key);
172  if (i == _stringCache.end())
173  return;
174 
175  _Entry* e = i->second;
176 
177  for (TfIterator<_TypeInfoList> j = e->typeInfoAliases; j; ++j) {
178  _typeInfoCache.erase(*j);
179  }
180 
181  for (TfIterator<std::list<std::string> > j = e->stringAliases; j; ++j) {
182  _stringCache.erase(*j);
183  }
184 
185  // `e` points into the node owned by _nameMap. Passing
186  // e->primaryKey to erase() would cause the node to be
187  // deleted. However, the implementation of erase may access
188  // the key again after the node has been deleted (at least,
189  // when TfHashMap is __gnu_cxx::hash_map.)
190  const std::string primaryKey = std::move(e->primaryKey);
191  _nameMap.erase(primaryKey);
192  }
193 
194 private:
195  typedef std::list<const std::type_info*> _TypeInfoList;
196 
197  struct _Entry {
198  mutable _TypeInfoList typeInfoAliases;
199  mutable std::list<std::string> stringAliases;
200  std::string primaryKey;
201  VALUE value;
202  };
203 
204  void _CreateAlias(const std::type_info& alias, const std::string& key) {
205  typename _StringCache::iterator i = _stringCache.find(key);
206  if (i != _stringCache.end())
207  _CreateAlias(alias, i->second);
208  }
209 
210  void _CreateAlias(const std::type_info& alias, _Entry* e) {
211  if (_typeInfoCache.find(&alias) == _typeInfoCache.end()) {
212  _typeInfoCache[&alias] = e;
213  e->typeInfoAliases.push_back(&alias);
214  }
215  }
216 
217  void _CreateAlias(const std::string& alias, _Entry* e) {
218  if (_stringCache.find(alias) == _stringCache.end()) {
219  _stringCache[alias] = e;
220  e->stringAliases.push_back(alias);
221  }
222  }
223 
226  _TypeInfoCache;
227  typedef TfHashMap<std::string, _Entry*, TfHash> _StringCache;
228 
229  _NameMap _nameMap;
230 
231  _TypeInfoCache _typeInfoCache;
232  _StringCache _stringCache;
233 };
234 
236 
237 #endif // PXR_BASE_TF_TYPE_INFO_MAP_H
void Remove(const std::string &key)
Remove this key (and any aliases associated with it).
Definition: typeInfoMap.h:170
const GLdouble * v
Definition: glcorearb.h:837
bool Exists(const std::string &key) const
Definition: typeInfoMap.h:62
iterator end()
Definition: hashmap.h:301
GLsizei const GLfloat * value
Definition: glcorearb.h:824
VALUE * Find(const std::type_info &key, Upgrader &upgrader)
Definition: typeInfoMap.h:84
bool Exists(const std::type_info &key) const
Return true if the given key is present in the map.
Definition: typeInfoMap.h:55
bool CreateAlias(const std::string &alias, const std::type_info &key)
Definition: typeInfoMap.h:156
VALUE * Find(const std::string &key) const
Definition: typeInfoMap.h:100
void Set(const std::type_info &key, const VALUE &value)
Definition: typeInfoMap.h:111
GLint j
Definition: glad.h:2733
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
VALUE * Find(const std::type_info &key) const
Definition: typeInfoMap.h:68
bool CreateAlias(const std::string &alias, const std::string &key)
Definition: typeInfoMap.h:147
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
if(num_boxed_items<=0)
Definition: UT_RTreeImpl.h:697
void Remove(const std::type_info &key)
Remove this key (and any aliases associated with it).
Definition: typeInfoMap.h:165
void Set(const std::string &key, const VALUE &value)
Definition: typeInfoMap.h:125