8#ifndef HPP_ALIB_MONOMEM_CONTAINERS_HASHTABLE
9#define HPP_ALIB_MONOMEM_CONTAINERS_HASHTABLE 1
15#include "alib/containers/detail/hashtablebase.inl"
23#if ALIB_DEBUG_CONTAINERS && ALIB_CAMP
29namespace alib {
namespace containers {
452template<
typename TAllocator,
453 typename TValueDescriptor,
454 typename THash = std::hash <typename TValueDescriptor::KeyType>,
455 typename TEqual = std::equal_to<typename TValueDescriptor::KeyType>,
457 Recycling TRecycling = Recycling::Private >
462 #if ALIB_DEBUG_CRITICAL_SECTIONS
464 #define DCS ALIB_DCS_WITH(dcs)
465 #define DCSSHRD ALIB_DCS_SHARED_WITH(dcs)
476 using Element =
typename base::Element;
477 using Node =
typename base::Node;
501 using KeyType =
typename TValueDescriptor::KeyType;
535 static constexpr bool IsRecycling() {
return recyclerType::IsRecycling(); }
541 using Iterator =
typename base::template TIterator < StoredType>;
587 other.element=
nullptr;
610 other.element=
nullptr;
663 float pBaseLoadFactor = 1.0,
664 float pMaxLoadFactor = 2.0 );
678 float pMaxLoadFactor = 2.0 );
680 template<
Recycling TEnableIf= TRecycling,
681 ATMP_T_IF(
int, TEnableIf != Recycling::Shared) = 0 >
684 float pBaseLoadFactor = 1.0,
685 float pMaxLoadFactor = 2.0 )
686 :
base( pAllocator, pBaseLoadFactor, pMaxLoadFactor )
692 template<
Recycling TEnableIf= TRecycling,
693 ATMP_T_IF(
int, TEnableIf != Recycling::Shared) = 0 >
696 float pMaxLoadFactor = 2.0 )
697 :
base( pBaseLoadFactor, pMaxLoadFactor )
716 TSharedRecycler& pSharedRecycler,
717 float pBaseLoadFactor = 1.0,
718 float pMaxLoadFactor = 2.0 )
719 :
base( pAllocator, pSharedRecycler, pBaseLoadFactor, pMaxLoadFactor )
736 float pBaseLoadFactor = 1.0,
737 float pMaxLoadFactor = 2.0 )
738 :
base( pSharedRecycler, pBaseLoadFactor, pMaxLoadFactor )
753 {
return base::base::GetAllocator(); }
787 auto& allocator = base::base::GetAllocator();
789 if constexpr (
ATMP_EQ(
typename base::recyclerType,
800 {
return base::size; }
807 {
return base::size == 0; }
820 return base::rehash(
uinteger(std::ceil( expectedSize / base::baseLoadFactor)) );
841 - base::recyclerType::Count();
842 if( requiredRecyclables > 0 )
843 recyclerType::Reserve( requiredRecyclables );
860 {DCSSHRD
return base::recyclerType::Count(); }
888 { base::baseLoadFactor= newBaseLoadFactor; }
900 {
return base::baseLoadFactor; }
924 { base::setMaxLoadFactor( newMaxLoadFactor ); }
936 {
return base::maxLoadFactor; }
948 {
return base::bucketCount; }
959 "Bucket number out of range." )
961 return static_cast<uinteger>(base::buckets[bucketNumber].count());
972 {
return THash{}(key) % base::bucketCount; }
984 {
return Insert( value, THash{}( TValueDescriptor().Key(
reinterpret_cast<StoredType&
>(value)) ) ); }
998 {
return Insert(value, hashCode ); }
1016 auto hashCode = THash{}( TValueDescriptor().Key(
reinterpret_cast<StoredType&
>(value)) );
1017 return Insert( std::move(value), hashCode );
1034 Element* element= base::allocElement(hashCode);
1037 new ( &element->value )
StoredType ( std::move(value) );
1040 base::increaseSize( 1 );
1041 auto bucketIdx= base::insertInBucket( element, hashCode );
1042 return Iterator(
this, bucketIdx, element);
1071 base::increaseSize( 1 );
1073 auto hashCode= THash{}( TValueDescriptor().Key( element->value ));
1074 element->fixHashCode( hashCode );
1075 auto bucketIdx= base::insertInBucket( element, hashCode );
1077 return Iterator(
this, bucketIdx, element );
1134 auto hashCode = THash{}( TValueDescriptor().Key(
reinterpret_cast<StoredType&
>(value)) );
1152 Element* element = base::allocElement( hashCode );
1155 base::increaseSize( 1 );
1156 auto bucketIdx= hashCode % base::bucketCount;
1157 base::buckets[bucketIdx].pushFront( element );
1160 new ( &element->value )
StoredType( std::move(value) );
1166 while( ++it !=
cend(bucketIdx) )
1169 "InsertUnique used while element with same key-portion "
1174 return Iterator(
this, bucketIdx, element);
1193 template<
typename TEnableIf= MappedType>
1219 template<
typename TEnableIf= MappedType>
1222 {
return InsertOrAssign( key, std::move(mapped), THash{}(key) ); }
1245 template<
typename TEnableIf= MappedType>
1249 std::pair<Iterator, bool> result= base::insertOrGet( key, hashCode );
1252 if( result.second ==
false )
1253 lang::Destruct( TValueDescriptor().Mapped( result.first.element->value ) );
1257 new (&TValueDescriptor().Key( result.first.element->value ))
KeyType( key );
1260 new ( &TValueDescriptor().Mapped( result.first.element->value ) )
MappedType( std::move( mapped) );
1281 template<
typename TEnableIf= MappedType>
1307 template<
typename TEnableIf= MappedType>
1312 std::pair<Iterator, bool> result= base::insertIfNotExists( key, hashCode );
1315 if( result.second ==
false )
1319 new (&TValueDescriptor().Key( result.first.element->value ))
KeyType( key );
1322 new ( &TValueDescriptor().Mapped( result.first.element->value ) )
MappedType( std::move( mapped) );
1349 template<
typename TEnableIf= MappedType>
1383 auto hashCode= THash{}( TValueDescriptor().Key(value) );
1405 std::pair<Iterator, bool> result= base::insertIfNotExists( TValueDescriptor().Key(value), hashCode );
1408 if( result.second ==
false )
1412 new ( &result.first.element->value )
StoredType( std::move(value) );
1447 return Iterator(
this, base::bucketCount,
nullptr );
1450 auto hashCode = THash{}( TValueDescriptor().Key( handle.
element->value ) );
1451 auto bucketIdx= hashCode % base::bucketCount;
1453 Element* existing= base::findElement( hashCode, TValueDescriptor().Key( element->value ), hashCode );
1454 if ( existing !=
nullptr )
1455 return Iterator(
this, bucketIdx, existing );
1458 element->fixHashCode( hashCode );
1460 bucketIdx= base::increaseSize( 1, hashCode );
1462 base::buckets[bucketIdx].pushFront( element );
1464 return Iterator(
this, bucketIdx, element);
1482 template<
typename... TArgs>
1486 Element* element= base::allocElement( 0 );
1489 new ( &element->value )
StoredType( std::forward<TArgs>(args)... );
1492 auto hashCode= THash{}( TValueDescriptor().Key( element->value ));
1493 element->fixHashCode( hashCode );
1496 base::increaseSize( 1 );
1497 auto bucketIdx= base::insertInBucket( element, hashCode );
1498 return Iterator(
this, bucketIdx, element);
1528 template<
typename... TArgs>
1532 Element* element= base::allocElement(0);
1535 new ( &element->value )
StoredType( std::forward<TArgs>(args)... );
1538 auto hashCode= THash{}( TValueDescriptor().Key( element->value ));
1539 element->fixHashCode( hashCode );
1543 auto bucketIdx= base::increaseSize( 1, hashCode );
1545 base::buckets[bucketIdx].pushFront( element );
1547 auto result=
Iterator(
this, bucketIdx, element);
1551 auto it=
ConstLocalIterator( result.bucketIdx, base::buckets[result.bucketIdx].first() );
1555 ALIB_ASSERT_ERROR( !base::areEqual(result.element, it.element ),
"MONOMEM/HASHTABLE",
1556 "EmplaceUnique used while element with same key-portion "
1591 template<
typename TEnableIf=
MappedType,
typename... TArgs>
1593 std::pair<Iterator, bool>
1596 template<
typename TEnableIf_MapMode=
MappedType,
typename... TArgs>
1601 std::pair<Iterator, bool> result= base::insertOrGet( key, THash{}(key) );
1604 if( result.second ==
false )
1605 lang::Destruct( TValueDescriptor().Mapped( result.first.element->value ) );
1609 new (&TValueDescriptor().Key( result.first.element->value ))
KeyType( key );
1612 new ( &TValueDescriptor().Mapped( result.first.element->value ))
MappedType( std::forward<TArgs>( args)... );
1617 template<
typename TEnableIf_SetMode=
MappedType,
typename... TArgs>
1621 TArgs&&... >::value )
1625 std::pair<Iterator, bool> result= base::insertOrGet( key, THash{}(key) );
1628 if( result.second ==
false )
1632 new (&result.first.element->value)
StoredType( key, std::forward<TArgs>( args)... );
1676 template<
typename TEnableIf=
MappedType,
typename... TArgs>
1678 std::pair<Iterator, bool>
1681 template<
typename TEnableIf=
MappedType,
typename... TArgs>
1683 && std::is_move_constructible<StoredType>::value )
1686 StoredType value( std::forward<TArgs>( args)... );
1689 std::pair<Iterator, bool> result= base::insertIfNotExists( TValueDescriptor().Key(value),
1690 THash{}(TValueDescriptor().Key(value)) );
1693 if( result.second ==
false )
1697 new ( &result.first.element->value )
StoredType( std::move(value) );
1731 template<
typename TEnableIf,
typename... TArgs>
1733 std::pair<Iterator, bool>
1737 template<
typename TEnableIf=
MappedType,
typename... TArgs>
1740 TArgs&&... >::value )
1744 std::pair<Iterator, bool> result= base::insertIfNotExists( key, THash{}(key) );
1747 if( result.second ==
false )
1751 new (&TValueDescriptor().Key(result.first.element->value))
KeyType( key );
1754 new (&TValueDescriptor().Mapped(result.first.element->value))
MappedType( std::forward<TArgs>( args)... );
1759 template<
typename TEnableIf=
MappedType,
typename... TArgs>
1762 TArgs&&... >::value )
1766 std::pair<Iterator, bool> result= base::insertIfNotExists( key, THash{}(key) );
1769 if( result.second ==
false )
1773 new (&result.first.element->value)
StoredType( key, std::forward<TArgs>( args)... );
1801 auto hashCode = THash{}(key);
1802 auto bucketIdx= hashCode % base::bucketCount;
1803 Element* elem = base::findElement( bucketIdx, key, hashCode );
1804 return Iterator(
this, elem ==
nullptr ? base::bucketCount : bucketIdx, elem );
1815 auto hashCode = THash{}(key);
1816 auto bucketIdx= hashCode % base::bucketCount;
1817 Element* elem = base::findElement( bucketIdx, key, hashCode );
1818 return ConstIterator(
this, elem ==
nullptr ? base::bucketCount : bucketIdx, elem );
1835 auto bucketIdx= hashCode % base::bucketCount;
1836 Element* elem = base::findElement( bucketIdx, key, hashCode );
1837 return Iterator(
this, elem ==
nullptr ? base::bucketCount : bucketIdx, elem );
1854 auto bucketIdx= hashCode % base::bucketCount;
1855 Element* elem = base::findElement( bucketIdx, key, hashCode );
1856 return ConstIterator(
this, elem ==
nullptr ? base::bucketCount : bucketIdx, elem );
1867 auto hashCode= THash{}(key);
1868 return base::findElement(hashCode % base::bucketCount, key, hashCode )
1882 {DCSSHRD
return base::findRange( key ); }
1894 {DCSSHRD
return base::findRange( key ); }
1915 {
return Extract( key, THash{}(key) ); }
1933 Node* previous= base::findElementBefore( hashCode % base::bucketCount, hashCode, key );
1934 if( previous ==
nullptr )
1937 Element* element= previous->next();
1938 previous->removeNext();
1965 && pos.table !=
nullptr ,
"MONOMEM/HASHTABLE",
1966 "Illegal iterator." )
1968 Node* previous= base::buckets[pos.bucketIdx].findLastBefore( pos.element );
1969 ALIB_ASSERT_ERROR( previous !=
nullptr,
"MONOMEM/HASHTABLE",
"Illegal iterator: Element not found." )
1984 {
return Erase( key, THash{}(key) ); }
2000 Node* beforeFirst= base::findElementBefore( hashCode % base::bucketCount, hashCode, key );
2001 if( beforeFirst ==
nullptr )
2006 while(
end && base::areEqual(
end, key, hashCode ) )
2010 auto result= base::recyclerType::RecycleList(beforeFirst->next(),
end);
2011 beforeFirst->next(
end );
2013 base::size-= result.second;
2014 return result.second;
2050 Node* before= base::findElementBefore( hashCode % base::bucketCount, hashCode, key );
2051 if( before ==
nullptr )
2055 || !base::areEqual( before->next()->next(), key, hashCode ),
2056 "MONOMEM/HASHTABLE",
"More than one element found matching the given key")
2058 Element* elem= before->removeNext();
2059 base::recyclerType::Recycle(elem);
2080 && pos.table !=
nullptr ,
"MONOMEM/HASHTABLE",
2081 "Illegal iterator." )
2083 Iterator result(
this, pos.bucketIdx, pos.element );
2088 Node* previous= base::buckets[pos.bucketIdx].findLastBefore( pos.element );
2091 "Illegal iterator: Element not found." )
2095 base::recyclerType::Recycle(toDelete);
2116 && start.table !=
nullptr ,
"MONOMEM/HASHTABLE",
2117 "Illegal iterator." )
2120 "Iterators are referring to different hash tables." )
2122 if( start.element ==
end.element )
2123 return Iterator(
this, start.bucketIdx, start.element );
2126 for(
auto bucketIdx= start.bucketIdx; bucketIdx <=
end.bucketIdx; ++bucketIdx )
2129 if( bucketIdx == base::bucketCount )
2135 if( bucketIdx == start.bucketIdx )
2138 previous= base::buckets[start.bucketIdx].findLastBefore( start.element );
2140 "Illegal iterator: Element not found." )
2144 if( base::buckets[bucketIdx].isEmpty() )
2146 previous= &base::buckets[bucketIdx];
2151 if ( bucketIdx <
end.bucketIdx )
2153 base::size-= previous->
count();
2154 base::recyclerType::RecycleList( previous->
next() );
2155 previous->
next(
nullptr );
2159 auto pair= base::recyclerType::RecycleList(previous->
next(),
end.element );
2160 previous->
next(
end.element );
2161 base::size-= pair.second;
2183 ALIB_ASSERT_ERROR( pos.element !=
nullptr,
"MONOMEM/HASHTABLE",
"Illegal iterator." )
2187 Element* element= pos.element;
2189 base::buckets[pos.bucketIdx].findAndRemove( element );
2191 base::recyclerType::Recycle( element);
2211 ALIB_ASSERT_ERROR( start.element !=
nullptr,
"MONOMEM/HASHTABLE",
"Illegal iterator." )
2213 Node* previous= base::buckets[start.bucketIdx].findLastBefore( start.element );
2214 ALIB_ASSERT_ERROR( previous !=
nullptr,
"MONOMEM/HASHTABLE",
"Illegal iterator." )
2215 if( start.element ==
end.element )
2218 previous->next(
end.element );
2219 auto pair= base::recyclerType::RecycleList( start.element,
end.element );
2221 base::size-= pair.second;
2238 return Iterator (
this, base::bucketCount,
nullptr ); }
2266 "Bucket number out of range." )
2267 return LocalIterator( bucketNumber, base::buckets[bucketNumber].first() );
2278 "Bucket number out of range." )
2290 "Bucket number out of range." )
2302 "Bucket number out of range." )
2314 "Bucket number out of range." )
2326 "Bucket number out of range." )
2339#if ALIB_DEBUG_CONTAINERS
2360template<
typename THashtable>
2362std::tuple<double,double,integer,integer>
2365 auto qtyBuckets = hashtable.BucketCount();
2366 double averageExpected =
static_cast<double>( hashtable.Size() )
2367 /
static_cast<double>( qtyBuckets ) ;
2368 uinteger minimum = std::numeric_limits<uinteger>::max();
2369 uinteger maximum = std::numeric_limits<uinteger>::min();
2372 for(
uinteger i= 0 ; i < qtyBuckets ; ++i )
2374 auto bucketSize= hashtable.BucketSize( i );
2375 sumCheck+= bucketSize;
2376 if( minimum > bucketSize ) minimum= bucketSize;
2377 if( maximum < bucketSize ) maximum= bucketSize;
2379 double diff= averageExpected - double(bucketSize);
2380 diffs+= diff > 0 ? diff : - diff;
2385 "Error: Hashtable::Size() and sum of bucket sizes differ: {} != {}",
2386 hashtable.Size(), sumCheck )
2389 "Error: Hashtable::Size() and sum of bucket sizes differ" )
2391 double deviation= diffs / double(qtyBuckets);
2393 return std::make_tuple( averageExpected, deviation, minimum, maximum );
2416template<
typename THashtable>
2422 double loadFactor= std::get<0>( values );
2423 double deviation = std::get<1>( values );
2424 integer minSize = std::get<2>( values );
2425 integer maxSize = std::get<3>( values );
2429 formatter.
Format( result,
"Size: {}\n"
2431 "Load Factor: {:.02} (Base: {:.01} Max: {:.01})\n"
2432 "Deviation: {:.02} (~{:%.1})\n"
2436 hashtable.BucketCount(),
2437 loadFactor, hashtable.BaseLoadFactor(), hashtable.MaxLoadFactor(),
2438 deviation , ( hashtable.Size() != 0
2439 ? deviation / loadFactor
2446 for(
integer i= 0; i < maxSize ; ++i)
2449 for(
uinteger i= 0; i < hashtable.BucketCount() ; ++i)
2450 ++bucketFills[hashtable.BucketSize(i)];
2452 formatter.
Format( result,
"Bucket Fills: Size #Buckets\n" );
2453 formatter.
Format( result,
" -----------------\n" );
2454 for(
integer i= 0; i < maxSize ; ++i)
2455 formatter.
Format( result,
" {} {}\n", i, bucketFills[i] );
2456 delete[] bucketFills;
2460 if( detailedBucketList )
2462 formatter.
Format(result,
"\nDetailed Bucket List:\n");
2463 auto qtyBuckets = hashtable.BucketCount();
2464 for(
uinteger i= 0 ; i < qtyBuckets ; ++i )
2466 auto bucketSize= hashtable.BucketSize( i );
2467 formatter.
Format(result,
"{:3} ({:2}): {!FillCX}\n", i, bucketSize,
2468 static_cast<int>(bucketSize) );
2502template<
typename THashtable>
2510 formatter.
Format(result,
"\nHashtable dump:\n");
2511 auto qtyBuckets = hashtable.BucketCount();
2512 for(
uinteger i= 0 ; i < qtyBuckets ; ++i )
2514 auto bucketSize= hashtable.BucketSize( i );
2515 formatter.
Format(result,
"{:3} ({:2}): ", i, bucketSize );
2518 for(
auto bucketIt= hashtable.begin(i)
2519 ; bucketIt != hashtable.end (i)
2524 formatter.
Format(result,
"{}: {}\n", entryNo, *bucketIt );
2527 if( bucketSize == 0)
2579template<
typename TAllocator,
2581 typename THash = std::hash <T>,
2582 typename TEqual = std::equal_to<T>,
2584 Recycling TRecycling = Recycling::Private >
2625template<
typename TAllocator,
2628 typename THash = std::hash <TKey>,
2629 typename TEqual = std::equal_to<TKey>,
2631 Recycling TRecycling = Recycling::Private >
2641template<
typename TAllocator,
2642 typename TValueDescriptor,
2643 typename THash = std::hash <typename TValueDescriptor::KeyType>,
2644 typename TEqual = std::equal_to<typename TValueDescriptor::KeyType>,
2646 Recycling TRecycling = Recycling::Private >
2650template<
typename TAllocator,
2652 typename THash = std::hash <T>,
2653 typename TEqual = std::equal_to<T>,
2655 Recycling TRecycling = Recycling::Private >
2659template<
typename TAllocator,
2662 typename THash = std::hash <TKey>,
2663 typename TEqual = std::equal_to<TKey>,
2665 Recycling TRecycling = Recycling::Private >
2670#if ALIB_DEBUG_CRITICAL_SECTIONS
MappedType & Mapped() const
HashTable * table
The table we belong to.
ElementHandle & operator=(ElementHandle &&other)
StoredType & Value() const
ElementHandle(HashTable *pTable, Element *pElement)
Element * element
The extracted element.
ElementHandle(ElementHandle &other)=delete
Deleted copy constructor.
ElementHandle(ElementHandle &&other)
ElementHandle()
Default constructor creating and empty handle.
ElementHandle & operator=(const ElementHandle &other)=delete
Deleted copy assignment operator.
bool EraseUnique(const KeyType &key)
Iterator InsertUnique(StoredType &&value, size_t hashCode)
ConstIterator cend() const
ElementHandle Extract(const KeyType &key, size_t hashCode)
static constexpr bool IsCachingHashes()
ConstLocalIterator end(uinteger bucketNumber) const
ConstLocalIterator cbegin(uinteger bucketNumber) const
Iterator Insert(const StoredType &value, size_t hashCode)
void MaxLoadFactor(float newMaxLoadFactor) noexcept
ConstIterator Find(const KeyType &key, size_t hashCode) const
AllocatorType & GetAllocator() noexcept
integer Erase(const KeyType &key)
InsertIfNotExistent(const KeyType &key, const MappedType &mapped)
TAllocator AllocatorType
Type definition publishing template parameter TAllocator.
typename TValueDescriptor::MappedType MappedType
HashTable(float pBaseLoadFactor=1.0, float pMaxLoadFactor=2.0)
static constexpr Recycling RecyclingTag()
typename base::template TIterator< const StoredType > ConstIterator
The constant iterator exposed by this container.
ALIB_WARNINGS_IGNORE_NOTHING_RETURNED Iterator Erase(ConstIterator start, ConstIterator end)
ElementHandle Extract(const KeyType &key)
InsertOrAssign(const KeyType &key, const MappedType &mapped)
Iterator Find(const KeyType &key, size_t hashCode)
LocalIterator end(uinteger bucketNumber)
std::pair< Iterator, bool > EmplaceIfNotExistent(const KeyType &key, TArgs &&... args)
Iterator EmplaceUnique(TArgs &&... args)
bool IsEmpty() const noexcept
typename base::template TLocalIterator< StoredType > LocalIterator
The mutable iterator for a single bucket exposed by this container.
float BaseLoadFactor() const noexcept
std::pair< Iterator, bool > InsertIfNotExistent(const StoredType &value)
uinteger BucketNumber(const KeyType &key) const noexcept
integer Size() const noexcept
typename base::template TIterator< StoredType > Iterator
The mutable iterator exposed by this container.
typename base::SharedRecyclerType SharedRecyclerType
typename base::recyclerType recyclerType
The recycler type.
ConstIterator Find(const KeyType &key) const
static constexpr bool IsRecycling()
THash HashType
Type definition publishing template parameter THash.
HashTable(AllocatorType &pAllocator, float pBaseLoadFactor=1.0, float pMaxLoadFactor=2.0)
ConstIterator end() const
void BaseLoadFactor(float newBaseLoadFactor) noexcept
std::pair< Iterator, Iterator > EqualRange(const KeyType &key)
uinteger BucketSize(uinteger bucketNumber) const noexcept
bool Contains(const KeyType &key) const
typename TValueDescriptor::KeyType KeyType
uinteger BucketCount() const noexcept
integer RecyclablesCount() const noexcept
std::pair< Iterator, bool > EmplaceOrAssign(const KeyType &key, TArgs &&... args)
ElementHandle Extract(ConstIterator pos)
ConstLocalIterator begin(uinteger bucketNumber) const
ALIB_WARNINGS_RESTORE LocalIterator Erase(ConstLocalIterator pos)
Iterator Insert(const StoredType &value)
HashTable(TSharedRecycler &pSharedRecycler, float pBaseLoadFactor=1.0, float pMaxLoadFactor=2.0)
static constexpr bool CachedHashCodes
TMP constant that denotes whether hash codes are cached or not.
ConstIterator cbegin() const
std::pair< ConstIterator, ConstIterator > EqualRange(const KeyType &key) const
Iterator InsertUnique(const StoredType &value, size_t hashCode)
HashTable(AllocatorType &pAllocator, TSharedRecycler &pSharedRecycler, float pBaseLoadFactor=1.0, float pMaxLoadFactor=2.0)
LocalIterator begin(uinteger bucketNumber)
Iterator Insert(StoredType &&value)
TEqual EqualType
Type definition publishing template parameter TEqual.
bool EraseUnique(const KeyType &key, size_t hashCode)
Iterator Insert(ElementHandle &handle)
typename base::template TLocalIterator< const StoredType > ConstLocalIterator
The constant iterator for a single bucket exposed by this container.
std::pair< Iterator, bool > InsertIfNotExistent(StoredType &&value, size_t hashCode)
Iterator InsertUnique(StoredType &&value)
std::pair< Iterator, bool > EmplaceIfNotExistent(TArgs &&... args)
Iterator Erase(ConstIterator pos)
integer Erase(const KeyType &key, size_t hashCode)
std::pair< Iterator, bool > InsertIfNotExistent(StoredType &&value)
TValueDescriptor DescriptorType
Type definition publishing template parameter TValueDescriptor.
ConstLocalIterator cend(uinteger bucketNumber) const
Iterator InsertUnique(const StoredType &value)
Iterator Find(const KeyType &key)
LocalIterator Erase(ConstLocalIterator start, ConstLocalIterator end)
void ReserveRecyclables(integer qty, lang::ValueReference reference)
ConstIterator begin() const
Iterator Emplace(TArgs &&... args)
Iterator InsertIfNotExistent(ElementHandle &handle)
void Reserve(integer qty, lang::ValueReference reference)
Iterator Insert(StoredType &&value, size_t hashCode)
typename TValueDescriptor::StoredType StoredType
float MaxLoadFactor() const noexcept
#define ALIB_ASSERT_MODULE(modulename)
#define ALIB_WARNINGS_RESTORE
#define ATMP_EQ( T, TEqual)
#define ALIB_LOCK_RECURSIVE_WITH(lock)
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
#define ALIB_WARNINGS_IGNORE_NOTHING_RETURNED
#define ALIB_ASSERT(cond)
#define ATMP_T_IF(T, Cond)
#define ALIB_DEBUG_CRITICAL_SECTIONS
AString DbgDumpHashtable(const THashtable &hashtable)
AString DbgDumpDistribution(const THashtable &hashtable, bool detailedBucketList)
std::tuple< double, double, integer, integer > DbgGetHashTableDistribution(const THashtable &hashtable)
static ALIB_FORCE_INLINE void Destruct(T &object)
ValueReference
Denotes if a value is interpreted as an absolute or relative number.
@ Relative
Referring to a relative value.
@ Absolute
Referring to an absolute value.
Caching
Denotes if a cache mechanism is enabled or disabled.
lang::uinteger uinteger
Type alias in namespace alib.
containers::HashTable< TAllocator, TValueDescriptor, THash, TEqual, THashCaching, TRecycling > HashTable
Type alias in namespace alib. See type definition alib::containers::HashSet.
constexpr CString NEW_LINE
A zero-terminated string containing the new-line character sequence.
lang::integer integer
Type alias in namespace alib.
typename HTElementSelector< TValueDescriptor, THashCaching >::Type Element
The type stored in the bucket of class HashTable.
typename RecyclingSelector< TRecycling >::template Type< TAllocator, typename HTElementSelector< TValueDescriptor, THashCaching >::Type > base
Our base type.
float baseLoadFactor
The load factor that is set when the table is rehashed automatically.
float maxLoadFactor
The maximum quotient of size and bucketCount that triggers a rehash.
TElement * removeNext() noexcept
void next(SidiNodeBase *p)
integer count(SidiNodeBase *end=nullptr) const noexcept