Skip to content

Commit a03b09d

Browse files
committed
[libc++] Refactor key extraction for __hash_table and __tree
1 parent 3c4bad0 commit a03b09d

File tree

15 files changed

+308
-352
lines changed

15 files changed

+308
-352
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,6 @@ set(files
792792
__type_traits/aligned_storage.h
793793
__type_traits/aligned_union.h
794794
__type_traits/alignment_of.h
795-
__type_traits/can_extract_key.h
796795
__type_traits/common_reference.h
797796
__type_traits/common_type.h
798797
__type_traits/conditional.h
@@ -933,6 +932,7 @@ set(files
933932
__utility/small_buffer.h
934933
__utility/swap.h
935934
__utility/to_underlying.h
935+
__utility/try_key_extraction.h
936936
__utility/unreachable.h
937937
__variant/monostate.h
938938
__vector/comparison.h

libcxx/include/__fwd/tuple.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ struct tuple_element;
2626
template <class...>
2727
class tuple;
2828

29+
template <class>
30+
inline const bool __is_tuple_v = false;
31+
32+
template <class... _Tp>
33+
inline const bool __is_tuple_v<tuple<_Tp...>> = true;
34+
2935
template <size_t _Ip, class... _Tp>
3036
struct tuple_element<_Ip, tuple<_Tp...> > {
3137
using type _LIBCPP_NODEBUG = __type_pack_element<_Ip, _Tp...>;

libcxx/include/__hash_table

Lines changed: 65 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include <__memory/swap_allocator.h>
3030
#include <__memory/unique_ptr.h>
3131
#include <__new/launder.h>
32-
#include <__type_traits/can_extract_key.h>
3332
#include <__type_traits/copy_cvref.h>
3433
#include <__type_traits/enable_if.h>
3534
#include <__type_traits/invoke.h>
@@ -46,6 +45,7 @@
4645
#include <__utility/move.h>
4746
#include <__utility/pair.h>
4847
#include <__utility/swap.h>
48+
#include <__utility/try_key_extraction.h>
4949
#include <limits>
5050

5151
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -797,40 +797,66 @@ public:
797797
_LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd);
798798
_LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
799799

800-
template <class _Key, class... _Args>
801-
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args);
802-
803-
template <class... _Args>
804-
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_impl(_Args&&... __args);
805-
806-
template <class _Pp>
807-
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Pp&& __x) {
808-
return __emplace_unique_extract_key(std::forward<_Pp>(__x), __can_extract_key<_Pp, key_type>());
809-
}
810-
811-
template <class _First,
812-
class _Second,
813-
__enable_if_t<__can_extract_map_key<_First, key_type, value_type>::value, int> = 0>
814-
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_First&& __f, _Second&& __s) {
815-
return __emplace_unique_key_args(__f, std::forward<_First>(__f), std::forward<_Second>(__s));
816-
}
817-
818800
template <class... _Args>
819801
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Args&&... __args) {
820-
return __emplace_unique_impl(std::forward<_Args>(__args)...);
821-
}
822-
823-
template <class _Pp>
824-
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) {
825-
return __emplace_unique_impl(std::forward<_Pp>(__x));
826-
}
827-
template <class _Pp>
828-
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) {
829-
return __emplace_unique_key_args(__x, std::forward<_Pp>(__x));
830-
}
831-
template <class _Pp>
832-
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) {
833-
return __emplace_unique_key_args(__x.first, std::forward<_Pp>(__x));
802+
return std::__try_key_extraction<key_type>(
803+
[this](const key_type& __key, _Args&&... __args2) {
804+
size_t __hash = hash_function()(__key);
805+
size_type __bc = bucket_count();
806+
bool __inserted = false;
807+
__next_pointer __nd;
808+
size_t __chash;
809+
if (__bc != 0) {
810+
__chash = std::__constrain_hash(__hash, __bc);
811+
__nd = __bucket_list_[__chash];
812+
if (__nd != nullptr) {
813+
for (__nd = __nd->__next_;
814+
__nd != nullptr &&
815+
(__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
816+
__nd = __nd->__next_) {
817+
if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __key))
818+
goto __done;
819+
}
820+
}
821+
}
822+
{
823+
__node_holder __h = __construct_node_hash(__hash, std::forward<_Args>(__args2)...);
824+
if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
825+
__rehash_unique(std::max<size_type>(2 * __bc + !std::__is_hash_power2(__bc),
826+
size_type(__math::ceil(float(size() + 1) / max_load_factor()))));
827+
__bc = bucket_count();
828+
__chash = std::__constrain_hash(__hash, __bc);
829+
}
830+
// insert_after __bucket_list_[__chash], or __first_node if bucket is null
831+
__next_pointer __pn = __bucket_list_[__chash];
832+
if (__pn == nullptr) {
833+
__pn = __first_node_.__ptr();
834+
__h->__next_ = __pn->__next_;
835+
__pn->__next_ = __h.get()->__ptr();
836+
// fix up __bucket_list_
837+
__bucket_list_[__chash] = __pn;
838+
if (__h->__next_ != nullptr)
839+
__bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] = __h.get()->__ptr();
840+
} else {
841+
__h->__next_ = __pn->__next_;
842+
__pn->__next_ = static_cast<__next_pointer>(__h.get());
843+
}
844+
__nd = static_cast<__next_pointer>(__h.release());
845+
// increment size
846+
++size();
847+
__inserted = true;
848+
}
849+
__done:
850+
return pair<iterator, bool>(iterator(__nd), __inserted);
851+
},
852+
[this](_Args&&... __args2) {
853+
__node_holder __h = __construct_node(std::forward<_Args>(__args2)...);
854+
pair<iterator, bool> __r = __node_insert_unique(__h.get());
855+
if (__r.second)
856+
__h.release();
857+
return __r;
858+
},
859+
std::forward<_Args>(__args)...);
834860
}
835861

