Insert/emplace with hint.

This commit is contained in:
Daniel James
2016-08-17 12:08:15 +01:00
parent e58370b4ff
commit cae72eec2f
8 changed files with 307 additions and 56 deletions

View File

@@ -321,7 +321,10 @@ namespace boost { namespace unordered { namespace detail {
// Emplace/Insert
static inline void add_after_node(
// Add node 'n' to the group containing 'pos'.
// If 'pos' is the first node in group, add to the end of the group,
// otherwise add before 'pos'.
static inline void add_to_node_group(
node_pointer n,
node_pointer pos)
{
@@ -338,7 +341,7 @@ namespace boost { namespace unordered { namespace detail {
{
n->hash_ = key_hash;
if (pos.node_) {
this->add_after_node(n, pos.node_);
this->add_to_node_group(n, pos.node_);
if (n->next_) {
std::size_t next_bucket = this->hash_to_bucket(
static_cast<node_pointer>(n->next_)->hash_);
@@ -375,6 +378,24 @@ namespace boost { namespace unordered { namespace detail {
return iterator(n);
}
inline iterator add_using_hint(
node_pointer n,
node_pointer hint)
{
n->hash_ = hint->hash_;
this->add_to_node_group(n, hint);
if (n->next_ != hint && n->next_) {
std::size_t next_bucket = this->hash_to_bucket(
static_cast<node_pointer>(n->next_)->hash_);
if (next_bucket != this->hash_to_bucket(n->hash_)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
++this->size_;
return iterator(n);
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
iterator emplace(boost::unordered::detail::emplace_args1<
@@ -383,6 +404,13 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(false);
return iterator();
}
iterator emplace_hint(c_iterator, boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return iterator();
}
# else
iterator emplace(
boost::unordered::detail::please_ignore_this_overload const&)
@@ -390,6 +418,13 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(false);
return iterator();
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return iterator();
}
# endif
#endif
@@ -401,6 +436,14 @@ namespace boost { namespace unordered { namespace detail {
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS)
{
return iterator(emplace_hint_impl(hint,
boost::unordered::detail::func::construct_value_generic(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
iterator emplace_impl(node_pointer n)
{
node_tmp a(n, this->node_alloc());
@@ -411,6 +454,22 @@ namespace boost { namespace unordered { namespace detail {
return this->add_node(a.release(), key_hash, position);
}
iterator emplace_hint_impl(c_iterator hint, node_pointer n)
{
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
this->reserve_for_insert(this->size_ + 1);
return this->add_using_hint(a.release(), hint.node_);
}
else {
std::size_t key_hash = this->hash(k);
iterator position = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
return this->add_node(a.release(), key_hash, position);
}
}
void emplace_impl_no_rehash(node_pointer n)
{
node_tmp a(n, this->node_alloc());

View File

@@ -316,6 +316,14 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::emplace_args1<
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
return this->begin();
}
# else
emplace_return emplace(
boost::unordered::detail::please_ignore_this_overload const&)
@@ -323,6 +331,13 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(false);
return emplace_return(this->begin(), false);
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
return this->begin();
}
# endif
#endif
@@ -340,6 +355,21 @@ namespace boost { namespace unordered { namespace detail {
#endif
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint(c_iterator hint,
BOOST_UNORDERED_EMPLACE_ARGS)
{
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
return emplace_hint_impl(hint,
extractor::extract(BOOST_UNORDERED_EMPLACE_FORWARD),
BOOST_UNORDERED_EMPLACE_FORWARD);
#else
return emplace_hint_impl(hint,
extractor::extract(args.a0, args.a1),
BOOST_UNORDERED_EMPLACE_FORWARD);
#endif
}
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename A0>
emplace_return emplace(
@@ -347,8 +377,27 @@ namespace boost { namespace unordered { namespace detail {
{
return emplace_impl(extractor::extract(args.a0), args);
}
template <typename A0>
iterator emplace_hint(c_iterator hint,
boost::unordered::detail::emplace_args1<A0> const& args)
{
return emplace_hint_impl(hint, extractor::extract(args.a0), args);
}
#endif
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint_impl(c_iterator hint, key_type const& k,
BOOST_UNORDERED_EMPLACE_ARGS)
{
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
return iterator(hint.node_);
}
else {
return emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
}
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace_impl(key_type const& k,
BOOST_UNORDERED_EMPLACE_ARGS)
@@ -368,11 +417,31 @@ namespace boost { namespace unordered { namespace detail {
}
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
iterator emplace_hint_impl(c_iterator hint, no_key,
BOOST_UNORDERED_EMPLACE_ARGS)
{
node_tmp b(
boost::unordered::detail::func::construct_value_generic(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
key_type const& k = this->get_key(b.node_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
return iterator(hint.node_);
}
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
if (pos.node_) {
return pos;
}
else {
return this->resize_and_add_node(b.release(), key_hash);
}
}
template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
{
// Don't have a key, so construct the node first in order
// to be able to lookup the position.
node_tmp b(
boost::unordered::detail::func::construct_value_generic(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),

View File

@@ -240,9 +240,9 @@ namespace unordered
}
template <class... Args>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...).first;
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
}
#else
@@ -281,12 +281,12 @@ namespace unordered
}
template <typename A0>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
).first;
);
}
template <typename A0, typename A1>
@@ -302,15 +302,15 @@ namespace unordered
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator,
iterator emplace_hint(const_iterator hint,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
).first;
);
}
template <typename A0, typename A1, typename A2>
@@ -328,17 +328,17 @@ namespace unordered
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator,
iterator emplace_hint(const_iterator hint,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
).first;
);
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
@@ -360,15 +360,15 @@ namespace unordered
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator, \
const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
return table_.emplace_hint(hint, \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
)).first; \
)); \
}
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -724,9 +724,9 @@ namespace unordered
}
template <class... Args>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...);
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
}
#else
@@ -765,9 +765,9 @@ namespace unordered
}
template <typename A0>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
@@ -786,11 +786,11 @@ namespace unordered
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator,
iterator emplace_hint(const_iterator hint,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
@@ -812,12 +812,12 @@ namespace unordered
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator,
iterator emplace_hint(const_iterator hint,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
@@ -844,11 +844,11 @@ namespace unordered
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator, \
const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
return table_.emplace_hint(hint, \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \

View File

@@ -237,9 +237,9 @@ namespace unordered
}
template <class... Args>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...).first;
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
}
#else
@@ -278,12 +278,12 @@ namespace unordered
}
template <typename A0>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
).first;
);
}
template <typename A0, typename A1>
@@ -299,15 +299,15 @@ namespace unordered
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator,
iterator emplace_hint(const_iterator hint,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
).first;
);
}
template <typename A0, typename A1, typename A2>
@@ -325,17 +325,17 @@ namespace unordered
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator,
iterator emplace_hint(const_iterator hint,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
boost::forward<A2>(a2))
).first;
);
}
#define BOOST_UNORDERED_EMPLACE(z, n, _) \
@@ -357,15 +357,15 @@ namespace unordered
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator, \
const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
return table_.emplace_hint(hint, \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \
)).first; \
)); \
}
BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
@@ -707,9 +707,9 @@ namespace unordered
}
template <class... Args>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(Args)... args)
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
{
return table_.emplace(boost::forward<Args>(args)...);
return table_.emplace_hint(hint, boost::forward<Args>(args)...);
}
#else
@@ -748,9 +748,9 @@ namespace unordered
}
template <typename A0>
iterator emplace_hint(const_iterator, BOOST_FWD_REF(A0) a0)
iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0))
);
@@ -769,11 +769,11 @@ namespace unordered
}
template <typename A0, typename A1>
iterator emplace_hint(const_iterator,
iterator emplace_hint(const_iterator hint,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1))
@@ -795,12 +795,12 @@ namespace unordered
}
template <typename A0, typename A1, typename A2>
iterator emplace_hint(const_iterator,
iterator emplace_hint(const_iterator hint,
BOOST_FWD_REF(A0) a0,
BOOST_FWD_REF(A1) a1,
BOOST_FWD_REF(A2) a2)
{
return table_.emplace(
return table_.emplace_hint(hint,
boost::unordered::detail::create_emplace_args(
boost::forward<A0>(a0),
boost::forward<A1>(a1),
@@ -827,11 +827,11 @@ namespace unordered
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A) \
> \
iterator emplace_hint( \
const_iterator, \
const_iterator hint, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a) \
) \
{ \
return table_.emplace( \
return table_.emplace_hint(hint, \
boost::unordered::detail::create_emplace_args( \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, \
a) \