7#ifndef PXR_BASE_TF_DENSE_HASH_MAP_H
8#define PXR_BASE_TF_DENSE_HASH_MAP_H
14#include "pxr/base/tf/hashmap.h"
21PXR_NAMESPACE_OPEN_SCOPE
38 class EqualKey = std::equal_to<Key>,
39 unsigned Threshold = 128
47 using mapped_type = Data;
48 using value_type = std::pair<const Key, Data>;
49 using pointer = value_type*;
50 using const_pointer =
const value_type*;
60 struct _InternalValueType
62 _InternalValueType() {}
64 _InternalValueType(
const Key &k,
const Data &d)
67 _InternalValueType &operator=(
const _InternalValueType &rhs) {
73 _value.value_type::~value_type();
74 new (&_value) value_type(rhs.GetValue());
80 value_type &GetValue() {
84 const value_type &GetValue()
const {
88 void swap(_InternalValueType &rhs) {
93 Key tmp = _value.first;
95 _value.first.Key::~Key();
96 new (
const_cast<Key *
>(&_value.first)) Key(rhs._value.first);
98 rhs._value.first.Key::~Key();
99 new (
const_cast<Key *
>(&rhs._value.first)) Key(tmp);
101 swap(_value.second, rhs._value.second);
112 typedef std::vector<_InternalValueType> _Vector;
115 typedef TfHashMap<Key, size_t, HashFn, EqualKey> _HashMap;
127 template <
class ElementType,
class UnderlyingIterator>
131 using iterator_category = std::bidirectional_iterator_tag;
132 using value_type = ElementType;
133 using reference = ElementType&;
134 using pointer = ElementType*;
135 using difference_type =
typename UnderlyingIterator::difference_type;
138 _IteratorBase() =
default;
141 template<
class OtherIteratorType>
142 _IteratorBase(
const OtherIteratorType &rhs)
143 : _iter(rhs._GetUnderlyingIterator()) {}
145 reference operator*()
const {
return dereference(); }
146 pointer operator->()
const {
return &(dereference()); }
148 _IteratorBase& operator++() {
153 _IteratorBase& operator--() {
158 _IteratorBase operator++(
int) {
159 _IteratorBase result(*
this);
164 _IteratorBase operator--(
int) {
165 _IteratorBase result(*
this);
170 template <
class OtherIteratorType>
171 bool operator==(
const OtherIteratorType& other)
const {
175 template <
class OtherIteratorType>
176 bool operator!=(
const OtherIteratorType& other)
const {
177 return !equal(other);
185 _IteratorBase(
const UnderlyingIterator &iter)
188 template<
class OtherIteratorType>
189 bool equal(
const OtherIteratorType &rhs)
const {
190 return _iter == rhs._iter;
201 ElementType &dereference()
const {
205 return _iter->GetValue();
208 UnderlyingIterator _GetUnderlyingIterator()
const {
214 UnderlyingIterator _iter;
224 _IteratorBase<value_type, typename _Vector::iterator>
230 _IteratorBase<const value_type, typename _Vector::const_iterator>
241 const HashFn &hashFn = HashFn(),
242 const EqualKey &equalKey = EqualKey())
250 template <
class Iterator>
258 insert(l.begin(), l.end());
264 : _storage(rhs._storage) {
266 _h = std::make_unique<_HashMap>(*rhs._h);
291 insert(l.begin(), l.end());
309 if (iter->second != riter->second)
317 return !(*
this == rhs);
330 _storage.swap(rhs._storage);
337 return _vec().empty();
343 return _vec().size();
349 return _vec().begin();
361 return _vec().begin();
373 return _vec().cbegin();
379 return _vec().cbegin();
385 return _vec().empty() ? nullptr : &_vec().front().GetValue();
391 return _vec().empty() ? nullptr : &_vec().front().GetValue();
397 return _vec().empty() ? nullptr : &_vec().front().GetValue();
404 typename _HashMap::const_iterator iter = _h->find(k);
405 if (iter == _h->end())
408 return _vec().begin() + iter->second;
410 return _FindInVec(k);
418 typename _HashMap::const_iterator iter = _h->find(k);
419 if (iter == _h->end())
422 return _vec().begin() + iter->second;
424 return _FindInVec(k);
430 size_t count(
const key_type &k)
const {
441 std::pair<typename _HashMap::iterator, bool> res =
442 _h->insert(std::make_pair(v.first, size()));
448 iterator iter = _FindInVec(v.first);
454 _vec().push_back(_InternalValueType(v.first, v.second));
455 _CreateTableIfNeeded();
463 template<
class IteratorType>
464 void insert(IteratorType i0, IteratorType i1) {
469 if (
size() + std::distance(i0, i1) >= Threshold)
473 for(IteratorType iter = i0; iter != i1; ++iter)
480 template <
class Iterator>
485 _CreateTableIfNeeded();
498 return insert(value_type(key, Data())).first->second;
519 _h->erase(iter->first);
522 if (iter != std::prev(
end())) {
526 typename _Vector::iterator vi = iter._GetUnderlyingIterator();
529 vi->swap(_vec().back());
533 (*_h)[vi->GetValue().first] = vi - _vec().begin();
544 for(
iterator iter = i0; iter != i1; ++iter)
545 _h->erase(iter->first);
548 typename _Vector::const_iterator vremain = _vec().erase(
549 i0._GetUnderlyingIterator(), i1._GetUnderlyingIterator());
552 for(; vremain != _vec().end(); ++vremain)
553 (*_h)[vremain->GetValue().first] = vremain - _vec().begin();
562 _vec().shrink_to_fit();
570 if (sz < Threshold) {
577 _h.reset(
new _HashMap(sz, _hash(), _equ()));
578 for(
size_t i=0; i<sz; ++i)
579 _h->insert(std::make_pair(_vec()[i].GetValue().first, i));
595 return _storage.vector;
609 const _Vector &_vec()
const {
610 return _storage.vector;
614 const HashFn &_hash()
const {
619 const EqualKey &_equ()
const {
624 inline iterator _FindInVec(
const key_type &k) {
625 _Vector &vec = _vec();
626 EqualKey &equ = _equ();
627 typename _Vector::iterator iter = vec.begin(),
end = vec.end();
628 for (; iter !=
end; ++iter) {
629 if (equ(iter->GetValue().first, k))
637 _Vector
const &vec = _vec();
638 EqualKey
const &equ = _equ();
639 typename _Vector::const_iterator iter = vec.begin(),
end = vec.end();
640 for (; iter !=
end; ++iter) {
641 if (equ(iter->GetValue().first, k))
648 inline void _CreateTableIfNeeded() {
649 if (
size() >= Threshold) {
656 inline void _CreateTable() {
658 _h.reset(
new _HashMap(Threshold, _hash(), _equ()));
659 for(
size_t i=0; i <
size(); ++i)
660 _h->insert(std::make_pair(_vec()[i].GetValue().first, i));
669 private EqualKey,
private HashFn {
670 static_assert(!std::is_same<EqualKey, HashFn>::value,
671 "EqualKey and HashFn must be distinct types.");
672 _CompressedStorage() =
default;
673 _CompressedStorage(
const EqualKey& equalKey,
const HashFn& hashFn)
674 : EqualKey(equalKey), HashFn(hashFn) {}
676 void swap(_CompressedStorage& other) {
678 vector.swap(other.vector);
679 swap(
static_cast<EqualKey&
>(*
this),
static_cast<EqualKey&
>(other));
680 swap(
static_cast<HashFn&
>(*
this),
static_cast<HashFn&
>(other));
685 _CompressedStorage _storage;
688 std::unique_ptr<_HashMap> _h;
691PXR_NAMESPACE_CLOSE_SCOPE
Define function attributes.
#define ARCH_EMPTY_BASES
Macro to begin the definition of a class that is using private inheritance to take advantage of the e...
A hash map with contiguous storage, suitable for use with TfSpan, e.g.
Data & operator[](const key_type &key)
Indexing operator.
_IteratorBase< value_type, typename _Vector::iterator > iterator
An iterator type for this map.
const_pointer cdata() const
Returns a const pointer to the map's data.
size_t size() const
Returns the size of the map.
TfDenseHashMap(std::initializer_list< value_type > l)
Construct from an initializer_list.
const_iterator begin() const
Returns a const_iterator pointing to the beginning of the map.
TfDenseHashMap(const HashFn &hashFn=HashFn(), const EqualKey &equalKey=EqualKey())
Ctor.
const_pointer data() const
Returns a const pointer to the map's data.
pointer data()
Returns a pointer to the map's data.
const_iterator cbegin() const
Returns a const_iterator pointing to the beginning of the map.
size_t count(const key_type &k) const
Returns the number of elements with key k.
size_t erase(const key_type &k)
Erase element with key k.
const_iterator find(const key_type &k) const
Finds the element with key k.
void insert(IteratorType i0, IteratorType i1)
Insert a range into the hash map.
iterator find(const key_type &k)
Finds the element with key k.
TfDenseHashMap & operator=(TfDenseHashMap &&rhs)=default
Move assignment operator.
void shrink_to_fit()
Optimize storage space.
bool empty() const
true if the map's size is 0.
bool operator==(const TfDenseHashMap &rhs) const
Equality operator.
void erase(const iterator &iter)
Erases element pointed to by iter.
_IteratorBase< const value_type, typename _Vector::const_iterator > const_iterator
An iterator type for this map.
TfDenseHashMap(Iterator begin, Iterator end)
Construct with range.
const_iterator cend() const
Returns a const_iterator pointing to the end of the map.
TfDenseHashMap & operator=(const TfDenseHashMap &rhs)
Copy assignment operator.
insert_result insert(const value_type &v)
Returns a pair of <iterator, bool> where iterator points to the element in the list and bool is true ...
void clear()
Erases all of the elements.
iterator end()
Returns an iterator pointing to the end of the map.
void insert_unique(Iterator begin, Iterator end)
Insert a range of unique elements into the container.
const_iterator end() const
Returns a const_iterator pointing to the end of the map.
std::pair< iterator, bool > insert_result
Return type for insert() method.
void swap(TfDenseHashMap &rhs)
Swaps the contents of two maps.
iterator begin()
Returns an iterator pointing to the beginning of the map.
void erase(iterator i0, iterator i1)
Erases a range from the map.
TfDenseHashMap(const TfDenseHashMap &rhs)
Copy Ctor.
TfDenseHashMap(TfDenseHashMap &&rhs)=default
Move Ctor.
void reserve(size_t n)
Reserve space.
TfDenseHashMap & operator=(std::initializer_list< value_type > l)
Assignment from an initializer_list.