26 #ifndef EASTL_INTERNAL_HASHTABLE_H
27 #define EASTL_INTERNAL_HASHTABLE_H
30 #include <EABase/eabase.h>
31 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
35 #include <EASTL/internal/config.h>
36 #include <EASTL/type_traits.h>
37 #include <EASTL/allocator.h>
38 #include <EASTL/iterator.h>
39 #include <EASTL/functional.h>
40 #include <EASTL/utility.h>
41 #include <EASTL/algorithm.h>
42 #include <EASTL/initializer_list.h>
43 #include <EASTL/tuple.h>
46 EA_DISABLE_ALL_VC_WARNINGS()
49 EA_RESTORE_ALL_VC_WARNINGS()
54 EA_DISABLE_VC_WARNING(4512 4530 4571);
64 #ifndef EASTL_HASHTABLE_DEFAULT_NAME
65 #define EASTL_HASHTABLE_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " hashtable"
71 #ifndef EASTL_HASHTABLE_DEFAULT_ALLOCATOR
72 #define EASTL_HASHTABLE_DEFAULT_ALLOCATOR allocator_type(EASTL_HASHTABLE_DEFAULT_NAME)
78 enum { kHashtableAllocFlagBuckets = 0x00400000 };
94 #define EASTL_MACRO_SWAP(Type, a, b) \
95 { Type temp = a; a = b; b = temp; }
106 template <
typename Value,
bool bCacheHashCode>
109 EA_DISABLE_VC_WARNING(4625 4626)
110 #ifdef EA_COMPILER_MSVC_2015
111 EA_DISABLE_VC_WARNING(5026)
113 template <
typename Value>
122 eastl_size_t mnHashCode;
125 template <
typename Value>
136 #ifdef EA_COMPILER_MSVC_2015
137 EA_RESTORE_VC_WARNING()
139 EA_RESTORE_VC_WARNING()
158 template <
class U>
static eastl::yes_type test(decltype(U::mnHashCode)* = 0);
160 static const bool value =
sizeof(test<T>(0)) ==
sizeof(eastl::yes_type);
169 #define ENABLE_IF_HAS_HASHCODE(T, RT) typename eastl::enable_if<Internal::has_hashcode_member<T>::value, RT>::type*
170 #define ENABLE_IF_HASHCODE_EASTLSIZET(T, RT) typename eastl::enable_if<eastl::is_convertible<T, eastl_size_t>::value, RT>::type
171 #define ENABLE_IF_TRUETYPE(T) typename eastl::enable_if<T::value>::type*
172 #define DISABLE_IF_TRUETYPE(T) typename eastl::enable_if<!T::value>::type*
182 template <
typename Value,
bool bCacheHashCode>
193 { mpNode = mpNode->mpNext; }
205 template <
typename Value,
bool bConst,
bool bCacheHashCode>
212 typedef Value value_type;
215 typedef ptrdiff_t difference_type;
216 typedef EASTL_ITC_NS::forward_iterator_tag iterator_category;
226 {
return base_type::mpNode->mValue; }
229 {
return &(base_type::mpNode->mValue); }
232 { base_type::increment();
return *
this; }
235 {
node_iterator temp(*
this); base_type::increment();
return temp; }
251 template <
typename Value,
bool bCacheHashCode>
259 template <
typename,
typename,
typename,
typename,
typename,
typename,
typename,
typename,
typename,
bool,
bool,
bool>
262 template <
typename,
bool,
bool>
265 template <
typename V,
bool b>
268 template <
typename V,
bool b>
276 : mpNode(pNode), mpBucket(pBucket) { }
278 void increment_bucket()
281 while(*mpBucket == NULL)
288 mpNode = mpNode->mpNext;
290 while(mpNode == NULL)
291 mpNode = *++mpBucket;
309 template <
typename Value,
bool bConst,
bool bCacheHashCode>
317 typedef Value value_type;
320 typedef ptrdiff_t difference_type;
321 typedef EASTL_ITC_NS::forward_iterator_tag iterator_category;
334 {
return base_type::mpNode->mValue; }
337 {
return &(base_type::mpNode->mValue); }
340 { base_type::increment();
return *
this; }
346 {
return base_type::mpNode; }
363 template <
typename Iterator>
364 inline typename eastl::iterator_traits<Iterator>::difference_type
370 template <
typename Iterator>
371 inline typename eastl::iterator_traits<Iterator>::difference_type
372 distance_fw_impl(Iterator first, Iterator last, EASTL_ITC_NS::forward_iterator_tag)
373 {
return eastl::distance(first, last); }
375 template <
typename Iterator>
376 inline typename eastl::iterator_traits<Iterator>::difference_type
377 ht_distance(Iterator first, Iterator last)
379 typedef typename eastl::iterator_traits<Iterator>::iterator_category IC;
393 uint32_t operator()(
size_t r, uint32_t n)
const
417 float mfMaxLoadFactor;
418 float mfGrowthFactor;
419 mutable uint32_t mnNextResize;
423 : mfMaxLoadFactor(fMaxLoadFactor), mfGrowthFactor(2.f), mnNextResize(0) { }
425 float GetMaxLoadFactor()
const
426 {
return mfMaxLoadFactor; }
430 static uint32_t GetPrevBucketCountOnly(uint32_t nBucketCountHint);
434 uint32_t GetPrevBucketCount(uint32_t nBucketCountHint)
const;
438 uint32_t GetNextBucketCount(uint32_t nBucketCountHint)
const;
442 uint32_t GetBucketCount(uint32_t nElementCount)
const;
449 GetRehashRequired(uint32_t nBucketCount, uint32_t nElementCount, uint32_t nElementAdd)
const;
473 template <
typename RehashPolicy,
typename Hashtable>
476 template <
typename Hashtable>
481 float get_max_load_factor()
const
483 const Hashtable*
const pThis =
static_cast<const Hashtable*
>(
this);
484 return pThis->rehash_policy().GetMaxLoadFactor();
489 void set_max_load_factor(
float fMaxLoadFactor)
491 Hashtable*
const pThis =
static_cast<Hashtable*
>(
this);
513 template <
typename Key,
typename Value,
typename ExtractKey,
typename Equal,
514 typename H1,
typename H2,
typename H,
bool bCacheHashCode>
523 template <
typename Key,
typename Value,
typename ExtractKey,
typename Equal,
typename H1,
typename H2,
typename H>
527 ExtractKey mExtractKey;
532 H1 hash_function()
const
535 Equal equal_function()
const
538 const Equal& key_eq()
const
545 typedef void* hash_code_t;
546 typedef uint32_t bucket_index_t;
548 hash_code_base(
const ExtractKey& extractKey,
const Equal& eq,
const H1&,
const H2&,
const H& h)
549 : mExtractKey(extractKey), mEqual(eq), mRangedHash(h) { }
551 hash_code_t get_hash_code(
const Key& key)
const
557 bucket_index_t bucket_index(hash_code_t, uint32_t)
const
558 {
return (bucket_index_t)0; }
560 bucket_index_t bucket_index(
const Key& key, hash_code_t, uint32_t nBucketCount)
const
561 {
return (bucket_index_t)mRangedHash(key, nBucketCount); }
564 {
return (bucket_index_t)mRangedHash(mExtractKey(pNode->mValue), nBucketCount); }
567 {
return mEqual(key, mExtractKey(pNode->mValue)); }
580 eastl::swap(mExtractKey, x.mExtractKey);
581 eastl::swap(mEqual, x.mEqual);
582 eastl::swap(mRangedHash, x.mRangedHash);
599 template <
typename Key,
typename Value,
typename ExtractKey,
typename Equal,
typename H1,
typename H2,
typename H>
600 struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, true>;
610 template <
typename Key,
typename Value,
typename ExtractKey,
typename Equal,
typename H1,
typename H2>
614 ExtractKey mExtractKey;
622 H1 hash_function()
const
625 Equal equal_function()
const
628 const Equal& key_eq()
const
635 typedef size_t hash_code_t;
636 typedef uint32_t bucket_index_t;
640 : mExtractKey(ex), mEqual(eq), m_h1(h1), m_h2(h2) { }
642 hash_code_t get_hash_code(
const Key& key)
const
643 {
return (hash_code_t)m_h1(key); }
645 bucket_index_t bucket_index(hash_code_t c, uint32_t nBucketCount)
const
646 {
return (bucket_index_t)m_h2(c, nBucketCount); }
648 bucket_index_t bucket_index(
const Key&, hash_code_t c, uint32_t nBucketCount)
const
649 {
return (bucket_index_t)m_h2(c, nBucketCount); }
651 bucket_index_t bucket_index(
const node_type* pNode, uint32_t nBucketCount)
const
652 {
return (bucket_index_t)m_h2((hash_code_t)m_h1(mExtractKey(pNode->mValue)), nBucketCount); }
654 bool compare(
const Key& key, hash_code_t,
node_type* pNode)
const
655 {
return mEqual(key, mExtractKey(pNode->mValue)); }
660 void set_code(
node_type*, hash_code_t)
const
665 eastl::swap(mExtractKey, x.mExtractKey);
666 eastl::swap(mEqual, x.mEqual);
667 eastl::swap(m_h1, x.m_h1);
668 eastl::swap(m_h2, x.m_h2);
681 template <
typename Key,
typename Value,
typename ExtractKey,
typename Equal,
typename H1,
typename H2>
685 ExtractKey mExtractKey;
693 H1 hash_function()
const
696 Equal equal_function()
const
699 const Equal& key_eq()
const
706 typedef uint32_t hash_code_t;
707 typedef uint32_t bucket_index_t;
711 : mExtractKey(ex), mEqual(eq), m_h1(h1), m_h2(h2) { }
713 hash_code_t get_hash_code(
const Key& key)
const
714 {
return (hash_code_t)m_h1(key); }
716 bucket_index_t bucket_index(hash_code_t c, uint32_t nBucketCount)
const
717 {
return (bucket_index_t)m_h2(c, nBucketCount); }
719 bucket_index_t bucket_index(
const Key&, hash_code_t c, uint32_t nBucketCount)
const
720 {
return (bucket_index_t)m_h2(c, nBucketCount); }
722 bucket_index_t bucket_index(
const node_type* pNode, uint32_t nBucketCount)
const
723 {
return (bucket_index_t)m_h2((uint32_t)pNode->mnHashCode, nBucketCount); }
725 bool compare(
const Key& key, hash_code_t c,
node_type* pNode)
const
726 {
return (pNode->mnHashCode == c) && mEqual(key, mExtractKey(pNode->mValue)); }
729 { pDest->mnHashCode = pSource->mnHashCode; }
731 void set_code(
node_type* pDest, hash_code_t c)
const
732 { pDest->mnHashCode = c; }
736 eastl::swap(mExtractKey, x.mExtractKey);
737 eastl::swap(mEqual, x.mEqual);
738 eastl::swap(m_h1, x.m_h1);
739 eastl::swap(m_h2, x.m_h2);
824 template <
typename Key,
typename Value,
typename Allocator,
typename ExtractKey,
825 typename Equal,
typename H1,
typename H2,
typename H,
826 typename RehashPolicy,
bool bCacheHashCode,
bool bMutableIterators,
bool bUniqueKeys>
828 :
public rehash_base<RehashPolicy, hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H, RehashPolicy, bCacheHashCode, bMutableIterators, bUniqueKeys> >,
829 public hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, bCacheHashCode>
832 typedef Key key_type;
833 typedef Value value_type;
834 typedef typename ExtractKey::result_type mapped_type;
836 typedef typename hash_code_base_type::hash_code_t hash_code_t;
837 typedef Allocator allocator_type;
838 typedef Equal key_equal;
839 typedef ptrdiff_t difference_type;
840 typedef eastl_size_t size_type;
841 typedef value_type& reference;
842 typedef const value_type& const_reference;
849 typedef hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H,
850 RehashPolicy, bCacheHashCode, bMutableIterators, bUniqueKeys>
this_type;
851 typedef RehashPolicy rehash_policy_type;
852 typedef ExtractKey extract_key_type;
858 using hash_code_base_type::key_eq;
859 using hash_code_base_type::hash_function;
860 using hash_code_base_type::mExtractKey;
861 using hash_code_base_type::get_hash_code;
862 using hash_code_base_type::bucket_index;
863 using hash_code_base_type::compare;
864 using hash_code_base_type::set_code;
865 using hash_code_base_type::copy_code;
867 static const bool kCacheHashCode = bCacheHashCode;
872 kAllocFlagBuckets = eastl::kHashtableAllocFlagBuckets
877 size_type mnBucketCount;
878 size_type mnElementCount;
879 RehashPolicy mRehashPolicy;
880 allocator_type mAllocator;
883 hashtable(size_type nBucketCount,
const H1&,
const H2&,
const H&,
const Equal&,
const ExtractKey&,
884 const allocator_type&
allocator = EASTL_HASHTABLE_DEFAULT_ALLOCATOR);
886 template <
typename FowardIterator>
887 hashtable(FowardIterator first, FowardIterator last, size_type nBucketCount,
888 const H1&,
const H2&,
const H&,
const Equal&,
const ExtractKey&,
889 const allocator_type&
allocator = EASTL_HASHTABLE_DEFAULT_ALLOCATOR);
901 const allocator_type& get_allocator()
const EA_NOEXCEPT;
902 allocator_type& get_allocator() EA_NOEXCEPT;
903 void set_allocator(
const allocator_type&
allocator);
915 i.increment_bucket();
923 i.increment_bucket();
931 {
return iterator(mpBucketArray + mnBucketCount); }
959 bool empty()
const EA_NOEXCEPT
960 {
return mnElementCount == 0; }
962 size_type size()
const EA_NOEXCEPT
963 {
return mnElementCount; }
965 size_type bucket_count()
const EA_NOEXCEPT
966 {
return mnBucketCount; }
968 size_type bucket_size(size_type n)
const EA_NOEXCEPT
969 {
return (size_type)eastl::distance(begin(n), end(n)); }
976 float load_factor()
const EA_NOEXCEPT
977 {
return (
float)mnElementCount / (float)mnBucketCount; }
994 {
return mRehashPolicy; }
1000 template <
class... Args>
1003 template <
class... Args>
1006 template <
class... Args>
insert_return_type try_emplace(
const key_type& k, Args&&... args);
1007 template <
class... Args>
insert_return_type try_emplace(key_type&& k, Args&&... args);
1008 template <
class... Args>
iterator try_emplace(
const_iterator position,
const key_type& k, Args&&... args);
1016 template <
typename InputIterator>
void insert(InputIterator first, InputIterator last);
1027 class =
typename eastl::enable_if_t<
1028 #if EASTL_ENABLE_PAIR_FIRST_ELEMENT_CONSTRUCTOR
1029 !eastl::is_same_v<eastl::decay_t<P>, key_type> &&
1031 !eastl::is_literal_type_v<P> &&
1032 eastl::is_constructible_v<value_type, P&&>>>
1056 node_type* allocate_uninitialized_node();
1057 void free_uninitialized_node(
node_type* pNode);
1061 size_type erase(
const key_type& k);
1064 void clear(
bool clearBuckets);
1065 void reset_lose_memory() EA_NOEXCEPT;
1066 void rehash(size_type nBucketCount);
1067 void reserve(size_type nElementCount);
1069 iterator find(const key_type& key);
1087 template <typename U, typename UHash, typename BinaryPredicate>
1088 iterator find_as(const U& u, UHash uhash, BinaryPredicate predicate);
1090 template <typename U, typename UHash, typename BinaryPredicate>
1091 const_iterator find_as(const U& u, UHash uhash, BinaryPredicate predicate) const;
1093 template <typename U>
1096 template <typename U>
1107 template<typename HashCodeT>
1108 ENABLE_IF_HASHCODE_EASTLSIZET(HashCodeT,
iterator) find_by_hash(HashCodeT c)
1110 EASTL_CT_ASSERT_MSG(bCacheHashCode,
1111 "find_by_hash(hash_code_t c) is designed to avoid recomputing hashes, "
1112 "so it requires cached hash codes. Consider setting template parameter "
1113 "bCacheHashCode to true or using find_by_hash(const key_type& k, hash_code_t c) instead.");
1115 const size_type n = (size_type)bucket_index(c, (uint32_t)mnBucketCount);
1117 node_type*
const pNode = DoFindNode(mpBucketArray[n], c);
1119 return pNode ?
iterator(pNode, mpBucketArray + n) :
1120 iterator(mpBucketArray + mnBucketCount);
1123 template<
typename HashCodeT>
1124 ENABLE_IF_HASHCODE_EASTLSIZET(HashCodeT, const_iterator) find_by_hash(HashCodeT c)
const
1126 EASTL_CT_ASSERT_MSG(bCacheHashCode,
1127 "find_by_hash(hash_code_t c) is designed to avoid recomputing hashes, "
1128 "so it requires cached hash codes. Consider setting template parameter "
1129 "bCacheHashCode to true or using find_by_hash(const key_type& k, hash_code_t c) instead.");
1131 const size_type n = (size_type)bucket_index(c, (uint32_t)mnBucketCount);
1133 node_type*
const pNode = DoFindNode(mpBucketArray[n], c);
1136 const_iterator(pNode, mpBucketArray + n) :
1137 const_iterator(mpBucketArray + mnBucketCount);
1140 iterator find_by_hash(
const key_type& k, hash_code_t c)
1142 const size_type n = (size_type)bucket_index(c, (uint32_t)mnBucketCount);
1144 node_type*
const pNode = DoFindNode(mpBucketArray[n], k, c);
1145 return pNode ? iterator(pNode, mpBucketArray + n) : iterator(mpBucketArray + mnBucketCount);
1148 const_iterator find_by_hash(
const key_type& k, hash_code_t c)
const
1150 const size_type n = (size_type)bucket_index(c, (uint32_t)mnBucketCount);
1152 node_type*
const pNode = DoFindNode(mpBucketArray[n], k, c);
1153 return pNode ? const_iterator(pNode, mpBucketArray + n) : const_iterator(mpBucketArray + mnBucketCount);
1165 size_type count(
const key_type& k)
const EA_NOEXCEPT;
1170 bool validate()
const;
1171 int validate_iterator(const_iterator i)
const;
1179 template <
typename BoolConstantT>
1180 iterator DoGetResultIterator(BoolConstantT,
1181 const insert_return_type& irt,
1182 ENABLE_IF_TRUETYPE(BoolConstantT) =
nullptr) const EA_NOEXCEPT
1187 template <
typename BoolConstantT>
1188 iterator DoGetResultIterator(BoolConstantT,
1189 const insert_return_type& irt,
1190 DISABLE_IF_TRUETYPE(BoolConstantT) =
nullptr) const EA_NOEXCEPT
1195 node_type* DoAllocateNodeFromKey(
const key_type& key);
1196 node_type* DoAllocateNodeFromKey(key_type&& key);
1197 void DoFreeNode(node_type* pNode);
1198 void DoFreeNodes(node_type** pBucketArray, size_type);
1200 node_type** DoAllocateBuckets(size_type n);
1201 void DoFreeBuckets(node_type** pBucketArray, size_type n);
1203 template <
typename BoolConstantT,
class... Args, ENABLE_IF_TRUETYPE(BoolConstantT) =
nullptr>
1206 template <
typename BoolConstantT,
class... Args, DISABLE_IF_TRUETYPE(BoolConstantT) =
nullptr>
1207 iterator DoInsertValue(BoolConstantT, Args&&... args);
1210 template <
typename BoolConstantT>
1214 node_type* pNodeNew,
1216 ENABLE_IF_TRUETYPE(BoolConstantT) =
nullptr);
1218 template <
typename BoolConstantT>
1221 ENABLE_IF_TRUETYPE(BoolConstantT) =
nullptr);
1223 template <
typename BoolConstantT>
1224 iterator DoInsertValueExtra(BoolConstantT,
1227 node_type* pNodeNew,
1229 DISABLE_IF_TRUETYPE(BoolConstantT) =
nullptr);
1231 template <
typename BoolConstantT>
1232 iterator DoInsertValue(BoolConstantT, value_type&& value, DISABLE_IF_TRUETYPE(BoolConstantT) =
nullptr);
1235 template <
typename BoolConstantT>
1239 node_type* pNodeNew,
1240 const value_type& value,
1241 ENABLE_IF_TRUETYPE(BoolConstantT) =
nullptr);
1243 template <
typename BoolConstantT>
1245 const value_type& value,
1246 ENABLE_IF_TRUETYPE(BoolConstantT) =
nullptr);
1248 template <
typename BoolConstantT>
1249 iterator DoInsertValueExtra(BoolConstantT,
1252 node_type* pNodeNew,
1253 const value_type& value,
1254 DISABLE_IF_TRUETYPE(BoolConstantT) =
nullptr);
1256 template <
typename BoolConstantT>
1257 iterator DoInsertValue(BoolConstantT,
const value_type& value, DISABLE_IF_TRUETYPE(BoolConstantT) =
nullptr);
1259 template <
class... Args>
1260 node_type* DoAllocateNode(Args&&... args);
1261 node_type* DoAllocateNode(value_type&& value);
1262 node_type* DoAllocateNode(
const value_type& value);
1268 iterator DoInsertKey(false_type,
const key_type& key, hash_code_t c);
1270 iterator DoInsertKey(false_type, key_type&& key, hash_code_t c);
1274 eastl::pair<iterator, bool> DoInsertKey(true_type,
const key_type& key) {
return DoInsertKey(true_type(), key, get_hash_code(key)); }
1275 iterator DoInsertKey(false_type,
const key_type& key) {
return DoInsertKey(false_type(), key, get_hash_code(key)); }
1277 iterator DoInsertKey(false_type, key_type&& key) {
return DoInsertKey(false_type(),
eastl::move(key), get_hash_code(key)); }
1279 void DoRehash(size_type nBucketCount);
1280 node_type* DoFindNode(node_type* pNode,
const key_type& k, hash_code_t c)
const;
1282 template <
typename T>
1283 ENABLE_IF_HAS_HASHCODE(T, node_type) DoFindNode(T* pNode, hash_code_t c)
const
1285 for (; pNode; pNode = pNode->mpNext)
1287 if (pNode->mnHashCode == c)
1293 template <
typename U,
typename BinaryPredicate>
1294 node_type* DoFindNodeT(node_type* pNode,
const U& u, BinaryPredicate predicate)
const;
1306 template <
typename Value,
bool bCacheHashCode>
1307 inline bool operator==(
const node_iterator_base<Value, bCacheHashCode>& a,
const node_iterator_base<Value, bCacheHashCode>& b)
1308 {
return a.mpNode == b.mpNode; }
1310 template <
typename Value,
bool bCacheHashCode>
1311 inline bool operator!=(
const node_iterator_base<Value, bCacheHashCode>& a,
const node_iterator_base<Value, bCacheHashCode>& b)
1312 {
return a.mpNode != b.mpNode; }
1321 template <
typename Value,
bool bCacheHashCode>
1322 inline bool operator==(
const hashtable_iterator_base<Value, bCacheHashCode>& a,
const hashtable_iterator_base<Value, bCacheHashCode>& b)
1323 {
return a.mpNode == b.mpNode; }
1325 template <
typename Value,
bool bCacheHashCode>
1326 inline bool operator!=(
const hashtable_iterator_base<Value, bCacheHashCode>& a,
const hashtable_iterator_base<Value, bCacheHashCode>& b)
1327 {
return a.mpNode != b.mpNode; }
1336 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1337 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1338 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>
1339 ::hashtable(size_type nBucketCount,
const H1& h1,
const H2& h2,
const H& h,
1340 const Eq& eq,
const EK& ek,
const allocator_type& allocator)
1341 : rehash_base<RP, hashtable>(),
1342 hash_code_base<K, V, EK, Eq, H1, H2, H, bC>(ek, eq, h1, h2, h),
1346 mAllocator(allocator)
1348 if(nBucketCount < 2)
1349 reset_lose_memory();
1352 EASTL_ASSERT(nBucketCount < 10000000);
1353 mnBucketCount = (size_type)mRehashPolicy.GetNextBucketCount((uint32_t)nBucketCount);
1354 mpBucketArray = DoAllocateBuckets(mnBucketCount);
1360 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1361 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1362 template <
typename FowardIterator>
1363 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::hashtable(FowardIterator first, FowardIterator last, size_type nBucketCount,
1364 const H1& h1,
const H2& h2,
const H& h,
1365 const Eq& eq,
const EK& ek,
const allocator_type& allocator)
1366 : rehash_base<rehash_policy_type, hashtable>(),
1367 hash_code_base<key_type, value_type, extract_key_type, key_equal, h1_type, h2_type, h_type, kCacheHashCode>(ek, eq, h1, h2, h),
1371 mAllocator(allocator)
1373 if(nBucketCount < 2)
1375 const size_type nElementCount = (size_type)eastl::ht_distance(first, last);
1376 mnBucketCount = (size_type)mRehashPolicy.GetBucketCount((uint32_t)nElementCount);
1380 EASTL_ASSERT(nBucketCount < 10000000);
1381 mnBucketCount = nBucketCount;
1384 mpBucketArray = DoAllocateBuckets(mnBucketCount);
1386 #if EASTL_EXCEPTIONS_ENABLED
1390 for(; first != last; ++first)
1392 #if EASTL_EXCEPTIONS_ENABLED
1397 DoFreeBuckets(mpBucketArray, mnBucketCount);
1405 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1406 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1407 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::hashtable(
const this_type& x)
1408 : rehash_base<RP, hashtable>(x),
1409 hash_code_base<K, V, EK, Eq, H1, H2, H, bC>(x),
1410 mnBucketCount(x.mnBucketCount),
1411 mnElementCount(x.mnElementCount),
1412 mRehashPolicy(x.mRehashPolicy),
1413 mAllocator(x.mAllocator)
1417 mpBucketArray = DoAllocateBuckets(mnBucketCount);
1419 #if EASTL_EXCEPTIONS_ENABLED
1423 for(size_type i = 0; i < x.mnBucketCount; ++i)
1425 node_type* pNodeSource = x.mpBucketArray[i];
1426 node_type** ppNodeDest = mpBucketArray + i;
1430 *ppNodeDest = DoAllocateNode(pNodeSource->mValue);
1431 copy_code(*ppNodeDest, pNodeSource);
1432 ppNodeDest = &(*ppNodeDest)->mpNext;
1433 pNodeSource = pNodeSource->mpNext;
1436 #if EASTL_EXCEPTIONS_ENABLED
1441 DoFreeBuckets(mpBucketArray, mnBucketCount);
1450 reset_lose_memory();
1455 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1456 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1457 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::hashtable(this_type&& x)
1458 : rehash_base<RP, hashtable>(x),
1459 hash_code_base<K, V, EK, Eq, H1, H2, H, bC>(x),
1462 mRehashPolicy(x.mRehashPolicy),
1463 mAllocator(x.mAllocator)
1465 reset_lose_memory();
1470 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1471 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1472 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::hashtable(this_type&& x,
const allocator_type& allocator)
1473 : rehash_base<RP, hashtable>(x),
1474 hash_code_base<K, V, EK, Eq, H1, H2, H, bC>(x),
1477 mRehashPolicy(x.mRehashPolicy),
1478 mAllocator(allocator)
1480 reset_lose_memory();
1485 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1486 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1487 inline const typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::allocator_type&
1488 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::get_allocator() const EA_NOEXCEPT
1495 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1496 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1497 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::allocator_type&
1498 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::get_allocator() EA_NOEXCEPT
1505 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1506 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1507 inline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::set_allocator(
const allocator_type& allocator)
1509 mAllocator = allocator;
1514 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1515 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1516 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::this_type&
1517 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::operator=(
const this_type& x)
1523 #if EASTL_ALLOCATOR_COPY_ENABLED
1524 mAllocator = x.mAllocator;
1527 insert(x.begin(), x.end());
1533 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1534 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1535 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::this_type&
1536 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::operator=(this_type&& x)
1547 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1548 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1549 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::this_type&
1550 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::operator=(
std::initializer_list<value_type> ilist)
1555 insert(ilist.begin(), ilist.end());
1561 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1562 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1563 inline hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::~hashtable()
1566 DoFreeBuckets(mpBucketArray, mnBucketCount);
1570 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1571 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1572 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*
1573 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNodeFromKey(
const key_type& key)
1575 node_type*
const pNode = (node_type*)
allocate_memory(mAllocator,
sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);
1576 EASTL_ASSERT_MSG(pNode !=
nullptr,
"the behaviour of eastl::allocators that return nullptr is not defined.");
1578 #if EASTL_EXCEPTIONS_ENABLED
1582 ::new(
eastl::addressof(pNode->mValue)) value_type(pair_first_construct, key);
1583 pNode->mpNext = NULL;
1585 #if EASTL_EXCEPTIONS_ENABLED
1589 EASTLFree(mAllocator, pNode,
sizeof(node_type));
1596 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1597 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1598 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*
1599 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNodeFromKey(key_type&& key)
1601 node_type*
const pNode = (node_type*)
allocate_memory(mAllocator,
sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);
1602 EASTL_ASSERT_MSG(pNode !=
nullptr,
"the behaviour of eastl::allocators that return nullptr is not defined.");
1604 #if EASTL_EXCEPTIONS_ENABLED
1609 pNode->mpNext = NULL;
1611 #if EASTL_EXCEPTIONS_ENABLED
1615 EASTLFree(mAllocator, pNode,
sizeof(node_type));
1622 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1623 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1624 inline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFreeNode(node_type* pNode)
1626 pNode->~node_type();
1627 EASTLFree(mAllocator, pNode,
sizeof(node_type));
1632 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1633 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1634 void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFreeNodes(node_type** pNodeArray, size_type n)
1636 for(size_type i = 0; i < n; ++i)
1638 node_type* pNode = pNodeArray[i];
1641 node_type*
const pTempNode = pNode;
1642 pNode = pNode->mpNext;
1643 DoFreeNode(pTempNode);
1645 pNodeArray[i] = NULL;
1651 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1652 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1653 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type**
1654 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateBuckets(size_type n)
1658 EASTL_ASSERT(n > 1);
1659 EASTL_CT_ASSERT(kHashtableAllocFlagBuckets == 0x00400000);
1660 node_type**
const pBucketArray = (node_type**)EASTLAllocAlignedFlags(mAllocator, (n + 1) *
sizeof(node_type*), EASTL_ALIGN_OF(node_type*), 0, kHashtableAllocFlagBuckets);
1662 memset(pBucketArray, 0, n *
sizeof(node_type*));
1663 pBucketArray[n] =
reinterpret_cast<node_type*
>((uintptr_t)~0);
1664 return pBucketArray;
1669 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1670 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1671 inline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFreeBuckets(node_type** pBucketArray, size_type n)
1677 EASTLFree(mAllocator, pBucketArray, (n + 1) *
sizeof(node_type*));
1681 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1682 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1683 void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::swap(this_type& x)
1685 hash_code_base<K, V, EK, Eq, H1, H2, H, bC>::base_swap(x);
1686 eastl::swap(mRehashPolicy, x.mRehashPolicy);
1687 EASTL_MACRO_SWAP(node_type**, mpBucketArray, x.mpBucketArray);
1688 eastl::swap(mnBucketCount, x.mnBucketCount);
1689 eastl::swap(mnElementCount, x.mnElementCount);
1691 if (mAllocator != x.mAllocator)
1693 eastl::swap(mAllocator, x.mAllocator);
1698 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1699 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1700 inline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::rehash_policy(
const rehash_policy_type& rehashPolicy)
1702 mRehashPolicy = rehashPolicy;
1704 const size_type nBuckets = rehashPolicy.GetBucketCount((uint32_t)mnElementCount);
1706 if(nBuckets > mnBucketCount)
1712 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1713 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1714 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
1715 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find(
const key_type& k)
1717 const hash_code_t c = get_hash_code(k);
1718 const size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
1720 node_type*
const pNode = DoFindNode(mpBucketArray[n], k, c);
1721 return pNode ?
iterator(pNode, mpBucketArray + n) :
iterator(mpBucketArray + mnBucketCount);
1726 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1727 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1728 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator
1729 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find(
const key_type& k)
const
1731 const hash_code_t c = get_hash_code(k);
1732 const size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
1734 node_type*
const pNode = DoFindNode(mpBucketArray[n], k, c);
1735 return pNode ? const_iterator(pNode, mpBucketArray + n) : const_iterator(mpBucketArray + mnBucketCount);
1740 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1741 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1742 template <
typename U,
typename UHash,
typename BinaryPredicate>
1743 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
1744 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_as(
const U& other, UHash uhash, BinaryPredicate predicate)
1746 const hash_code_t c = (hash_code_t)uhash(other);
1747 const size_type n = (size_type)(c % mnBucketCount);
1749 node_type*
const pNode = DoFindNodeT(mpBucketArray[n], other, predicate);
1750 return pNode ?
iterator(pNode, mpBucketArray + n) :
iterator(mpBucketArray + mnBucketCount);
1755 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1756 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1757 template <
typename U,
typename UHash,
typename BinaryPredicate>
1758 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator
1759 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_as(
const U& other, UHash uhash, BinaryPredicate predicate)
const
1761 const hash_code_t c = (hash_code_t)uhash(other);
1762 const size_type n = (size_type)(c % mnBucketCount);
1764 node_type*
const pNode = DoFindNodeT(mpBucketArray[n], other, predicate);
1765 return pNode ? const_iterator(pNode, mpBucketArray + n) : const_iterator(mpBucketArray + mnBucketCount);
1783 template <
typename H,
typename U>
1787 template <
typename H,
typename U>
1788 inline typename H::const_iterator
hashtable_find(
const H& hashTable, U u)
1793 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1794 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1795 template <
typename U>
1796 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
1797 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_as(
const U& other)
1804 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1805 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1806 template <
typename U>
1807 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator
1808 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_as(
const U& other)
const
1816 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1817 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1818 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator,
1819 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator>
1820 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_range_by_hash(hash_code_t c)
const
1822 const size_type start = (size_type)bucket_index(c, (uint32_t)mnBucketCount);
1823 node_type*
const pNodeStart = mpBucketArray[start];
1828 const_iterator(pNodeStart, mpBucketArray + start));
1829 pair.second.increment_bucket();
1834 const_iterator(mpBucketArray + mnBucketCount));
1839 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1840 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1841 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
1842 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator>
1843 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::find_range_by_hash(hash_code_t c)
1845 const size_type start = (size_type)bucket_index(c, (uint32_t)mnBucketCount);
1846 node_type*
const pNodeStart = mpBucketArray[start];
1851 iterator(pNodeStart, mpBucketArray + start));
1852 pair.second.increment_bucket();
1858 iterator(mpBucketArray + mnBucketCount));
1863 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1864 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1865 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::size_type
1866 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::count(
const key_type& k)
const EA_NOEXCEPT
1868 const hash_code_t c = get_hash_code(k);
1869 const size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
1870 size_type result = 0;
1874 for(node_type* pNode = mpBucketArray[n]; pNode; pNode = pNode->mpNext)
1876 if(compare(k, c, pNode))
1884 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1885 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1886 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
1887 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator>
1888 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::equal_range(
const key_type& k)
1890 const hash_code_t c = get_hash_code(k);
1891 const size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
1892 node_type** head = mpBucketArray + n;
1893 node_type* pNode = DoFindNode(*head, k, c);
1897 node_type* p1 = pNode->mpNext;
1899 for(; p1; p1 = p1->mpNext)
1901 if(!compare(k, c, p1))
1905 iterator first(pNode, head);
1906 iterator last(p1, head);
1909 last.increment_bucket();
1915 iterator(mpBucketArray + mnBucketCount));
1921 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1922 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1923 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator,
1924 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::const_iterator>
1925 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::equal_range(
const key_type& k)
const
1927 const hash_code_t c = get_hash_code(k);
1928 const size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
1929 node_type** head = mpBucketArray + n;
1930 node_type* pNode = DoFindNode(*head, k, c);
1934 node_type* p1 = pNode->mpNext;
1936 for(; p1; p1 = p1->mpNext)
1938 if(!compare(k, c, p1))
1942 const_iterator first(pNode, head);
1943 const_iterator last(p1, head);
1946 last.increment_bucket();
1952 const_iterator(mpBucketArray + mnBucketCount));
1957 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1958 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1959 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*
1960 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFindNode(node_type* pNode,
const key_type& k, hash_code_t c)
const
1962 for(; pNode; pNode = pNode->mpNext)
1964 if(compare(k, c, pNode))
1972 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1973 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1974 template <
typename U,
typename BinaryPredicate>
1975 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*
1976 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoFindNodeT(node_type* pNode,
const U& other, BinaryPredicate predicate)
const
1978 for(; pNode; pNode = pNode->mpNext)
1980 if(predicate(mExtractKey(pNode->mValue), other))
1988 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
1989 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
1990 template <
typename BoolConstantT,
class... Args, ENABLE_IF_TRUETYPE(BoolConstantT)>
1991 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
bool>
1992 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, Args&&... args)
2005 node_type*
const pNodeNew = DoAllocateNode(eastl::forward<Args>(args)...);
2006 const key_type& k = mExtractKey(pNodeNew->mValue);
2007 const hash_code_t c = get_hash_code(k);
2008 size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
2009 node_type*
const pNode = DoFindNode(mpBucketArray[n], k, c);
2013 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2015 set_code(pNodeNew, c);
2017 #if EASTL_EXCEPTIONS_ENABLED
2023 n = (size_type)bucket_index(k, c, (uint32_t)bRehash.second);
2024 DoRehash(bRehash.second);
2028 pNodeNew->mpNext = mpBucketArray[n];
2029 mpBucketArray[n] = pNodeNew;
2033 #if EASTL_EXCEPTIONS_ENABLED
2037 DoFreeNode(pNodeNew);
2051 DoFreeNode(pNodeNew);
2058 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2059 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2060 template <
typename BoolConstantT,
class... Args, DISABLE_IF_TRUETYPE(BoolConstantT)>
2061 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2062 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, Args&&... args)
2064 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2067 DoRehash(bRehash.second);
2069 node_type* pNodeNew = DoAllocateNode(eastl::forward<Args>(args)...);
2070 const key_type& k = mExtractKey(pNodeNew->mValue);
2071 const hash_code_t c = get_hash_code(k);
2072 const size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
2074 set_code(pNodeNew, c);
2082 node_type*
const pNodePrev = DoFindNode(mpBucketArray[n], k, c);
2084 if(pNodePrev == NULL)
2087 pNodeNew->mpNext = mpBucketArray[n];
2088 mpBucketArray[n] = pNodeNew;
2092 pNodeNew->mpNext = pNodePrev->mpNext;
2093 pNodePrev->mpNext = pNodeNew;
2098 return iterator(pNodeNew, mpBucketArray + n);
2102 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2103 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2104 template <
class... Args>
2105 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*
2106 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNode(Args&&... args)
2108 node_type*
const pNode = (node_type*)
allocate_memory(mAllocator,
sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);
2109 EASTL_ASSERT_MSG(pNode !=
nullptr,
"the behaviour of eastl::allocators that return nullptr is not defined.");
2111 #if EASTL_EXCEPTIONS_ENABLED
2116 pNode->mpNext = NULL;
2118 #if EASTL_EXCEPTIONS_ENABLED
2122 EASTLFree(mAllocator, pNode,
sizeof(node_type));
2137 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2138 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2139 template <
typename BoolConstantT>
2140 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
bool>
2141 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValueExtra(BoolConstantT,
const key_type& k,
2142 hash_code_t c, node_type* pNodeNew, value_type&& value, ENABLE_IF_TRUETYPE(BoolConstantT))
2146 size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
2147 node_type*
const pNode = DoFindNode(mpBucketArray[n], k, c);
2151 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2155 #if EASTL_EXCEPTIONS_ENABLED
2162 #if EASTL_EXCEPTIONS_ENABLED
2163 nodeAllocated =
false;
2169 #if EASTL_EXCEPTIONS_ENABLED
2170 nodeAllocated =
true;
2174 set_code(pNodeNew, c);
2176 #if EASTL_EXCEPTIONS_ENABLED
2182 n = (size_type)bucket_index(k, c, (uint32_t)bRehash.second);
2183 DoRehash(bRehash.second);
2187 pNodeNew->mpNext = mpBucketArray[n];
2188 mpBucketArray[n] = pNodeNew;
2192 #if EASTL_EXCEPTIONS_ENABLED
2197 DoFreeNode(pNodeNew);
2208 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2209 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2210 template <
typename BoolConstantT>
2211 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
bool>
2212 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, value_type&& value, ENABLE_IF_TRUETYPE(BoolConstantT))
2214 const key_type& k = mExtractKey(value);
2215 const hash_code_t c = get_hash_code(k);
2217 return DoInsertValueExtra(true_type(), k, c, NULL,
eastl::move(value));
2221 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2222 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2223 template <
typename BoolConstantT>
2224 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2225 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValueExtra(BoolConstantT,
const key_type& k, hash_code_t c, node_type* pNodeNew, value_type&& value,
2226 DISABLE_IF_TRUETYPE(BoolConstantT))
2228 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2231 DoRehash(bRehash.second);
2233 const size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
2238 pNodeNew = DoAllocateNode(
eastl::
move(value));
2240 set_code(pNodeNew, c);
2248 node_type* const pNodePrev = DoFindNode(mpBucketArray[n], k, c);
2250 if(pNodePrev == NULL)
2253 pNodeNew->mpNext = mpBucketArray[n];
2254 mpBucketArray[n] = pNodeNew;
2258 pNodeNew->mpNext = pNodePrev->mpNext;
2259 pNodePrev->mpNext = pNodeNew;
2264 return iterator(pNodeNew, mpBucketArray + n);
2268 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2269 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2270 template<
typename BoolConstantT>
2271 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2272 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT, value_type&& value, DISABLE_IF_TRUETYPE(BoolConstantT))
2274 const key_type& k = mExtractKey(value);
2275 const hash_code_t c = get_hash_code(k);
2277 return DoInsertValueExtra(false_type(), k, c, NULL,
eastl::move(value));
2281 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2282 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2283 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*
2284 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNode(value_type&& value)
2286 node_type*
const pNode = (node_type*)
allocate_memory(mAllocator,
sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);
2287 EASTL_ASSERT_MSG(pNode !=
nullptr,
"the behaviour of eastl::allocators that return nullptr is not defined.");
2289 #if EASTL_EXCEPTIONS_ENABLED
2294 pNode->mpNext = NULL;
2296 #if EASTL_EXCEPTIONS_ENABLED
2300 EASTLFree(mAllocator, pNode,
sizeof(node_type));
2307 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2308 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2309 template<
typename BoolConstantT>
2310 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
bool>
2311 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValueExtra(BoolConstantT,
const key_type& k, hash_code_t c, node_type* pNodeNew,
const value_type& value,
2312 ENABLE_IF_TRUETYPE(BoolConstantT))
2316 size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
2317 node_type*
const pNode = DoFindNode(mpBucketArray[n], k, c);
2321 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2325 #if EASTL_EXCEPTIONS_ENABLED
2332 #if EASTL_EXCEPTIONS_ENABLED
2333 nodeAllocated =
false;
2338 pNodeNew = DoAllocateNode(value);
2339 #if EASTL_EXCEPTIONS_ENABLED
2340 nodeAllocated =
true;
2344 set_code(pNodeNew, c);
2346 #if EASTL_EXCEPTIONS_ENABLED
2352 n = (size_type)bucket_index(k, c, (uint32_t)bRehash.second);
2353 DoRehash(bRehash.second);
2357 pNodeNew->mpNext = mpBucketArray[n];
2358 mpBucketArray[n] = pNodeNew;
2362 #if EASTL_EXCEPTIONS_ENABLED
2367 DoFreeNode(pNodeNew);
2378 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2379 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2380 template<
typename BoolConstantT>
2381 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
bool>
2382 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT,
const value_type& value, ENABLE_IF_TRUETYPE(BoolConstantT))
2384 const key_type& k = mExtractKey(value);
2385 const hash_code_t c = get_hash_code(k);
2387 return DoInsertValueExtra(true_type(), k, c, NULL, value);
2391 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2392 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2393 template <
typename BoolConstantT>
2394 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2395 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValueExtra(BoolConstantT,
const key_type& k, hash_code_t c, node_type* pNodeNew,
const value_type& value,
2396 DISABLE_IF_TRUETYPE(BoolConstantT))
2398 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2401 DoRehash(bRehash.second);
2403 const size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
2408 pNodeNew = DoAllocateNode(value);
2410 set_code(pNodeNew, c);
2418 node_type* const pNodePrev = DoFindNode(mpBucketArray[n], k, c);
2420 if(pNodePrev == NULL)
2423 pNodeNew->mpNext = mpBucketArray[n];
2424 mpBucketArray[n] = pNodeNew;
2428 pNodeNew->mpNext = pNodePrev->mpNext;
2429 pNodePrev->mpNext = pNodeNew;
2434 return iterator(pNodeNew, mpBucketArray + n);
2438 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2439 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2440 template<
typename BoolConstantT>
2441 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2442 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertValue(BoolConstantT,
const value_type& value, DISABLE_IF_TRUETYPE(BoolConstantT))
2444 const key_type& k = mExtractKey(value);
2445 const hash_code_t c = get_hash_code(k);
2447 return DoInsertValueExtra(false_type(), k, c, NULL, value);
2451 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2452 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2453 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*
2454 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoAllocateNode(
const value_type& value)
2456 node_type*
const pNode = (node_type*)
allocate_memory(mAllocator,
sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);
2457 EASTL_ASSERT_MSG(pNode !=
nullptr,
"the behaviour of eastl::allocators that return nullptr is not defined.");
2459 #if EASTL_EXCEPTIONS_ENABLED
2464 pNode->mpNext = NULL;
2466 #if EASTL_EXCEPTIONS_ENABLED
2470 EASTLFree(mAllocator, pNode,
sizeof(node_type));
2477 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2478 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2479 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::node_type*
2480 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::allocate_uninitialized_node()
2483 node_type*
const pNode = (node_type*)
allocate_memory(mAllocator,
sizeof(node_type), EASTL_ALIGN_OF(node_type), 0);
2484 EASTL_ASSERT_MSG(pNode !=
nullptr,
"the behaviour of eastl::allocators that return nullptr is not defined.");
2486 pNode->mpNext = NULL;
2491 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2492 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2493 void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::free_uninitialized_node(node_type* pNode)
2496 EASTLFree(mAllocator, pNode,
sizeof(node_type));
2500 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2501 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2502 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
bool>
2503 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertKey(true_type,
const key_type& key,
const hash_code_t c)
2505 size_type n = (size_type)bucket_index(key, c, (uint32_t)mnBucketCount);
2506 node_type*
const pNode = DoFindNode(mpBucketArray[n], key, c);
2510 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2514 node_type*
const pNodeNew = DoAllocateNodeFromKey(key);
2515 set_code(pNodeNew, c);
2517 #if EASTL_EXCEPTIONS_ENABLED
2523 n = (size_type)bucket_index(key, c, (uint32_t)bRehash.second);
2524 DoRehash(bRehash.second);
2528 pNodeNew->mpNext = mpBucketArray[n];
2529 mpBucketArray[n] = pNodeNew;
2533 #if EASTL_EXCEPTIONS_ENABLED
2537 DoFreeNode(pNodeNew);
2548 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2549 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2550 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2551 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertKey(false_type,
const key_type& key,
const hash_code_t c)
2553 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2556 DoRehash(bRehash.second);
2558 const size_type n = (size_type)bucket_index(key, c, (uint32_t)mnBucketCount);
2560 node_type*
const pNodeNew = DoAllocateNodeFromKey(key);
2561 set_code(pNodeNew, c);
2569 node_type*
const pNodePrev = DoFindNode(mpBucketArray[n], key, c);
2571 if(pNodePrev == NULL)
2574 pNodeNew->mpNext = mpBucketArray[n];
2575 mpBucketArray[n] = pNodeNew;
2579 pNodeNew->mpNext = pNodePrev->mpNext;
2580 pNodePrev->mpNext = pNodeNew;
2585 return iterator(pNodeNew, mpBucketArray + n);
2589 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2590 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2591 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
bool>
2592 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertKey(true_type, key_type&& key,
const hash_code_t c)
2594 size_type n = (size_type)bucket_index(key, c, (uint32_t)mnBucketCount);
2595 node_type*
const pNode = DoFindNode(mpBucketArray[n], key, c);
2599 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2603 node_type*
const pNodeNew = DoAllocateNodeFromKey(
eastl::move(key));
2604 set_code(pNodeNew, c);
2606 #if EASTL_EXCEPTIONS_ENABLED
2612 n = (size_type)bucket_index(key, c, (uint32_t)bRehash.second);
2613 DoRehash(bRehash.second);
2617 pNodeNew->mpNext = mpBucketArray[n];
2618 mpBucketArray[n] = pNodeNew;
2622 #if EASTL_EXCEPTIONS_ENABLED
2626 DoFreeNode(pNodeNew);
2636 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2637 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2638 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2639 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoInsertKey(false_type, key_type&& key,
const hash_code_t c)
2641 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, (uint32_t)1);
2644 DoRehash(bRehash.second);
2646 const size_type n = (size_type)bucket_index(key, c, (uint32_t)mnBucketCount);
2648 node_type*
const pNodeNew = DoAllocateNodeFromKey(
eastl::move(key));
2649 set_code(pNodeNew, c);
2657 node_type*
const pNodePrev = DoFindNode(mpBucketArray[n], key, c);
2659 if(pNodePrev == NULL)
2662 pNodeNew->mpNext = mpBucketArray[n];
2663 mpBucketArray[n] = pNodeNew;
2667 pNodeNew->mpNext = pNodePrev->mpNext;
2668 pNodePrev->mpNext = pNodeNew;
2673 return iterator(pNodeNew, mpBucketArray + n);
2677 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2678 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2679 template <
class... Args>
2680 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type
2681 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::emplace(Args&&... args)
2683 return DoInsertValue(has_unique_keys_type(), eastl::forward<Args>(args)...);
2686 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2687 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2688 template <
class... Args>
2689 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2690 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::emplace_hint(const_iterator, Args&&... args)
2693 insert_return_type result = DoInsertValue(has_unique_keys_type(), eastl::forward<Args>(args)...);
2694 return DoGetResultIterator(has_unique_keys_type(), result);
2697 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2698 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2699 template <
class... Args>
2701 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type
2702 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::try_emplace(
const key_type& key, Args&&... args)
2704 return DoInsertValue(has_unique_keys_type(),
piecewise_construct, eastl::forward_as_tuple(key),
2705 eastl::forward_as_tuple(eastl::forward<Args>(args)...));
2708 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2709 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2710 template <
class... Args>
2712 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type
2713 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::try_emplace(key_type&& key, Args&&... args)
2716 eastl::forward_as_tuple(eastl::forward<Args>(args)...));
2719 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2720 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2721 template <
class... Args>
2722 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2723 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::try_emplace(const_iterator,
const key_type& key, Args&&... args)
2725 insert_return_type result = DoInsertValue(
2726 has_unique_keys_type(),
2727 value_type(
piecewise_construct, eastl::forward_as_tuple(key), eastl::forward_as_tuple(eastl::forward<Args>(args)...)));
2729 return DoGetResultIterator(has_unique_keys_type(), result);
2732 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2733 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2734 template <
class... Args>
2735 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2736 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::try_emplace(const_iterator, key_type&& key, Args&&... args)
2738 insert_return_type result =
2740 eastl::forward_as_tuple(eastl::forward<Args>(args)...)));
2742 return DoGetResultIterator(has_unique_keys_type(), result);
2745 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2746 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2747 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type
2748 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(value_type&& otherValue)
2750 return DoInsertValue(has_unique_keys_type(),
eastl::move(otherValue));
2754 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2755 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2757 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type
2758 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(hash_code_t c, node_type* pNodeNew, P&& otherValue)
2761 value_type value(eastl::forward<P>(otherValue));
2762 const key_type& k = mExtractKey(value);
2763 return DoInsertValueExtra(has_unique_keys_type(), k, c, pNodeNew,
eastl::move(value));
2767 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2768 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2769 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2770 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(const_iterator, value_type&& value)
2773 insert_return_type result = DoInsertValue(has_unique_keys_type(), value_type(
eastl::move(value)));
2774 return DoGetResultIterator(has_unique_keys_type(), result);
2778 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2779 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2780 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type
2781 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(
const value_type& value)
2783 return DoInsertValue(has_unique_keys_type(), value);
2787 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2788 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2789 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type
2790 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(hash_code_t c, node_type* pNodeNew,
const value_type& value)
2793 const key_type& k = mExtractKey(value);
2794 return DoInsertValueExtra(has_unique_keys_type(), k, c, pNodeNew, value);
2798 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2799 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2800 template <
typename P,
class>
2801 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_return_type
2802 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(P&& otherValue)
2804 return emplace(eastl::forward<P>(otherValue));
2808 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2809 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2810 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2811 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(const_iterator,
const value_type& value)
2814 insert_return_type result = DoInsertValue(has_unique_keys_type(), value);
2815 return DoGetResultIterator(has_unique_keys_type(), result);
2819 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2820 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2821 void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(
std::initializer_list<value_type> ilist)
2823 insert(ilist.begin(), ilist.end());
2827 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2828 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2829 template <
typename InputIterator>
2831 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert(InputIterator first, InputIterator last)
2833 const uint32_t nElementAdd = (uint32_t)eastl::ht_distance(first, last);
2834 const eastl::pair<bool, uint32_t> bRehash = mRehashPolicy.GetRehashRequired((uint32_t)mnBucketCount, (uint32_t)mnElementCount, nElementAdd);
2837 DoRehash(bRehash.second);
2839 for(; first != last; ++first)
2840 DoInsertValue(has_unique_keys_type(), *first);
2844 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2845 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2847 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
bool>
2848 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_or_assign(
const key_type& k, M&& obj)
2850 auto iter =
find(k);
2853 return insert(value_type(
piecewise_construct, eastl::forward_as_tuple(k), eastl::forward_as_tuple(eastl::forward<M>(obj))));
2857 iter->second = eastl::forward<M>(obj);
2858 return {iter,
false};
2862 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2863 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2865 eastl::pair<typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator,
bool>
2866 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_or_assign(key_type&& k, M&& obj)
2868 auto iter =
find(k);
2875 iter->second = eastl::forward<M>(obj);
2876 return {iter,
false};
2880 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2881 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2883 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2884 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_or_assign(const_iterator,
const key_type& k, M&& obj)
2886 return insert_or_assign(k, eastl::forward<M>(obj)).first;
2889 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2890 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2892 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2893 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::insert_or_assign(const_iterator, key_type&& k, M&& obj)
2895 return insert_or_assign(
eastl::move(k), eastl::forward<M>(obj)).first;
2899 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2900 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2901 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2902 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::erase(const_iterator i)
2904 iterator iNext(i.mpNode, i.mpBucket);
2907 node_type* pNode = i.mpNode;
2908 node_type* pNodeCurrent = *i.mpBucket;
2910 if(pNodeCurrent == pNode)
2911 *i.mpBucket = pNodeCurrent->mpNext;
2916 node_type* pNodeNext = pNodeCurrent->mpNext;
2918 while(pNodeNext != pNode)
2920 pNodeCurrent = pNodeNext;
2921 pNodeNext = pNodeCurrent->mpNext;
2924 pNodeCurrent->mpNext = pNodeNext->mpNext;
2935 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2936 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2937 inline typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::iterator
2938 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::erase(const_iterator first, const_iterator last)
2940 while(first != last)
2941 first = erase(first);
2942 return iterator(first.mpNode, first.mpBucket);
2947 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2948 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2949 typename hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::size_type
2950 hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::erase(
const key_type& k)
2956 const hash_code_t c = get_hash_code(k);
2957 const size_type n = (size_type)bucket_index(k, c, (uint32_t)mnBucketCount);
2958 const size_type nElementCountSaved = mnElementCount;
2960 node_type** pBucketArray = mpBucketArray + n;
2962 while(*pBucketArray && !compare(k, c, *pBucketArray))
2963 pBucketArray = &(*pBucketArray)->mpNext;
2965 while(*pBucketArray && compare(k, c, *pBucketArray))
2967 node_type*
const pNode = *pBucketArray;
2968 *pBucketArray = pNode->mpNext;
2973 return nElementCountSaved - mnElementCount;
2978 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2979 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2980 inline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::clear()
2982 DoFreeNodes(mpBucketArray, mnBucketCount);
2988 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
2989 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
2990 inline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::clear(
bool clearBuckets)
2992 DoFreeNodes(mpBucketArray, mnBucketCount);
2995 DoFreeBuckets(mpBucketArray, mnBucketCount);
2996 reset_lose_memory();
3003 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3004 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3005 inline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::reset_lose_memory() EA_NOEXCEPT
3017 memcpy(&mpBucketArray, &p,
sizeof(mpBucketArray));
3021 mRehashPolicy.mnNextResize = 0;
3025 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3026 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3027 inline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::reserve(size_type nElementCount)
3029 rehash(mRehashPolicy.GetBucketCount(uint32_t(nElementCount)));
3034 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3035 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3036 inline void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::rehash(size_type nBucketCount)
3040 DoRehash(nBucketCount);
3045 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3046 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3047 void hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::DoRehash(size_type nNewBucketCount)
3049 node_type**
const pBucketArray = DoAllocateBuckets(nNewBucketCount);
3051 #if EASTL_EXCEPTIONS_ENABLED
3057 for(size_type i = 0; i < mnBucketCount; ++i)
3059 while((pNode = mpBucketArray[i]) != NULL)
3061 const size_type nNewBucketIndex = (size_type)bucket_index(pNode, (uint32_t)nNewBucketCount);
3063 mpBucketArray[i] = pNode->mpNext;
3064 pNode->mpNext = pBucketArray[nNewBucketIndex];
3065 pBucketArray[nNewBucketIndex] = pNode;
3069 DoFreeBuckets(mpBucketArray, mnBucketCount);
3070 mnBucketCount = nNewBucketCount;
3071 mpBucketArray = pBucketArray;
3072 #if EASTL_EXCEPTIONS_ENABLED
3079 DoFreeNodes(pBucketArray, nNewBucketCount);
3080 DoFreeBuckets(pBucketArray, nNewBucketCount);
3081 DoFreeNodes(mpBucketArray, mnBucketCount);
3089 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3090 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3091 inline bool hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::validate()
const
3102 if(mnBucketCount == 0)
3112 if(mnBucketCount != 1)
3117 if(mnBucketCount < 2)
3122 size_type nElementCount = 0;
3124 for(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)
3127 if(nElementCount != mnElementCount)
3136 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3137 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3138 int hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>::validate_iterator(const_iterator i)
const
3142 for(const_iterator temp = begin(), tempEnd = end(); temp != tempEnd; ++temp)
3168 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3169 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3170 inline bool operator<(
const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& a,
3171 const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& b)
3180 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3181 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3182 inline bool operator>(
const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& a,
3183 const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& b)
3189 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3190 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3191 inline bool operator<=(
const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& a,
3192 const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& b)
3198 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3199 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3200 inline bool operator>=(
const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& a,
3201 const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& b)
3207 template <
typename K,
typename V,
typename A,
typename EK,
typename Eq,
3208 typename H1,
typename H2,
typename H,
typename RP,
bool bC,
bool bM,
bool bU>
3209 inline void swap(
const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& a,
3210 const hashtable<K, V, A, EK, Eq, H1, H2, H, RP, bC, bM, bU>& b)
3219 EA_RESTORE_VC_WARNING();
Definition: allocator.h:52
Definition: hashtable.h:830
const rehash_policy_type & rehash_policy() const EA_NOEXCEPT
Definition: hashtable.h:993
void rehash_policy(const rehash_policy_type &rehashPolicy)
Definition: hashtable.h:1700
iterator find_as(const U &u, UHash uhash, BinaryPredicate predicate)
Definition: hashtable.h:1744
Definition: initializer_list.h:38
EA Standard Template Library.
Definition: algorithm.h:288
InputIterator find(InputIterator first, InputIterator last, const T &value)
Definition: algorithm.h:1421
pair< ForwardIterator, ForwardIterator > equal_range(ForwardIterator first, ForwardIterator last, const T &value)
Definition: algorithm.h:2370
EA_CONSTEXPR piecewise_construct_t piecewise_construct
Definition: piecewise_construct_t.h:35
OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)
Definition: copy_help.h:170
eastl::iterator_traits< Iterator >::difference_type distance_fw_impl(Iterator, Iterator, EASTL_ITC_NS::input_iterator_tag)
Definition: hashtable.h:365
EASTL_API void * gpEmptyBucketArray[2]
Definition: hashtable.cpp:24
T * addressof(T &value) EA_NOEXCEPT
Definition: memory_base.h:29
@ isf_valid
This is called none and not called invalid because it is not strictly the opposite of invalid.
Definition: iterator.h:56
@ isf_can_dereference
The iterator is valid and points to the same element it did when created. For example,...
Definition: iterator.h:58
@ isf_current
The iterator is valid, which means it is in the range of [begin, end].
Definition: iterator.h:57
bool lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2)
Definition: algorithm.h:1996
void * allocate_memory(Allocator &a, size_t n, size_t alignment, size_t alignmentOffset)
Definition: allocator.h:354
H::iterator hashtable_find(H &hashTable, U u)
Definition: hashtable.h:1784
Definition: hashtable.h:155
Definition: hashtable.h:406
Definition: functional.h:395
Definition: hashtable.h:515
Definition: hashtable.h:127
Definition: hashtable.h:107
Definition: functional.h:1015
Definition: hashtable.h:253
Definition: hashtable.h:311
Definition: type_traits.h:263
Definition: iterator.h:86
Definition: hashtable.h:392
Definition: type_traits.h:303
Definition: hashtable.h:184
Definition: hashtable.h:207
Definition: utility.h:371
Definition: hashtable.h:415
Definition: red_black_tree.h:152
Definition: hashtable.h:474
Definition: type_traits.h:348