836862
template <class... _Args>
@@ -999,8 +1025,8 @@ private:
9991025
template <class... _Args>
10001026
_LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&&... __args);
10011027

1002-
template <class _First, class... _Rest>
1003-
_LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest);
1028+
template <class... _Args>
1029+
_LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _Args&&... __args);
10041030

10051031
_LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u) {
10061032
__copy_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());
@@ -1614,69 +1640,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(const_iterator __p
16141640
return __node_insert_multi(__cp);
16151641
}
16161642

1617-
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1618-
template <class _Key, class... _Args>
1619-
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1620-
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) {
1621-
size_t __hash = hash_function()(__k);
1622-
size_type __bc = bucket_count();
1623-
bool __inserted = false;
1624-
__next_pointer __nd;
1625-
size_t __chash;
1626-
if (__bc != 0) {
1627-
__chash = std::__constrain_hash(__hash, __bc);
1628-
__nd = __bucket_list_[__chash];
1629-
if (__nd != nullptr) {
1630-
for (__nd = __nd->__next_;
1631-
__nd != nullptr && (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1632-
__nd = __nd->__next_) {
1633-
if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
1634-
goto __done;
1635-
}
1636-
}
1637-
}
1638-
{
1639-
__node_holder __h = __construct_node_hash(__hash, std::forward<_Args>(__args)...);
1640-
if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1641-
__rehash_unique(std::max<size_type>(
1642-
2 * __bc + !std::__is_hash_power2(__bc), size_type(__math::ceil(float(size() + 1) / max_load_factor()))));
1643-
__bc = bucket_count();
1644-
__chash = std::__constrain_hash(__hash, __bc);
1645-
}
1646-
// insert_after __bucket_list_[__chash], or __first_node if bucket is null
1647-
__next_pointer __pn = __bucket_list_[__chash];
1648-
if (__pn == nullptr) {
1649-
__pn = __first_node_.__ptr();
1650-
__h->__next_ = __pn->__next_;
1651-
__pn->__next_ = __h.get()->__ptr();
1652-
// fix up __bucket_list_
1653-
__bucket_list_[__chash] = __pn;
1654-
if (__h->__next_ != nullptr)
1655-
__bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] = __h.get()->__ptr();
1656-
} else {
1657-
__h->__next_ = __pn->__next_;
1658-
__pn->__next_ = static_cast<__next_pointer>(__h.get());
1659-
}
1660-
__nd = static_cast<__next_pointer>(__h.release());
1661-
// increment size
1662-
++size();
1663-
__inserted = true;
1664-
}
1665-
__done:
1666-
return pair<iterator, bool>(iterator(__nd), __inserted);
1667-
}
1668-
1669-
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1670-
template <class... _Args>
1671-
pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1672-
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args) {
1673-
__node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1674-
pair<iterator, bool> __r = __node_insert_unique(__h.get());
1675-
if (__r.second)
1676-
__h.release();
1677-
return __r;
1678-
}
1679-
16801643
template <class _Tp, class _Hash, class _Equal, class _Alloc>
16811644
template <class... _Args>
16821645
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
@@ -1928,15 +1891,14 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) {
19281891
}
19291892

19301893
template <class _Tp, class _Hash, class _Equal, class _Alloc>
1931-
template <class _First, class... _Rest>
1894+
template <class... _Args>
19321895
typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1933-
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest) {
1934-
static_assert(!__is_hash_value_type<_First, _Rest...>::value, "Construct cannot be called with a hash value type");
1896+
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _Args&&... __args) {
1897+
static_assert(!__is_hash_value_type<_Args...>::value, "Construct cannot be called with a hash value type");
19351898
__node_allocator& __na = __node_alloc();
19361899
__node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
19371900
std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash);
1938-
__node_traits::construct(
1939-
__na, std::addressof(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...);
1901+
__node_traits::construct(__na, std::addressof(__h->__get_value()), std::forward<_Args>(__args)...);
19401902
__h.get_deleter().__value_constructed = true;
19411903
return __h;
19421904
}

0 commit comments

Comments
 (0)