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_Types.h>
65 
66 #include <hboost/unordered_map.hpp>
67 #include <iterator>
68 #include <map>
69 
70 template<typename K, typename V, typename H, typename P>
71 int64
72 UTgetMemoryUsage(const hboost::unordered_map<K, V, H, P> &map, bool inclusive)
73 {
74  int64 mem = inclusive ? sizeof(map) : 0;
75  // Buckets only contain a pointer to the node
76  mem += map.bucket_count() * sizeof(void*);
77  // Nodes contain the hash value, a pointer to the next node,
78  // and the key-value pair.
79  mem += map.size() * (sizeof(size_t) + sizeof(void*) + sizeof(std::pair<K,V>));
80  return mem;
81 }
82 
83 template<typename K, typename V, typename C>
84 int64
85 UTgetMemoryUsage(const std::map<K, V, C> &map, bool inclusive)
86 {
87  int64 mem = inclusive ? sizeof(map) : 0;
88 
89  // NOTE: If the comparator object of type C owns any memory
90  // (i.e. apart from itself) when default constructed
91  // or copy constructed, that memory won't be counted.
92 
93  // NOTE: This count is for the VC++ 2010 implementation
94  // of std::map, but others should be in the ballpark.
95  // Nodes contain pointers to the left, parent, and right,
96  // the key-value pair, a colour in a char (red or black),
97  // and a flag in a char indicating if the node is the head.
98  // Round up to a multiple of 4 on the size of each node.
99  mem += (map.size() + 1) * ((3*sizeof(void*) + sizeof(std::pair<const K,V>)
100  + 2*sizeof(char) + 3) & ~3);
101  return mem;
102 }
103 
104 /// Unsorted map container.
105 template<typename K, typename V,
106  typename H = hboost::hash<K>, typename P = std::equal_to<K> >
107 class UT_Map : public hboost::unordered_map<K, V, H, P>
108 {
109 public:
110  // Hoisting of base types
111  typedef hboost::unordered_map<K, V, H, P> Base;
112  typedef typename Base::key_type key_type;
113  typedef typename Base::mapped_type mapped_type;
114  typedef typename Base::value_type value_type;
115  typedef typename Base::hasher hasher;
116  typedef typename Base::key_equal key_equal;
117  typedef typename Base::iterator iterator;
118  typedef typename Base::const_iterator const_iterator;
119  typedef H Hasher;
120  typedef P Equal;
121 
122  /// Initialize an empty map, and optionally a custom hasher and
123  /// equal compare functions.
124  explicit UT_Map(const Hasher &hf = Hasher(),
125  const Equal &eql = Equal()) :
126  Base(hboost::unordered::detail::default_bucket_count, hf, eql) {}
127 
128  /// Initialize the map from an iterator pair, and optionally a custom
129  /// hasher and equal compare functions.
130  template <typename InputIt>
131  UT_Map(InputIt first, InputIt last,
132  const Hasher &hf = Hasher(),
133  const Equal &eql = Equal()) :
134  Base(first, last, hboost::unordered::detail::default_bucket_count,
135  hf, eql) {}
136 
137  /// Initialize the map using an initializer list. The initializer list is a
138  /// list of pairs of items to add to the map. E.g:
139  /// @code
140  /// UT_Map<int, const char *> foo = {{1, "one"}, {2, "two"}};
141  /// @endcode
142  UT_Map(std::initializer_list<value_type> init_list)
143  {
144  // We can't thunk down to the hboost::unordered_map initializer_list
145  // constructor, since it seems disabled when building with clang.
146  this->insert(init_list.begin(), init_list.end());
147  }
148 
149  /// Returns the approximate size, in bytes, of the memory consumed by this map
150  /// or, optionally, only the data contained within.
151  int64 getMemoryUsage(bool inclusive) const
152  {
153  int64 mem = inclusive ? sizeof(*this) : 0;
154  mem += UTgetMemoryUsage(*static_cast<const Base *>(this), false);
155  return mem;
156  }
157 
158  /// Returns @c true if a value with the @c key is contained in the map.
159  bool contains(const key_type &key) const
160  {
161  return this->find(key) != this->end();
162  }
163 
164  /// Returns the value at the key if it exists, or the provided default
165  /// value if it does not.
166  /// NOTE: Considering making this return const V&? Don't.
167  /// Lifetime extension rules likely can't be used to make that safe.
168  /// eg. const Foo &foo = get(key, Foo()) will return a stale reference.
169  V get(const key_type &key, const V &defval) const
170  {
171  auto it = this->find(key);
172  if (it == this->end())
173  return defval;
174  return it->second;
175  }
176 
177  /// The implementation of clear() is O(bucket_count()), not O(size()),
178  /// which can cause unexpected performance issues if the map has a large
179  /// capacity.
180  /// For std::unordered_map this was defect 2550
181  /// (http://cplusplus.github.io/LWG/lwg-defects.html#2550)
182  /// When updating or changing the underlying implemention, verify if this
183  /// is still necessary.
184  void clear()
185  {
186  // clear() is slightly faster than erase(begin(), end()) in typical
187  // scenarios, so only switch over to erase() once there are a lot of
188  // empty buckets.
189  if (Base::bucket_count() > 20 * Base::size())
190  Base::erase(Base::begin(), Base::end());
191  else
192  Base::clear();
193  }
194 
195 protected:
196  template<typename VIT, typename VT>
198  {
199  VT &operator()(const VIT &v) const { return v->first; }
200  };
201  template<typename VIT, typename VT>
203  {
204  VT &operator()(const VIT &v) const { return v->second; }
205  };
206 
207  template<typename IT, typename T, typename DR>
209  {
210  public:
211  using iterator_category = std::forward_iterator_tag;
212  using value_type = T;
213  using difference_type = std::ptrdiff_t;
214  using pointer = T*;
215  using reference = T&;
216 
218 
219  template<typename EIT, typename EDR>
221  it(src.it) {}
222 
223  reference operator*() const { DR dr; return dr(it); }
224  pointer operator->() const { DR dr; return &dr(it); }
225 
227  { return it == o.it; }
228 
230  { return it != o.it; }
231 
233  {
234  ++it;
235  return *this;
236  }
237 
238  protected:
239  friend class UT_Map<K, V, H, P>;
240 
241  partial_iterator_base(IT it) : it(it) {}
242  private:
243  IT it;
244  };
245 
246 public:
247  using const_key_iterator = partial_iterator_base<const_iterator, const key_type,
248  deref_pair_first<const_iterator, const key_type>>;
249  using mapped_iterator = partial_iterator_base<iterator, mapped_type,
250  deref_pair_second<iterator, mapped_type>>;
251  using const_mapped_iterator = partial_iterator_base<const_iterator, const mapped_type,
252  deref_pair_second<const_iterator, const mapped_type>>;
253 
254  /// Returns a range object that iterates over the map but returns only
255  /// the key values.
256  /// Example:
257  /// @code
258  /// UT_Map<int, const char *> foo = {{1, "one"}, {2, "two"}};
259  /// for (int key : foo.key_range())
260  /// std::cout << key << "\n";
261  /// @endcode
263  { return UTmakeRange(const_key_iterator(this->begin()),
264  const_key_iterator(this->end())); }
265 
266  /// Returns a range object that iterates over the map but returns only
267  /// the mapped values.
269  { return UTmakeRange(mapped_iterator(this->begin()),
270  mapped_iterator(this->end())); }
271 
272  /// Returns a const range object that iterates over the map but returns
273  /// only the mapped values.
275  { return UTmakeRange(const_mapped_iterator(this->begin()),
276  const_mapped_iterator(this->end())); }
277 };
278 
279 /// Sorted map container.
280 template<typename K, typename V, typename C = std::less<K> >
281 class UT_SortedMap : public std::map<K, V, C>
282 {
283 public:
284  // Hoisting of base types.
285  typedef std::map<K, V, C> Base;
286  typedef typename Base::key_type key_type;
287  typedef typename Base::mapped_type mapped_type;
288  typedef typename Base::value_type value_type;
289  typedef typename Base::key_compare key_compare;
290  typedef typename Base::iterator iterator;
291  typedef typename Base::const_iterator const_iterator;
292 
293  typedef C LessThan;
294 
296 
297  explicit UT_SortedMap(const LessThan &lt) : Base(lt) {}
298 
299  template<typename InputIt>
300  UT_SortedMap(InputIt first, InputIt last) : Base(first, last) {}
301 
302  template<typename InputIt>
303  UT_SortedMap(InputIt first, InputIt last, const LessThan &lt) :
304  Base(first, last, lt) {}
305 
306  /// Initialize the map using an initializer list. The initializer list is a
307  /// list of pairs of items to add to the map. E.g:
308  /// @code
309  /// UT_Map<int, const char *> foo = {{1, "one"}, {2, "two"}};
310  /// @endcode
311  UT_SortedMap(std::initializer_list<value_type> init_list)
312  {
313  this->insert(init_list.begin(), init_list.end());
314  }
315 
316  int64 getMemoryUsage(bool inclusive) const
317  {
318  int64 mem = inclusive ? sizeof(*this) : 0;
319  mem += UTgetMemoryUsage(*static_cast<const Base *>(this), false);
320  return mem;
321  }
322 
323  bool contains(const key_type &key) const
324  {
325  return this->find(key) != this->end();
326  }
327 
328 protected:
329  template<typename VIT, typename VT>
331  {
332  VT &operator()(const VIT &v) const { return v->first; }
333  };
334  template<typename VIT, typename VT>
336  {
337  VT &operator()(const VIT &v) const { return v->second; }
338  };
339 
340  template<typename IT, typename T, typename DR>
342  {
343  public:
344  using iterator_category = std::forward_iterator_tag;
345  using value_type = T;
346  using difference_type = std::ptrdiff_t;
347  using pointer = T*;
348  using reference = T&;
349 
351 
352  template<typename EIT, typename EDR>
354  it(src.it) {}
355 
356  reference operator*() const { DR dr; return dr(it); }
357  pointer operator->() const { DR dr; return &dr(it); }
358 
360  { return it == o.it; }
361 
363  { return it != o.it; }
364 
366  {
367  ++it;
368  return *this;
369  }
370 
371  protected:
372  friend class UT_SortedMap<K, V, C>;
373 
374  partial_iterator_base(IT it) : it(it) {}
375  private:
376  IT it;
377  };
378 
379 public:
380  using key_iterator = partial_iterator_base<iterator, key_type,
381  deref_pair_first<iterator, key_type>>;
382  using const_key_iterator = partial_iterator_base<const_iterator, const key_type,
383  deref_pair_first<const_iterator, const key_type>>;
384  using mapped_iterator = partial_iterator_base<iterator, mapped_type,
385  deref_pair_second<iterator, mapped_type>>;
386  using const_mapped_iterator = partial_iterator_base<const_iterator, const mapped_type,
387  deref_pair_second<const_iterator, const mapped_type>>;
388 
389  /// Returns a range object that iterates over the map but returns only
390  /// the key values.
392  { return UTmakeRange(key_iterator(this->begin()),
393  key_iterator(this->end())); }
394 
395  /// Returns a const range object that iterates over the map but returns
396  /// only the key values.
398  { return UTmakeRange(const_key_iterator(this->begin()),
399  const_key_iterator(this->end())); }
400 
401  /// Returns a range object that iterates over the map but returns only
402  /// the mapped values.
404  { return UTmakeRange(mapped_iterator(this->begin()),
405  mapped_iterator(this->end())); }
406 
407  /// Returns a const range object that iterates over the map but returns
408  /// only the mapped values.
410  { return UTmakeRange(const_mapped_iterator(this->begin()),
411  const_mapped_iterator(this->end())); }
412 };
413 
414 namespace std
415 {
416  // This helper needs to live in the 'std' namespace for argument-dependent
417  // lookup to succeed.
418  template<typename OS, typename K, typename V>
419  inline OS &
420  operator<<(OS &os, const pair<K, V> &v)
421  {
422  os << "<" << v.first << ", " << v.second << ">";
423  return os;
424  }
425 }
426 
427 template<typename OS, typename K, typename V>
428 inline OS &
429 operator<<(OS &os, const UT_Map<K, V> &d)
430 {
431  os << "UT_Map" << UT_ContainerPrinter<UT_Map<K, V> >(d);
432  return os;
433 }
434 
435 template<typename OS, typename K, typename V>
436 inline OS &
437 operator<<(OS &os, const UT_SortedMap<K, V> &d)
438 {
439  os << "UT_SortedMap" << UT_ContainerPrinter<UT_SortedMap<K, V> >(d);
440  return os;
441 }
442 
443 #endif
partial_iterator_base< iterator, mapped_type, deref_pair_second< iterator, mapped_type >> mapped_iterator
Definition: UT_Map.h:250
GLint first
Definition: glcorearb.h:405
Base::key_type key_type
Definition: UT_Map.h:112
UT_IteratorRange< const_key_iterator > key_range() const
Definition: UT_Map.h:262
Unsorted map container.
Definition: UT_Map.h:107
int64 getMemoryUsage(bool inclusive) const
Definition: UT_Map.h:316
const GLdouble * v
Definition: glcorearb.h:837
P Equal
Definition: UT_Map.h:120
int64 getMemoryUsage(bool inclusive) const
Definition: UT_Map.h:151
std::forward_iterator_tag iterator_category
Definition: UT_Map.h:344
UT_IteratorRange< IterT > UTmakeRange(IterT &&b, IterT &&e)
partial_iterator_base(const partial_iterator_base< EIT, T, EDR > &src)
Definition: UT_Map.h:353
VT & operator()(const VIT &v) const
Definition: UT_Map.h:332
Base::key_type key_type
Definition: UT_Map.h:286
void clear()
Definition: UT_Map.h:184
std::ptrdiff_t difference_type
Definition: UT_Map.h:213
reference operator*() const
Definition: UT_Map.h:223
OIIO_FORCEINLINE vbool4 insert(const vbool4 &a, bool val)
Helper: substitute val for a[i].
Definition: simd.h:3436
H Hasher
Definition: UT_Map.h:119
uint64 value_type
Definition: GA_PrimCompat.h:29
partial_iterator_base & operator++()
Definition: UT_Map.h:232
bool operator!=(const partial_iterator_base< IT, T, DR > &o) const
Definition: UT_Map.h:362
UT_SortedMap(std::initializer_list< value_type > init_list)
Definition: UT_Map.h:311
Base::value_type value_type
Definition: UT_Map.h:288
UT_SortedMap(InputIt first, InputIt last)
Definition: UT_Map.h:300
hboost::unordered_map< K, V, H, P > Base
Definition: UT_Map.h:111
Sorted map container.
Definition: UT_Map.h:281
VT & operator()(const VIT &v) const
Definition: UT_Map.h:204
partial_iterator_base< iterator, key_type, deref_pair_first< iterator, key_type >> key_iterator
Definition: UT_Map.h:381
std::map< K, V, C > Base
Definition: UT_Map.h:285
pointer operator->() const
Definition: UT_Map.h:224
bool operator!=(const partial_iterator_base< IT, T, DR > &o) const
Definition: UT_Map.h:229
Base::mapped_type mapped_type
Definition: UT_Map.h:113
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:248
UT_SortedMap(InputIt first, InputIt last, const LessThan &lt)
Definition: UT_Map.h:303
Base::iterator iterator
Definition: UT_Map.h:290
VT & operator()(const VIT &v) const
Definition: UT_Map.h:199
UT_IteratorRange< const_mapped_iterator > mapped_range() const
Definition: UT_Map.h:409
UT_Map(const Hasher &hf=Hasher(), const Equal &eql=Equal())
Definition: UT_Map.h:124
UT_SortedMap()
Definition: UT_Map.h:295
partial_iterator_base< const_iterator, const mapped_type, deref_pair_second< const_iterator, const mapped_type >> const_mapped_iterator
Definition: UT_Map.h:252
UT_IteratorRange< mapped_iterator > mapped_range()
Definition: UT_Map.h:268
long long int64
Definition: SYS_Types.h:116
partial_iterator_base & operator++()
Definition: UT_Map.h:365
STATIC_INLINE uint64_t H(uint64_t x, uint64_t y, uint64_t mul, int r)
Definition: farmhash.h:701
Base::iterator iterator
Definition: UT_Map.h:117
Base::const_iterator const_iterator
Definition: UT_Map.h:291
int64 UTgetMemoryUsage(const hboost::unordered_map< K, V, H, P > &map, bool inclusive)
Definition: UT_Map.h:72
VT & operator()(const VIT &v) const
Definition: UT_Map.h:337
bool operator==(const partial_iterator_base< IT, T, DR > &o) const
Definition: UT_Map.h:359
UT_SortedMap(const LessThan &lt)
Definition: UT_Map.h:297
Base::mapped_type mapped_type
Definition: UT_Map.h:287
Base::hasher hasher
Definition: UT_Map.h:115
GLsizeiptr size
Definition: glcorearb.h:664
std::forward_iterator_tag iterator_category
Definition: UT_Map.h:211
UT_IteratorRange< const_mapped_iterator > mapped_range() const
Definition: UT_Map.h:274
UT_IteratorRange< key_iterator > key_range()
Definition: UT_Map.h:391
UT_Map(InputIt first, InputIt last, const Hasher &hf=Hasher(), const Equal &eql=Equal())
Definition: UT_Map.h:131
UT_IteratorRange< mapped_iterator > mapped_range()
Definition: UT_Map.h:403
reference operator*() const
Definition: UT_Map.h:356
UT_Map(std::initializer_list< value_type > init_list)
Definition: UT_Map.h:142
UT_IteratorRange< const_key_iterator > key_range() const
Definition: UT_Map.h:397
Base::value_type value_type
Definition: UT_Map.h:114
bool contains(const key_type &key) const
Definition: UT_Map.h:323
Base::const_iterator const_iterator
Definition: UT_Map.h:118
partial_iterator_base< iterator, mapped_type, deref_pair_second< iterator, mapped_type >> mapped_iterator
Definition: UT_Map.h:385
Base::key_compare key_compare
Definition: UT_Map.h:289
partial_iterator_base< const_iterator, const key_type, deref_pair_first< const_iterator, const key_type >> const_key_iterator
Definition: UT_Map.h:383
Base::key_equal key_equal
Definition: UT_Map.h:116
partial_iterator_base< const_iterator, const mapped_type, deref_pair_second< const_iterator, const mapped_type >> const_mapped_iterator
Definition: UT_Map.h:387
bool operator==(const partial_iterator_base< IT, T, DR > &o) const
Definition: UT_Map.h:226
partial_iterator_base(const partial_iterator_base< EIT, T, EDR > &src)
Definition: UT_Map.h:220
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2089
bool contains(const key_type &key) const
Returns true if a value with the key is contained in the map.
Definition: UT_Map.h:159
GLenum src
Definition: glcorearb.h:1793
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:483