Skip to content

Commit 94e6e90

Browse files
author
Julian LALU
committed
Improve hashmap
1 parent ec05af7 commit 94e6e90

5 files changed

Lines changed: 923 additions & 44 deletions

File tree

interface/core/containers/hashmap.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,20 @@ namespace hud
374374
template<typename u_key_t = key_t, typename u_value_t = value_t>
375375
constexpr iterator add(hud::pair<u_key_t, u_value_t> &&pair) noexcept
376376
{
377-
return add(hud::get<0>(hud::forward<hud::pair<u_key_t, u_value_t>>(pair)), hud::get<1>(hud::forward<hud::pair<u_key_t, u_value_t>>(pair)));
377+
return super::add(hud::get<0>(hud::forward<hud::pair<u_key_t, u_value_t>>(pair)), hud::get<1>(hud::forward<hud::pair<u_key_t, u_value_t>>(pair)));
378+
}
379+
380+
/**
381+
* Insert a key in the hashset.
382+
* @param key The key associated with the `value`
383+
* @param args List of arguments pass to `value_type` constructor after the `key` itself
384+
* @return Iterator to the `value`
385+
*/
386+
387+
constexpr iterator add(key_type &&key, value_type &&value) noexcept
388+
requires(hud::is_constructible_v<storage_type, key_type, value_type>)
389+
{
390+
return super::add(hud::forward<key_type>(key), hud::forward<key_type>(value));
378391
}
379392
};
380393

interface/core/containers/hashset.h

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ namespace hud
808808
usize control_size {allocate_control_and_slot(max_slot_count_)};
809809

810810
// If constant evaluated context or when slot_type is not bitwise copy constructible
811-
// loop through all slot and construct them regardless of the trivially constructible ( Maybe only for control_ptr_ ) like like grow_capacity
811+
// loop through all slot and construct them regardless of the trivially constructible ( Maybe only for control_ptr_ ) like grow_capacity
812812
// In a non constant evaluated context
813813
// If type is trivially copy constructible, just memcpy control and slot
814814
// else do like grow_capacity
@@ -1271,19 +1271,6 @@ namespace hud
12711271
}
12721272

12731273
private:
1274-
// template<typename key_type, typename u_key_type>
1275-
// constexpr u64 compute_hash(const auto *slot) noexcept
1276-
// {
1277-
// if constexpr (hud::is_same_v<key_type, u_key_type>)
1278-
// {
1279-
// return hasher_type {}(slot->key());
1280-
// }
1281-
// else
1282-
// {
1283-
// return hasher_type {}(static_cast<key_type>(slot->key()));
1284-
// }
1285-
// }
1286-
12871274
template<typename u_storage_t, typename u_hasher_t, typename u_key_equal_t, typename u_allocator_t>
12881275
constexpr void copy_assign(const hashset_impl<u_storage_t, u_hasher_t, u_key_equal_t, u_allocator_t> &other) noexcept
12891276
{
@@ -1351,9 +1338,6 @@ namespace hud
13511338
return hasher_type {}(static_cast<key_type>(slot->key()));
13521339
}
13531340
};
1354-
1355-
// if constexpr (hud::is_same_v<key_type, typename u_storage_t::key_type>)
1356-
// {
13571341
control_type *control_full_or_sentinel = other.control_ptr_;
13581342
auto slot_full_or_sentinel = other.slot_ptr_;
13591343
while (control_full_or_sentinel != other.control_ptr_sentinel())
@@ -1442,7 +1426,7 @@ namespace hud
14421426
// Slots are aligned based on alignof(slot_type)
14431427
// In the case of a constant-evaluated context, slot_ptr_ may be uninitialized when the map is created
14441428
// To satisfy the compiler, initialize it to nullptr in this case
1445-
if (hud::is_constant_evaluated() && control_ptr_ == &INIT_GROUP[16])
1429+
if (hud::is_constant_evaluated() ? (control_ptr_ == &INIT_GROUP[16]) : false)
14461430
{
14471431
slot_ptr_ = nullptr;
14481432
}
@@ -1538,7 +1522,6 @@ namespace hud
15381522
return slot_index_that_is_free_or_deleted;
15391523
}
15401524

