Skip to content

Commit 1eec72f

Browse files
author
Julian LALU
committed
Improve hashmap
1 parent 299def0 commit 1eec72f

3 files changed

Lines changed: 620 additions & 195 deletions

File tree

interface/core/containers/array.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,6 @@ namespace hud
11551155
template<typename u_type_t>
11561156
constexpr void copy_assign(const u_type_t *source, const usize source_count, const usize min_slack = 0) noexcept
11571157
{
1158-
11591158
// Grow the allocation if we don't have enough room
11601159
// If we need to reallocate, we destroy all elements before reallocating the allocation
11611160
// Then we copy construct all elements of source in the allocation

interface/core/containers/hashset.h

Lines changed: 40 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ namespace hud
860860
: allocator_ {allocator}
861861
, max_slot_count_ {compute_max_count(other.max_count() + extra_max_count)}
862862
, count_ {other.count()}
863-
, free_slot_before_grow_(other.free_slot_before_grow_)
863+
, free_slot_before_grow_(max_slot_before_grow(max_slot_count_) - count_)
864864
{
865865
// Nothing to allocate, stop here
866866
if (max_slot_count_ == 0)
@@ -998,7 +998,7 @@ namespace hud
998998
: allocator_ {allocator}
999999
, max_slot_count_ {compute_max_count(other.max_count() + extra_max_count)}
10001000
, count_ {other.count()}
1001-
, free_slot_before_grow_(other.free_slot_before_grow_)
1001+
, free_slot_before_grow_(max_slot_before_grow(max_slot_count_) - count_)
10021002
{
10031003
// Nothing to allocate, stop here
10041004
if (max_slot_count_ == 0)
@@ -1071,47 +1071,34 @@ namespace hud
10711071
constexpr hashset_impl &operator=(const hashset_impl &other) noexcept
10721072
requires(hud::is_copy_constructible_v<slot_type>)
10731073
{
1074-
// If `this` allocation is not big enough, clear all, then deallocate, allocate new memory and add all element
1075-
// If `this` allocation is big enough, clear all, copy controls, add all elements
1076-
if (max_slot_count_ < other.max_slot_count_ || max_slot_count_ == 0)
1077-
{
1078-
destroy_all_slots();
1079-
free_control_and_slot(control_ptr_, slot_ptr_, max_slot_count_);
1074+
// Destroy all slots
1075+
destroy_all_slots();
1076+
1077+
// We don't keep the max count of the copied array
1078+
// The requested memory is the number of element in the copied array, not the max slot count.
1079+
const usize max_count_requested = other.count_;
10801080

1081-
// Copy controls
1081+
// If we have enough allocated memory
1082+
if (max_count_requested <= max_slot_count_)
1083+
{
1084+
// Reset the control to empty if we have allocated memory ( Do nothing if we have nothing because control_ptr_ points to static INIT_GROUP)
1085+
if (max_slot_count_ > 0)
1086+
{
1087+
hud::memory::set_memory(control_ptr_, control_size_for_max_count(max_slot_count_), empty_byte);
1088+
control_ptr_[max_slot_count_] = sentinel_byte;
1089+
}
1090+
// Copy the allocator if copy_when_container_copy_assigned is true
10821091
if constexpr (hud::allocator_traits<allocator_t>::copy_when_container_copy_assigned::value)
10831092
{
10841093
allocator_ = other.allocator_;
10851094
}
1086-
max_slot_count_ = other.max_slot_count_;
1095+
// Copy the number of element
10871096
count_ = other.count_;
1088-
free_slot_before_grow_ = other.free_slot_before_grow_;
1089-
1090-
// Nothing to allocate, stop here
1091-
if (other.max_slot_count_ == 0)
1092-
return *this;
1097+
// Compute the free slot count before growing
1098+
free_slot_before_grow_ = max_slot_before_grow(max_slot_count_) - count_;
10931099

1094-
// Allocate the buffer that will contain controls and aligned slots
1095-
// In a constant-evaluated context, bit_cast cannot be used with pointers
1096-
// To satisfy the compiler, allocate controls and slots in two separate allocations
1097-
usize control_size {allocate_control_and_slot(other.max_slot_count_)};
1098-
1099-
// If constant evaluated context or when slot_type is not bitwise copy constructible
1100-
// loop through all slot and construct them regardless of the trivially constructible ( Maybe only for control_ptr_ ) like like grow_capacity
1101-
// In a non constant evaluated context
1102-
// If type is trivially copy constructible, just memcpy control and slot
1103-
// else do like grow_capacity
1104-
if (hud::is_constant_evaluated() || !hud::is_bitwise_copy_constructible_v<slot_type>)
1100+
if (count_ > 0)
11051101
{
1106-
// Set control to empty ending with sentinel
1107-
hud::memory::set_memory(control_ptr_, control_size, empty_byte);
1108-
control_ptr_[max_slot_count_] = sentinel_byte;
1109-
1110-
// Nothing to copy, stop here
1111-
if (other.count() == 0)
1112-
return *this;
1113-
1114-
// Copy slots to newly allocated buffer
11151102
control_type *control_full_or_sentinel = other.control_ptr_;
11161103
slot_type *slot_full_or_sentinel = other.slot_ptr_;
11171104
while (control_full_or_sentinel != other.control_ptr_sentinel())
@@ -1131,48 +1118,33 @@ namespace hud
11311118
control_full_or_sentinel = full_or_sentinel;
11321119
}
11331120
}
1134-
else
1135-
{
1136-
hud::memory::copy_construct_array(control_ptr_, other.control_ptr_, control_size);
1137-
if (other.count() > 0)
1138-
{
1139-
hud::memory::copy_construct_array(slot_ptr_, other.slot_ptr_, other.max_count());
1140-
}
1141-
}
11421121
}
1143-
else
1122+
else // If we don't have enough memory
11441123
{
1145-
destroy_all_slots();
1146-
hud::memory::set_memory(control_ptr_, control_size_for_max_count(max_slot_count_), empty_byte);
1147-
control_ptr_[max_slot_count_] = sentinel_byte;
1124+
// Free the control and slot allocation
1125+
free_control_and_slot(control_ptr_, slot_ptr_, max_slot_count_);
11481126

1149-
// Copy controls
1127+
// Copy the allocator if copy_when_container_copy_assigned is true
11501128
if constexpr (hud::allocator_traits<allocator_t>::copy_when_container_copy_assigned::value)
11511129
{
11521130
allocator_ = other.allocator_;
11531131
}
1132+
// Copy the number of element
11541133
count_ = other.count_;
1134+
// Copy the max number of element
1135+
max_slot_count_ = compute_max_count(count_);
1136+
// Compute the free slot count before growing
11551137
free_slot_before_grow_ = max_slot_before_grow(max_slot_count_) - count_;
1138+
// Allocate the control and slot
1139+
usize control_size {allocate_control_and_slot(max_slot_count_)};
11561140

1157-
usize control_size {control_size_for_max_count(max_slot_count_)};
1141+
// Set control to empty ending with sentinel
1142+
hud::memory::set_memory(control_ptr_, control_size, empty_byte);
1143+
control_ptr_[max_slot_count_] = sentinel_byte;
11581144

1159-
// If constant evaluated context or when slot_type is not bitwise copy constructible
1160-
// loop through all slot and construct them regardless of the trivially constructible ( Maybe only for control_ptr_ ) like like grow_capacity
1161-
// In a non constant evaluated context
1162-
// If type is trivially copy constructible, just memcpy control and slot
1163-
// else do like grow_capacity
1164-
if (hud::is_constant_evaluated() || !hud::is_bitwise_copy_constructible_v<slot_type>)
1145+
// If we have elements to copy, copy them
1146+
if (count_ > 0)
11651147
{
1166-
1167-
// Set control to empty ending with sentinel
1168-
hud::memory::set_memory(control_ptr_, control_size, empty_byte);
1169-
control_ptr_[max_slot_count_] = sentinel_byte;
1170-
1171-
// Nothing to copy, stop here
1172-
if (other.count() == 0)
1173-
return *this;
1174-
1175-
// Copy slots to newly allocated buffer
11761148
control_type *control_full_or_sentinel = other.control_ptr_;
11771149
slot_type *slot_full_or_sentinel = other.slot_ptr_;
11781150
while (control_full_or_sentinel != other.control_ptr_sentinel())
@@ -1192,20 +1164,14 @@ namespace hud
11921164
control_full_or_sentinel = full_or_sentinel;
11931165
}
11941166
}
1195-
else
1196-
{
1197-
hud::memory::copy_construct_array(control_ptr_, other.control_ptr_, control_size);
1198-
if (other.count() > 0)
1199-
{
1200-
hud::memory::copy_construct_array(slot_ptr_, other.slot_ptr_, other.max_count());
1201-
}
1202-
}
12031167
}
12041168
return *this;
12051169
}
12061170

12071171
/** Reserve memory for at least `count` element and regenerates the hash table. */
1208-
constexpr void reserve(usize count) noexcept
1172+
constexpr void
1173+
reserve(usize count) noexcept
1174+
12091175
{
12101176
if (count > max_slot_count_)
12111177
{

0 commit comments

Comments
 (0)