Skip to content

Commit

Permalink
Improve hashmap
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian LALU committed Dec 30, 2024
1 parent 36a8246 commit 305ba47
Show file tree
Hide file tree
Showing 13 changed files with 965 additions and 362 deletions.
11 changes: 10 additions & 1 deletion interface/core/containers/hashmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ namespace hud
using key_type = typename hud::pair<key_t, value_t>::first_type;
using value_type = typename hud::pair<key_t, value_t>::second_type;

explicit constexpr slot(const key_type &key) noexcept
: super(key, value_type {})
{
}

explicit constexpr slot(key_type &&key) noexcept
: super(std::move(key), value_type {})
{
}

[[nodiscard]] constexpr const key_t &key() const noexcept
{
return hud::get<0>(*this);
Expand Down Expand Up @@ -79,7 +89,6 @@ namespace hud
typename allocator_t = hashmap_default_allocator>
class hashmap
: public details::hashset::hashset_impl<details::hashmap::slot<key_t, value_t>, hasher_t, key_equal_t, allocator_t>

{

private:
Expand Down
43 changes: 34 additions & 9 deletions interface/core/containers/hashset.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "pair.h"
#include "../hash.h"
#include "../bits.h"
#include "../traits/is_comparable_with_equal.h"

namespace hud
{
Expand Down Expand Up @@ -470,14 +471,16 @@ namespace hud
return tmp;
}

friend constexpr bool operator==(const iterator &a, const iterator &b)
/** Checks if 2 iterator are equal. */
[[nodiscard]] constexpr bool operator==(const iterator &other) const noexcept
{
return a.control_ptr_ == b.control_ptr_;
return control_ptr_ == other.control_ptr_;
}

friend constexpr bool operator!=(const iterator &a, const iterator &b)
/** Checks if 2 iterator are not equals. */
[[nodiscard]] constexpr bool operator!=(const iterator &other) const noexcept
{
return !(a == b);
return control_ptr_ != other.control_ptr_;
}

private:
Expand All @@ -499,8 +502,8 @@ namespace hud
typename key_equal_t,
typename allocator_t>
class hashset_impl

{

protected:
/** Type of the slot. */
using slot_type = slot_t;
Expand Down Expand Up @@ -592,7 +595,7 @@ namespace hud
slot_type *slot_ptr = slot_ptr_ + res.first;
if (res.second)
{
hud::memory::construct_at<args_t...>(slot_ptr, key, hud::forward<args_t>(args)...);
hud::memory::construct_at<args_t...>(slot_ptr, hud::move(key), hud::forward<args_t>(args)...);
}
return slot_ptr->value();
}
Expand All @@ -609,7 +612,26 @@ namespace hud
slot_type *slot_ptr = slot_ptr_ + res.first;
if (res.second)
{
hud::memory::construct_at(slot_ptr, key, hud::move(value));
hud::memory::construct_at(slot_ptr, hud::move(key), hud::move(value));
}
return {control_ptr_ + res.first, slot_ptr};
}

/**
* Insert a key in the hashset.
* @param key The key associated with the `value`
* @param args List of arguments pass to `value_type` constructor after the `key` itself
* @return Iterator to the `value`
*/
template<typename... args_t>
requires(hud::is_constructible_v<value_type, args_t...>)
constexpr iterator add(key_type &&key, args_t &&...args) noexcept
{
hud::pair<usize, bool> res = find_or_insert_no_construct(key);
slot_type *slot_ptr = slot_ptr_ + res.first;
if (res.second)
{
hud::memory::construct_at(slot_ptr, hud::move(key), hud::forward<args_t>(args)...);
}
return {control_ptr_ + res.first, slot_ptr};
}
Expand All @@ -635,7 +657,7 @@ namespace hud

/** Find a key and return an iterator to the value. */
[[nodiscard]]
constexpr iterator find(key_type &&key) const noexcept
constexpr iterator find(key_type &&key) noexcept
{
u64 hash = hasher_type {}(key);
u64 h1 = H1(hash);
Expand Down Expand Up @@ -721,7 +743,7 @@ namespace hud
[[nodiscard]]
constexpr const_iterator end() const noexcept
{
return iterator(control_ptr_sentinel());
return const_iterator(control_ptr_sentinel());
}

private:
Expand All @@ -732,6 +754,9 @@ namespace hud
*/
[[nodiscard]] constexpr hud::pair<usize, bool> find_or_insert_no_construct(const key_type &key) noexcept
{
static_assert(hud::is_hashable_64_v<key_type>, "key_type is not hashable");
static_assert(hud::is_comparable_with_equal_v<key_type, key_type>, "key_type is not comparable with equal");

u64 hash = hasher_type {}(key);
u64 h1 = H1(hash);
hud::check(hud::bits::is_valid_power_of_two_mask(max_slot_count_) && "Not a mask");
Expand Down
34 changes: 34 additions & 0 deletions interface/core/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "templates/bit_cast.h"
#include "cstring.h"
#include "traits/decay.h"
#include "templates/declval.h"

namespace hud
{
Expand Down Expand Up @@ -429,6 +430,39 @@ namespace hud
u64 state_ {0}; // Default is 0, but can be a seed
};

// Traits used to check if a type is hashable
template<typename type_t, typename = void>
struct is_hashable_64
: hud::false_type
{
};

template<typename type_t>
struct is_hashable_64<type_t, void_t<decltype(hud::hash_64<type_t> {}(hud::declval<type_t>()))>>
: hud::true_type
{
};

/** Equivalent of is_hashable<type_t>::value. */
template<typename type_t>
inline constexpr bool is_hashable_64_v = is_hashable_64<type_t>::value;

// Traits used to check if a type is hashable
template<typename type_t, typename = void>
struct is_hashable_32
: hud::false_type
{
};

template<typename type_t>
struct is_hashable_32<type_t, void_t<decltype(hud::hash_32<type_t> {}(hud::declval<type_t>()))>>
: hud::true_type
{
};

/** Equivalent of is_hashable<type_t>::value. */
template<typename type_t>
inline constexpr bool is_hashable_32_v = is_hashable_32<type_t>::value;
} // namespace hud

#endif // HD_INC_CORE_HASH_H
2 changes: 1 addition & 1 deletion test/array/array_add.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <core/containers/array.h>
#include "../misc/allocator_watcher.h"

GTEST_TEST(array, add_by_copy_construct_non_bitwise_copy_constructible_type)
GTEST_TEST(array, add_by_copy_construct_non_bitwise_copy_constructible_type_same_type)
{

using type = hud_test::non_bitwise_copy_constructible_type;
Expand Down
1 change: 0 additions & 1 deletion test/array/array_add_no_construct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

GTEST_TEST(array, add_no_construct_do_not_call_constructor)
{

using type = hud_test::NonDefaultConstructibleType;
using array_type = hud::array<type, hud_test::allocator_watcher<alignof(type)>>;
static_assert(!hud::is_constructible_v<type>);
Expand Down
1 change: 0 additions & 1 deletion test/array/array_add_to_ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

GTEST_TEST(array, add_to_ref_by_copy_construct_non_bitwise_copy_constructible_type)
{

using type = hud_test::non_bitwise_copy_constructible_type;
using array_type = hud::array<type, hud_test::allocator_watcher<alignof(type)>>;
static_assert(!hud::is_bitwise_copy_constructible_v<type, type>);
Expand Down
2 changes: 0 additions & 2 deletions test/array/array_iteration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

GTEST_TEST(array, iterators)
{

// Non const Array
{
hud::array<i32> arr({10, 20, 30, 40});
Expand Down Expand Up @@ -46,7 +45,6 @@ GTEST_TEST(array, iterators)

GTEST_TEST(array, range_for_loop)
{

// Non const Array
{
hud::array<i32> arr({10, 20, 30, 40});
Expand Down
1 change: 0 additions & 1 deletion test/array/array_move_assign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// void assign(array &&other, const usize min_slack = 0)
GTEST_TEST(array, move_assign_array_of_bitwise_move_assignable_same_type_same_allocator_no_min_slack)
{

using type = i32;

static_assert(hud::is_bitwise_move_assignable_v<type>);
Expand Down
Loading

0 comments on commit 305ba47

Please sign in to comment.