1541-
// Advance to next group (Maybe a control iterator taht iterate over groups can be better alternative)
15421525
slot_index += group_type::SLOT_PER_GROUP;
15431526
slot_index &= max_slot_count;
15441527
}
@@ -1559,7 +1542,6 @@ namespace hud
15591542
return {control_ptr_ + first_full_index, slot_ptr_ + first_full_index};
15601543
}
15611544

1562-
// Advance to next group (Maybe a control iterator that iterate over groups can be better alternative)
15631545
slot_index += group_type::SLOT_PER_GROUP;
15641546
}
15651547
return {control_ptr_sentinel(), nullptr};
@@ -1658,17 +1640,49 @@ namespace hud
16581640
{
16591641
control_type *ctrl_ptr {control_ptr_};
16601642
slot_type *slot_ptr {slot_ptr_};
1661-
size_t remaining_slots {count()};
1662-
while (remaining_slots != 0)
1643+
// When max slot count is less than the probing group
1644+
// We have cloned control in the group
1645+
// In this case, we start probing at the sentinel instead of 0
1646+
if (max_slot_count_ < group_type::SLOT_PER_GROUP - 1)
1647+
{
1648+
group_type group {control_ptr_sentinel()};
1649+
1650+
// In the case of constant expression
1651+
// If the hashmap is empty, slot_ptr is nullptr, we don't want to decrement the pointer in the case
1652+
// In a non constant expression slot_ptr is located after control in the same memory layout,
1653+
// we can safely decrement as soon as we don't read the value
1654+
if (hud::is_constant_evaluated())
1655+
{
1656+
// Iterate over cloned control bytes
1657+
for (u32 full_index : group.mask_of_full_slot())
1658+
{
1659+
hud::memory::destroy_object(slot_ptr + (full_index - 1));
1660+
}
1661+
}
1662+
else
1663+
{
1664+
--slot_ptr;
1665+
// Iterate over cloned control bytes
1666+
for (u32 full_index : group.mask_of_full_slot())
1667+
{
1668+
hud::memory::destroy_object(slot_ptr + full_index);
1669+
}
1670+
}
1671+
}
1672+
else
16631673
{
1664-
group_type group {ctrl_ptr};
1665-
for (u32 full_index : group.mask_of_full_slot())
1674+
size_t remaining_slots {count()};
1675+
while (remaining_slots != 0)
16661676
{
1667-
hud::memory::destroy_object(slot_ptr + full_index);
1668-
--remaining_slots;
1677+
group_type group {ctrl_ptr};
1678+
for (u32 full_index : group.mask_of_full_slot())
1679+
{
1680+
hud::memory::destroy_object(slot_ptr + full_index);
1681+
--remaining_slots;
1682+
}
1683+
ctrl_ptr += group_type::SLOT_PER_GROUP;
1684+
slot_ptr += group_type::SLOT_PER_GROUP;
16691685
}
1670-
ctrl_ptr += group_type::SLOT_PER_GROUP;
1671-
slot_ptr += group_type::SLOT_PER_GROUP;
16721686
}
16731687
}
16741688
}

interface/core/hash.h

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ namespace hud
149149

