HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_Map.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_Map.h (UT Library, C++)
7  *
8  * COMMENTS: Wrapper for an unordered map data structure.
9  *
10  * UT_Map<key, entry> map;
11  * key id;
12  * entry item;
13  *
14  * map[id] = item; // insert or replace
15  *
16  * item = map[id]; // find or create new
17  *
18  * UT_Map<key,entry>::iterator map_item = map.find(id); // find only
19  * if(map_item != map.end())
20  * item = map_item->second;
21  *
22  * map.erase(id); // remove entry
23  *
24  * for(auto it = map.begin(); it != map.end(); ++it)
25  * {
26  * key = it->first; // traverse
27  * item = it->second;
28  * }
29  *
30  * int num = map.size(); // #entries
31  *
32  * map.clear(); // remove all entries
33  *
34  * RELATION TO THE STL:
35  *
36  * Use UT_Map (or UT_SortedMap) instead of std::map
37  *
38  * Reasoning to not use std::map:
39  *
40  * - Performance: std::map is an ordered map so is impossible to have
41  * reasonably fast implementations for it.
42  *
43  * - If you want a sorted map, we have wrapped std::map as UT_SortedMap. But
44  * you probably don’t.
45  *
46  * Use UT_Map instead of std::unordered_map:
47  *
48  * Reasoning to not use std::unordered_map:
49  *
50  * - There may are still be issues with std::unordered map (possibly platform
51  * specific hash functions?)
52  *
53  * - We also want to keep this wrapped so we can easily replace it with a
54  * faster version.
55  *
56  * - Consider UT_ArrayMap and UT_StringMap variants as well.
57  */
58 
59 #ifndef __UT_Map__
60 #define __UT_Map__
61 
62 #include "UT_ContainerPrinter.h"
63 #include "UT_IteratorRange.h"
64 #include <SYS/SYS_Pragma.h>
65 #include <SYS/SYS_Types.h>
66 
67 // IWYU pragma: begin_exports
70 #include <hboost/unordered_map.hpp>
72 
73 #include <iterator>
74 #include <map>
75 // IWYU pragma: end_exports
76 
77 template<typename K, typename V, typename H, typename P>
78 int64
79 UTgetMemoryUsage(const hboost::unordered_map<K, V, H, P> &map, bool inclusive)
80 {
81  int64 mem = inclusive ? sizeof(map) : 0;
82  // Buckets only contain a pointer to the node
83  mem += map.bucket_count() * sizeof(void*);
84  // Nodes contain the hash value, a pointer to the next node,
85  // and the key-value pair.
86  mem += map.size() * (sizeof(size_t) + sizeof(void*) + sizeof(std::pair<K,V>));
87  return mem;
88 }
89 
90 template<typename K, typename V, typename C>
91 int64
92 UTgetMemoryUsage(const std::map<K, V, C> &map, bool inclusive)
93 {
94  int64 mem = inclusive ? sizeof(map) : 0;
95 
96  // NOTE: If the comparator object of type C owns any memory
97  // (i.e. apart from itself) when default constructed
98  // or copy constructed, that memory won't be counted.
99 
100  // NOTE: This count is for the VC++ 2010 implementation
101  // of std::map, but others should be in the ballpark.
102  // Nodes contain pointers to the left, parent, and right,
103  // the key-value pair, a colour in a char (red or black),
104  // and a flag in a char indicating if the node is the head.
105  // Round up to a multiple of 4 on the size of each node.
106  mem += (map.size() + 1) * ((3*sizeof(void*) + sizeof(std::pair<const K,V>)
107  + 2*sizeof(char) + 3) & ~3);
108  return mem;
109 }
110 
111 /// Unsorted map container.
112 template<typename K, typename V,
113  typename H = hboost::hash<K>, typename P = std::equal_to<K> >
114 class UT_Map : public hboost::unordered_map<K, V, H, P>
115 {
116 public:
117  // Hoisting of base types
118  typedef hboost::unordered_map<K, V, H, P> Base;
119  typedef typename Base::key_type key_type;
120  typedef typename Base::mapped_type mapped_type;
121  typedef typename Base::value_type value_type;
122  typedef typename Base::hasher hasher;
123  typedef typename Base::key_equal key_equal;
124  typedef typename Base::iterator iterator;
125  typedef typename Base::const_iterator const_iterator;
126  typedef H Hasher;
127  typedef P Equal;
128 
129  /// Initialize an empty map, and optionally a custom hasher and
130  /// equal compare functions.
131  explicit UT_Map(const Hasher &hf = Hasher(),
132  const Equal &eql = Equal()) :
133  Base(hboost::unordered::detail::default_bucket_count, hf, eql) {}
134 
135  /// Initialize the map from an iterator pair, and optionally a custom
136  /// hasher and equal compare functions.
137  template <typename InputIt>
138  UT_Map(InputIt first, InputIt last,
139  const Hasher &hf = Hasher(),
140  const Equal &eql = Equal()) :
141  Base(first, last, hboost::unordered::detail::default_bucket_count,
142  hf, eql) {}
143 
144  /// Initialize the map using an initializer list. The initializer list is a
145  /// list of pairs of items to add to the map. E.g:
146  /// @code
147  /// UT_Map<int, const char *> foo = {{1, "one"}, {2, "two"}};
148  /// @endcode
149  UT_Map(std::initializer_list<value_type> init_list)
150  {
151  // We can't thunk down to the hboost::unordered_map initializer_list
152  // constructor, since it seems disabled when building with clang.
153  this->insert(init_list.begin(), init_list.end());
154  }
155 
156  /// Returns the approximate size, in bytes, of the memory consumed by this map
157  /// or, optionally, only the data contained within.
158  int64 getMemoryUsage(bool inclusive) const
159  {
160  int64 mem = inclusive ? sizeof(*this) : 0;
161  mem += UTgetMemoryUsage(*static_cast<const Base *>(this), false);
162  return mem;
163  }
164 
165  /// Returns @c true if a value with the @c key is contained in the map.
166  bool contains(const key_type &key) const
167  {
168  return this->find(key) != this->end();
169  }
170 
171  /// Returns the value at the key if it exists, or the provided default
172  /// value if it does not.
173  /// NOTE: Considering making this return const V&? Don't.
174  /// Lifetime extension rules likely can't be used to make that safe.
175  /// eg. const Foo &foo = get(key, Foo()) will return a stale reference.
176  V get(const key_type &key, const V &defval) const
177  {
178  auto it = this->find(key);
179  if (it == this->end())
180  return defval;
181  return it->second;
182  }
183 
184  /// The implementation of clear() is O(bucket_count()), not O(size()),
185  /// which can cause unexpected performance issues if the map has a large
186  /// capacity.
187  /// For std::unordered_map this was defect 2550
188  /// (http://cplusplus.github.io/LWG/lwg-defects.html#2550)
189  /// When updating or changing the underlying implemention, verify if this
190  /// is still necessary.
191  void clear()
192  {
193  // clear() is slightly faster than erase(begin(), end()) in typical
194  // scenarios, so only switch over to erase() once there are a lot of
195  // empty buckets.
196  if (Base::bucket_count() > 20 * Base::size())
197  Base::erase(Base::begin(), Base::end());
198  else
199  Base::clear();
200  }
201 
202 protected:
203  template<typename VIT, typename VT>
205  {
206  VT &operator()(const VIT &v) const { return v->first; }
207  };
208  template<typename VIT, typename VT>
210  {
211  VT &operator()(const VIT &v) const { return v->second; }
212  };
213 
214  template<typename IT, typename T, typename DR>
216  {
217  public:
218  using iterator_category = std::forward_iterator_tag;
219  using value_type = T;
220  using difference_type = std::ptrdiff_t;
221  using pointer = T*;
222  using reference = T&;
223 
225 
226  template<typename EIT, typename EDR>
228  it(src.it) {}
229 
230  reference operator*() const { DR dr; return dr(it); }
231  pointer operator->() const { DR dr; return &dr(it); }
232 
234  { return it == o.it; }
235 
237  { return it != o.it; }
238 
240  {
241  ++it;
242  return *this;
243  }
244 
245  protected:
246  friend class UT_Map<K, V, H, P>;
247 
248  partial_iterator_base(IT it) : it(it) {}
249  private:
250  IT it;
251  };
252 
253 public:
254  using const_key_iterator = partial_iterator_base<const_iterator, const key_type,
255  deref_pair_first<const_iterator, const key_type>>;
256  using mapped_iterator = partial_iterator_base<iterator, mapped_type,
257  deref_pair_second<iterator, mapped_type>>;
258  using const_mapped_iterator = partial_iterator_base<const_iterator, const mapped_type,
259  deref_pair_second<const_iterator, const mapped_type>>;
260 
261  /// Returns a range object that iterates over the map but returns only
262  /// the key values.
263  /// Example:
264  /// @code
265  /// UT_Map<int, const char *> foo = {{1, "one"}, {2, "two"}};
266  /// for (int key : foo.key_range())
267  /// std::cout << key << "\n";
268  /// @endcode
270  { return UTmakeRange(const_key_iterator(this->begin()),
271  const_key_iterator(this->end())); }
272 
273  /// Returns a range object that iterates over the map but returns only
274  /// the mapped values.
276  { return UTmakeRange(mapped_iterator(this->begin()),
277  mapped_iterator(this->end())); }
278 
279  /// Returns a const range object that iterates over the map but returns
280  /// only the mapped values.
282  { return UTmakeRange(const_mapped_iterator(this->begin()),
283  const_mapped_iterator(this->end())); }
284 };
285 
286 /// Sorted map container.
287 template<typename K, typename V, typename C = std::less<K> >
288 class UT_SortedMap : public std::map<K, V, C>
289 {
290 public:
291  // Hoisting of base types.
292  typedef std::map<K, V, C> Base;
293  typedef typename Base::key_type key_type;
294  typedef typename Base::mapped_type mapped_type;
295  typedef typename Base::value_type value_type;
296  typedef typename Base::key_compare key_compare;
297  typedef typename Base::iterator iterator;
298  typedef typename Base::const_iterator const_iterator;
299 
300  typedef C LessThan;
301 
303 
304  explicit UT_SortedMap(const LessThan &lt) : Base(lt) {}
305 
306  template<typename InputIt>
307  UT_SortedMap(InputIt first, InputIt last) : Base(first, last) {}
308 
309  template<typename InputIt>
310  UT_SortedMap(InputIt first, InputIt last, const LessThan &lt) :
311  Base(first, last, lt) {}
312 
313  /// Initialize the map using an initializer list. The initializer list is a
314  /// list of pairs of items to add to the map. E.g:
315  /// @code
316  /// UT_Map<int, const char *> foo = {{1, "one"}, {2, "two"}};
317  /// @endcode
318  UT_SortedMap(std::initializer_list<value_type> init_list)
319  {
320  this->insert(init_list.begin(), init_list.end());
321  }
322 
323  int64 getMemoryUsage(bool inclusive) const
324  {
325  int64 mem = inclusive ? sizeof(*this) : 0;
326  mem += UTgetMemoryUsage(*static_cast<const Base *>(this), false);
327  return mem;
328  }
329 
330  bool contains(const key_type &key) const
331  {
332  return this->find(key) != this->end();
333  }
334 
335 protected:
336  template<typename VIT, typename VT>
338  {
339  VT &operator()(const VIT &v) const { return v->first; }
340  };
341  template<typename VIT, typename VT>
343  {
344  VT &operator()(const VIT &v) const { return v->second; }
345  };
346 
347  template<typename IT, typename T, typename DR>
349  {
350  public:
351  using iterator_category = std::forward_iterator_tag;
352  using value_type = T;
353  using difference_type = std::ptrdiff_t;
354  using pointer = T*;
355  using reference = T&;
356 
358 
359  template<typename EIT, typename EDR>
361  it(src.it) {}
362 
363  reference operator*() const { DR dr; return dr(it); }
364  pointer operator->() const { DR dr; return &dr(it); }
365 
367  { return it == o.it; }
368 
370  { return it != o.it; }
371 
373  {
374  ++it;
375  return *this;
376  }
377 
378  protected:
379  friend class UT_SortedMap<K, V, C>;
380 
381  partial_iterator_base(IT it) : it(it) {}
382  private:
383  IT it;
384  };
385 
386 public:
387  using key_iterator = partial_iterator_base<iterator, key_type,
388  deref_pair_first<iterator, key_type>>;
389  using const_key_iterator = partial_iterator_base<const_iterator, const key_type,
390  deref_pair_first<const_iterator, const key_type>>;
391  using mapped_iterator = partial_iterator_base<iterator, mapped_type,
392  deref_pair_second<iterator, mapped_type>>;
393  using const_mapped_iterator = partial_iterator_base<const_iterator, const mapped_type,
394  deref_pair_second<const_iterator, const mapped_type>>;
395 
396  /// Returns a range object that iterates over the map but returns only
397  /// the key values.
399  { return UTmakeRange(key_iterator(this->begin()),
400  key_iterator(this->end())); }
401 
402  /// Returns a const range object that iterates over the map but returns
403  /// only the key values.
405  { return UTmakeRange(const_key_iterator(this->begin()),
406  const_key_iterator(this->end())); }
407 
408  /// Returns a range object that iterates over the map but returns only
409  /// the mapped values.
411  { return UTmakeRange(mapped_iterator(this->begin()),
412  mapped_iterator(this->end())); }
413 
414  /// Returns a const range object that iterates over the map but returns
415  /// only the mapped values.
417  { return UTmakeRange(const_mapped_iterator(this->begin()),
418  const_mapped_iterator(this->end())); }
419 };
420 
421 namespace std
422 {
423  // This helper needs to live in the 'std' namespace for argument-dependent
424  // lookup to succeed.
425  template<typename OS, typename K, typename V>
426  inline OS &
427  operator<<(OS &os, const pair<K, V> &v)
428  {
429  os << "<" << v.first << ", " << v.second << ">";
430  return os;
431  }
432 }
433 
434 template<typename OS, typename K, typename V>
435 inline OS &
436 operator<<(OS &os, const UT_Map<K, V> &d)
437 {
438  os << "UT_Map" << UT_ContainerPrinter<UT_Map<K, V> >(d);
439  return os;
440 }
441 
442 template<typename OS, typename K, typename V>
443 inline OS &
444 operator<<(OS &os, const UT_SortedMap<K, V> &d)
445 {
446  os << "UT_SortedMap" << UT_ContainerPrinter<UT_SortedMap<K, V> >(d);
447  return os;
448 }
449 
450 #endif
partial_iterator_base< iterator, mapped_type, deref_pair_second< iterator, mapped_type >> mapped_iterator
Definition: UT_Map.h:257
GLint first
Definition: glcorearb.h:405
Base::key_type key_type
Definition: UT_Map.h:119
UT_IteratorRange< const_key_iterator > key_range() const
Definition: UT_Map.h:269
Unsorted map container.
Definition: UT_Map.h:114
#define SYS_PRAGMA_PUSH_WARN()
Definition: SYS_Pragma.h:34
int64 getMemoryUsage(bool inclusive) const
Definition: UT_Map.h:323
const GLdouble * v
Definition: glcorearb.h:837
P Equal
Definition: UT_Map.h:127
int64 getMemoryUsage(bool inclusive) const
Definition: UT_Map.h:158
std::forward_iterator_tag iterator_category
Definition: UT_Map.h:351
UT_IteratorRange< IterT > UTmakeRange(IterT &&b, IterT &&e)
partial_iterator_base(const partial_iterator_base< EIT, T, EDR > &src)
Definition: UT_Map.h:360
VT & operator()(const VIT &v) const
Definition: UT_Map.h:339
Base::key_type key_type
Definition: UT_Map.h:293
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2138
void clear()
Definition: UT_Map.h:191
std::ptrdiff_t difference_type
Definition: UT_Map.h:220
reference operator*() const
Definition: UT_Map.h:230
OIIO_FORCEINLINE vbool4 insert(const vbool4 &a, bool val)
Helper: substitute val for a[i].
Definition: simd.h:3556
H Hasher
Definition: UT_Map.h:126
uint64 value_type
Definition: GA_PrimCompat.h:29
partial_iterator_base & operator++()
Definition: UT_Map.h:239
bool operator!=(const partial_iterator_base< IT, T, DR > &o) const
Definition: UT_Map.h:369
UT_SortedMap(std::initializer_list< value_type > init_list)
Definition: UT_Map.h:318
Base::value_type value_type
Definition: UT_Map.h:295
UT_SortedMap(InputIt first, InputIt last)
Definition: UT_Map.h:307
hboost::unordered_map< K, V, H, P > Base
Definition: UT_Map.h:118
Sorted map container.
Definition: UT_Map.h:288
VT & operator()(const VIT &v) const
Definition: UT_Map.h:211
partial_iterator_base< iterator, key_type, deref_pair_first< iterator, key_type >> key_iterator
Definition: UT_Map.h:388
std::map< K, V, C > Base
Definition: UT_Map.h:292
pointer operator->() const
Definition: UT_Map.h:231
bool operator!=(const partial_iterator_base< IT, T, DR > &o) const
Definition: UT_Map.h:236
Base::mapped_type mapped_type
Definition: UT_Map.h:120
GLuint GLuint end
Definition: glcorearb.h:475
partial_iterator_base< const_iterator, const key_type, deref_pair_first< const_iterator, const key_type >> const_key_iterator
Definition: UT_Map.h:255
UT_SortedMap(InputIt first, InputIt last, const LessThan &lt)
Definition: UT_Map.h:310
Base::iterator iterator
Definition: UT_Map.h:297
VT & operator()(const VIT &v) const
Definition: UT_Map.h:206
UT_IteratorRange< const_mapped_iterator > mapped_range() const
Definition: UT_Map.h:416
UT_Map(const Hasher &hf=Hasher(), const Equal &eql=Equal())
Definition: UT_Map.h:131
UT_SortedMap()
Definition: UT_Map.h:302
partial_iterator_base< const_iterator, const mapped_type, deref_pair_second< const_iterator, const mapped_type >> const_mapped_iterator
Definition: UT_Map.h:259
UT_IteratorRange< mapped_iterator > mapped_range()
Definition: UT_Map.h:275
long long int64
Definition: SYS_Types.h:116
partial_iterator_base & operator++()
Definition: UT_Map.h:372
STATIC_INLINE uint64_t H(uint64_t x, uint64_t y, uint64_t mul, int r)
Definition: farmhash.h:762
Base::iterator iterator
Definition: UT_Map.h:124
Base::const_iterator const_iterator
Definition: UT_Map.h:298
int64 UTgetMemoryUsage(const hboost::unordered_map< K, V, H, P > &map, bool inclusive)
Definition: UT_Map.h:79
#define SYS_PRAGMA_POP_WARN()
Definition: SYS_Pragma.h:35
VT & operator()(const VIT &v) const
Definition: UT_Map.h:344
bool operator==(const partial_iterator_base< IT, T, DR > &o) const
Definition: UT_Map.h:366
UT_SortedMap(const LessThan &lt)
Definition: UT_Map.h:304
Base::mapped_type mapped_type
Definition: UT_Map.h:294
Base::hasher hasher
Definition: UT_Map.h:122
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
GLsizeiptr size
Definition: glcorearb.h:664
std::forward_iterator_tag iterator_category
Definition: UT_Map.h:218
UT_IteratorRange< const_mapped_iterator > mapped_range() const
Definition: UT_Map.h:281
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:587
#define SYS_PRAGMA_DISABLE_NON_NULL()
Definition: SYS_Pragma.h:201
UT_IteratorRange< key_iterator > key_range()
Definition: UT_Map.h:398
UT_Map(InputIt first, InputIt last, const Hasher &hf=Hasher(), const Equal &eql=Equal())
Definition: UT_Map.h:138
UT_IteratorRange< mapped_iterator > mapped_range()
Definition: UT_Map.h:410
reference operator*() const
Definition: UT_Map.h:363
UT_Map(std::initializer_list< value_type > init_list)
Definition: UT_Map.h:149
UT_IteratorRange< const_key_iterator > key_range() const
Definition: UT_Map.h:404
Base::value_type value_type
Definition: UT_Map.h:121
bool contains(const key_type &key) const
Definition: UT_Map.h:330
Base::const_iterator const_iterator
Definition: UT_Map.h:125
partial_iterator_base< iterator, mapped_type, deref_pair_second< iterator, mapped_type >> mapped_iterator
Definition: UT_Map.h:392
Base::key_compare key_compare
Definition: UT_Map.h:296
partial_iterator_base< const_iterator, const key_type, deref_pair_first< const_iterator, const key_type >> const_key_iterator
Definition: UT_Map.h:390
Base::key_equal key_equal
Definition: UT_Map.h:123
partial_iterator_base< const_iterator, const mapped_type, deref_pair_second< const_iterator, const mapped_type >> const_mapped_iterator
Definition: UT_Map.h:394
bool operator==(const partial_iterator_base< IT, T, DR > &o) const
Definition: UT_Map.h:233
partial_iterator_base(const partial_iterator_base< EIT, T, EDR > &src)
Definition: UT_Map.h:227
bool contains(const key_type &key) const
Returns true if a value with the key is contained in the map.
Definition: UT_Map.h:166
GLenum src
Definition: glcorearb.h:1793