150150
/** Retrieves the 32 bits hash of a ansichar null-terminated string. */
151151
template<>
152-
struct hash_32<const ansichar *, usize>
152+
struct hash_32<ansichar *, usize>
153153
{
154154
[[nodiscard]] constexpr u32 operator()(const ansichar *value, usize length) const
155155
{
@@ -158,17 +158,17 @@ namespace hud
158158
};
159159

160160
template<>
161-
struct hash_32<const ansichar *>
161+
struct hash_32<ansichar *>
162162
{
163163
[[nodiscard]] constexpr u32 operator()(const ansichar *value, usize length) const
164164
{
165-
return hud::hash_32<const ansichar *, usize> {}(value, length);
165+
return hud::hash_32<ansichar *, usize> {}(value, length);
166166
}
167167
};
168168

169169
/** Retrieves the 32 bits hash of a wchar null-terminated string. */
170170
template<>
171-
struct hash_32<const wchar *, usize>
171+
struct hash_32<wchar *, usize>
172172
{
173173
[[nodiscard]] inline u32 operator()(const wchar *value, usize length) const
174174
{
@@ -177,17 +177,17 @@ namespace hud
177177
};
178178

179179
template<>
180-
struct hash_32<const wchar *>
180+
struct hash_32<wchar *>
181181
{
182182
[[nodiscard]] inline u32 operator()(const wchar *value, usize length) const
183183
{
184-
return hud::hash_32<const wchar *, usize> {}(value, length);
184+
return hud::hash_32<wchar *, usize> {}(value, length);
185185
}
186186
};
187187

188188
/** Retrieves the 32 bits hash of a pointer of a type type_t. */
189189
template<>
190-
struct hash_32<const void *>
190+
struct hash_32<void *>
191191
{
192192
[[nodiscard]] inline u32 operator()(const void *const pointer) const
193193
{
@@ -203,6 +203,18 @@ namespace hud
203203
}
204204
};
205205

206+
template<typename T, typename... types_t>
207+
struct hash_32<const T, types_t...>
208+
: hash_32<T, types_t...>
209+
{
210+
};
211+
212+
template<typename T, typename... types_t>
213+
struct hash_32<const T *, types_t...>
214+
: hash_32<T *, types_t...>
215+
{
216+
};
217+
206218
/** Combine two 64 bits value. */
207219
[[nodiscard]] static constexpr u64 combine_64(u64 a, u64 b) noexcept
208220
{
@@ -334,7 +346,7 @@ namespace hud
334346

335347
/** Retrieves the 64 bits hash of a ansichar null-terminated string. */
336348
template<>
337-
struct hash_64<const ansichar *, usize>
349+
struct hash_64<ansichar *, usize>
338350
{
339351
[[nodiscard]] constexpr u64 operator()(const ansichar *value, usize length) const
340352
{
@@ -343,36 +355,36 @@ namespace hud
343355
};
344356

345357
template<>
346-
struct hash_64<const ansichar *>
358+
struct hash_64<ansichar *>
347359
{
348360
[[nodiscard]] constexpr u64 operator()(const ansichar *value, usize length) const
349361
{
350-
return hud::hash_64<const ansichar *, usize> {}(value, length);
362+
return hud::hash_64<ansichar *, usize> {}(value, length);
351363
}
352364
};
353365

354366
/** Retrieves the 64 bits hash of a wchar null-terminated string. */
355367
template<>
356-
struct hash_64<const wchar *, usize>
368+
struct hash_64<wchar *, usize>
357369
{
358370
[[nodiscard]] inline u64 operator()(const wchar *value, usize length) const
359371
{
360-
return hud::hash_64<const ansichar *, usize> {}(reinterpret_cast<const ansichar *>(value), length * sizeof(wchar));
372+
return hud::hash_64<ansichar *, usize> {}(reinterpret_cast<const ansichar *>(value), length * sizeof(wchar));
361373
}
362374
};
363375

364376
template<>
365-
struct hash_64<const wchar *>
377+
struct hash_64<wchar *>
366378
{
367379
[[nodiscard]] inline u64 operator()(const wchar *value, usize length) const
368380
{
369-
return hud::hash_64<const wchar *, usize> {}(value, length);
381+
return hud::hash_64<wchar *, usize> {}(value, length);
370382
}
371383
};
372384

373385
/** Retrieves the 64 bits hash of a pointer of a type type_t. */
374386
template<>
375-
struct hash_64<const void *>
387+
struct hash_64<void *>
376388
{
377389
[[nodiscard]] inline u64 operator()(const void *const pointer) const
378390
{
@@ -388,6 +400,18 @@ namespace hud
388400
}
389401
};
390402

403+
template<typename T, typename... types_t>
404+
struct hash_64<const T, types_t...>
405+
: hash_64<T, types_t...>
406+
{
407+
};
408+
409+
template<typename T, typename... types_t>
410+
struct hash_64<const T *, types_t...>
411+
: hash_64<T *, types_t...>
412+
{
413+
};
414+
391415
/**
392416
* A 32 bit hasher class used for hashing an arbitrary stream of bytes
393417
* Instances of `hasher_32` usually represent state that is changed while hashing data.

0 commit comments

Comments
 (0)