forked from boostorg/unordered
Clean up impl of node_handle
This commit is contained in:
@ -84,163 +84,6 @@ namespace unordered{
|
||||
namespace detail{
|
||||
namespace foa{
|
||||
|
||||
template <class Iterator,class NodeType>
|
||||
struct insert_return_type
|
||||
{
|
||||
Iterator position;
|
||||
bool inserted;
|
||||
NodeType node;
|
||||
};
|
||||
|
||||
template <class TypePolicy,class Allocator>
|
||||
struct node_handle_base
|
||||
{
|
||||
protected:
|
||||
using type_policy=TypePolicy;
|
||||
using value_type=typename type_policy::value_type;
|
||||
using element_type=typename type_policy::element_type;
|
||||
|
||||
public:
|
||||
using allocator_type = Allocator;
|
||||
|
||||
private:
|
||||
value_type* p_=nullptr;
|
||||
alignas(Allocator) unsigned char a_[sizeof(Allocator)]={0};
|
||||
|
||||
protected:
|
||||
value_type& element()noexcept
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return *p_;
|
||||
}
|
||||
|
||||
value_type const& element()const noexcept
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return *p_;
|
||||
}
|
||||
|
||||
Allocator& al()noexcept
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return *reinterpret_cast<Allocator*>(a_);
|
||||
}
|
||||
|
||||
Allocator const& al()const noexcept
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return *reinterpret_cast<Allocator const*>(a_);
|
||||
}
|
||||
|
||||
void emplace(value_type* p,Allocator a)
|
||||
{
|
||||
BOOST_ASSERT(empty());
|
||||
p_=p;
|
||||
new(a_)Allocator(a);
|
||||
}
|
||||
|
||||
void emplace(element_type&& x,Allocator a)
|
||||
{
|
||||
emplace(x.p,a);
|
||||
x.p=nullptr;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
al().~Allocator();
|
||||
p_=nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr node_handle_base()noexcept=default;
|
||||
|
||||
node_handle_base(node_handle_base&& nh) noexcept
|
||||
{
|
||||
if (!nh.empty()){
|
||||
emplace(nh.p_,nh.al());
|
||||
nh.clear();
|
||||
}
|
||||
}
|
||||
|
||||
node_handle_base& operator=(node_handle_base&& nh)noexcept
|
||||
{
|
||||
bool const pocma=
|
||||
boost::allocator_propagate_on_container_move_assignment<
|
||||
Allocator>::type::value;
|
||||
|
||||
if(!empty()){
|
||||
type_policy::destroy(al(),p_);
|
||||
if (pocma&&!nh.empty()){al()=std::move(nh.al());}
|
||||
}
|
||||
|
||||
if(!nh.empty()){
|
||||
if(empty()){new(a_)Allocator(std::move(nh.al()));}
|
||||
p_=nh.p_;
|
||||
|
||||
nh.p_=nullptr;
|
||||
reinterpret_cast<Allocator*>(nh.a_)->~Allocator();
|
||||
}else if (!empty()){
|
||||
reinterpret_cast<Allocator*>(a_)->~Allocator();
|
||||
p_=nullptr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~node_handle_base()
|
||||
{
|
||||
if(!empty()){
|
||||
type_policy::destroy(al(),p_);
|
||||
reinterpret_cast<Allocator*>(a_)->~Allocator();
|
||||
}
|
||||
}
|
||||
|
||||
allocator_type get_allocator()const noexcept{return al();}
|
||||
explicit operator bool()const noexcept{ return !empty();}
|
||||
BOOST_ATTRIBUTE_NODISCARD bool empty()const noexcept{return p_==nullptr;}
|
||||
|
||||
void swap(node_handle_base& nh) noexcept(
|
||||
boost::allocator_is_always_equal<Allocator>::type::value||
|
||||
boost::allocator_propagate_on_container_swap<Allocator>::type::value)
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
bool const pocs=
|
||||
boost::allocator_propagate_on_container_swap<Allocator>::type::value;
|
||||
|
||||
if (!empty()&&!nh.empty()){
|
||||
BOOST_ASSERT(pocs || al()==nh.al());
|
||||
|
||||
value_type *p=p_;
|
||||
p_=nh.p_;
|
||||
nh.p_=p;
|
||||
|
||||
if(pocs){
|
||||
swap(al(),nh.al());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty()&&nh.empty()){return;}
|
||||
|
||||
if (empty()){
|
||||
emplace(nh.p_,nh.al());
|
||||
nh.clear();
|
||||
}else{
|
||||
nh.emplace(p_,al());
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
friend
|
||||
void swap(node_handle_base& lhs,node_handle_base& rhs)
|
||||
noexcept(noexcept(lhs.swap(rhs)))
|
||||
{
|
||||
return lhs.swap(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
static const std::size_t default_bucket_count = 0;
|
||||
|
||||
/* foa::table is an open-addressing hash table serving as the foundational core
|
||||
@ -1583,6 +1426,14 @@ public:
|
||||
BOOST_FORCEINLINE std::pair<iterator,bool>
|
||||
insert(value_type&& x){return emplace_impl(std::move(x));}
|
||||
|
||||
template<typename T=element_type>
|
||||
BOOST_FORCEINLINE
|
||||
typename std::enable_if<
|
||||
!std::is_same<T,value_type>::value,
|
||||
std::pair<iterator,bool>
|
||||
>::type
|
||||
insert(element_type&& x){return emplace_impl(std::move(x));}
|
||||
|
||||
template<
|
||||
bool dependent_value=false,
|
||||
typename std::enable_if<
|
||||
@ -2045,7 +1896,7 @@ private:
|
||||
|
||||
return emplace_impl(type_policy::move(*p));
|
||||
}
|
||||
public:
|
||||
|
||||
template<typename... Args>
|
||||
BOOST_FORCEINLINE std::pair<iterator,bool> emplace_impl(Args&&... args)
|
||||
{
|
||||
@ -2070,7 +1921,7 @@ public:
|
||||
};
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
static std::size_t capacity_for(std::size_t n)
|
||||
{
|
||||
return size_policy::size(size_index_for<group_type,size_policy>(n))*N-1;
|
||||
|
196
include/boost/unordered/detail/foa/node_handle.hpp
Normal file
196
include/boost/unordered/detail/foa/node_handle.hpp
Normal file
@ -0,0 +1,196 @@
|
||||
/* Copyright 2023 Christian Mazakas.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See https://www.boost.org/libs/unordered for library home page.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
|
||||
#define BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/allocator_access.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace unordered{
|
||||
namespace detail{
|
||||
namespace foa{
|
||||
|
||||
template <class Iterator,class NodeType>
|
||||
struct insert_return_type
|
||||
{
|
||||
Iterator position;
|
||||
bool inserted;
|
||||
NodeType node;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
union opt_storage {
|
||||
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS T t_;
|
||||
|
||||
opt_storage(){}
|
||||
~opt_storage(){}
|
||||
};
|
||||
|
||||
template <class TypePolicy,class Allocator>
|
||||
struct node_handle_base
|
||||
{
|
||||
protected:
|
||||
using type_policy=TypePolicy;
|
||||
using value_type=typename type_policy::value_type;
|
||||
using element_type=typename type_policy::element_type;
|
||||
|
||||
public:
|
||||
using allocator_type = Allocator;
|
||||
|
||||
private:
|
||||
value_type* p_=nullptr;
|
||||
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS opt_storage<Allocator> a_;
|
||||
|
||||
protected:
|
||||
value_type& element()noexcept
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return *p_;
|
||||
}
|
||||
|
||||
value_type const& element()const noexcept
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return *p_;
|
||||
}
|
||||
|
||||
Allocator& al()noexcept
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return a_.t_;
|
||||
}
|
||||
|
||||
Allocator const& al()const noexcept
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return a_.t_;
|
||||
}
|
||||
|
||||
void emplace(value_type* p,Allocator a)
|
||||
{
|
||||
BOOST_ASSERT(empty());
|
||||
p_=p;
|
||||
new(&a_.t_)Allocator(a);
|
||||
}
|
||||
|
||||
void emplace(element_type&& x,Allocator a)
|
||||
{
|
||||
emplace(x.p,a);
|
||||
x.p=nullptr;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
al().~Allocator();
|
||||
p_=nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr node_handle_base()noexcept=default;
|
||||
|
||||
node_handle_base(node_handle_base&& nh) noexcept
|
||||
{
|
||||
if (!nh.empty()){
|
||||
emplace(nh.p_,nh.al());
|
||||
nh.clear();
|
||||
}
|
||||
}
|
||||
|
||||
node_handle_base& operator=(node_handle_base&& nh)noexcept
|
||||
{
|
||||
bool const pocma=
|
||||
boost::allocator_propagate_on_container_move_assignment<
|
||||
Allocator>::type::value;
|
||||
|
||||
BOOST_ASSERT(
|
||||
pocma
|
||||
||empty()
|
||||
||nh.empty()
|
||||
||(al()==nh.al()));
|
||||
|
||||
if(!empty()){
|
||||
type_policy::destroy(al(),p_);
|
||||
if (pocma&&!nh.empty()){al()=std::move(nh.al());}
|
||||
}
|
||||
|
||||
if(!nh.empty()){
|
||||
if(empty()){new(&a_.t_)Allocator(std::move(nh.al()));}
|
||||
p_=nh.p_;
|
||||
|
||||
nh.p_=nullptr;
|
||||
nh.a_.t_.~Allocator();
|
||||
}else if (!empty()){
|
||||
a_.t_.~Allocator();
|
||||
p_=nullptr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~node_handle_base()
|
||||
{
|
||||
if(!empty()){
|
||||
type_policy::destroy(al(),p_);
|
||||
a_.t_.~Allocator();
|
||||
}
|
||||
}
|
||||
|
||||
allocator_type get_allocator()const noexcept{return al();}
|
||||
explicit operator bool()const noexcept{ return !empty();}
|
||||
BOOST_ATTRIBUTE_NODISCARD bool empty()const noexcept{return p_==nullptr;}
|
||||
|
||||
void swap(node_handle_base& nh) noexcept(
|
||||
boost::allocator_is_always_equal<Allocator>::type::value||
|
||||
boost::allocator_propagate_on_container_swap<Allocator>::type::value)
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
bool const pocs=
|
||||
boost::allocator_propagate_on_container_swap<Allocator>::type::value;
|
||||
|
||||
if (!empty()&&!nh.empty()){
|
||||
BOOST_ASSERT(pocs || al()==nh.al());
|
||||
|
||||
value_type *p=p_;
|
||||
p_=nh.p_;
|
||||
nh.p_=p;
|
||||
|
||||
if(pocs){
|
||||
swap(al(),nh.al());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty()&&nh.empty()){return;}
|
||||
|
||||
if (empty()){
|
||||
emplace(nh.p_,nh.al());
|
||||
nh.clear();
|
||||
}else{
|
||||
nh.emplace(p_,al());
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
friend
|
||||
void swap(node_handle_base& lhs,node_handle_base& rhs)
|
||||
noexcept(noexcept(lhs.swap(rhs)))
|
||||
{
|
||||
return lhs.swap(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
|
@ -11,6 +11,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/foa.hpp>
|
||||
#include <boost/unordered/detail/foa/node_handle.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/unordered/unordered_node_map_fwd.hpp>
|
||||
|
||||
@ -139,16 +140,12 @@ namespace boost {
|
||||
using base_type =
|
||||
detail::foa::node_handle_base<NodeMapTypes, Allocator>;
|
||||
|
||||
using base_type::element;
|
||||
using typename base_type::type_policy;
|
||||
|
||||
template <class Key, class T, class Hash, class Pred, class Alloc>
|
||||
friend class boost::unordered::unordered_node_map;
|
||||
|
||||
public:
|
||||
using base_type::empty;
|
||||
using base_type::swap;
|
||||
|
||||
using key_type = typename NodeMapTypes::key_type;
|
||||
using mapped_type = typename NodeMapTypes::mapped_type;
|
||||
|
||||
@ -159,14 +156,14 @@ namespace boost {
|
||||
|
||||
key_type& key() const
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return const_cast<key_type&>(element().first);
|
||||
BOOST_ASSERT(!this->empty());
|
||||
return const_cast<key_type&>(this->element().first);
|
||||
}
|
||||
|
||||
mapped_type& mapped() const
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return const_cast<mapped_type&>(element().second);
|
||||
BOOST_ASSERT(!this->empty());
|
||||
return const_cast<mapped_type&>(this->element().second);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
@ -408,7 +405,7 @@ namespace boost {
|
||||
typename map_types::element_type x;
|
||||
x.p=std::addressof(nh.element());
|
||||
|
||||
auto itp = table_.emplace_impl(std::move(x));
|
||||
auto itp = table_.insert(std::move(x));
|
||||
if (itp.second) {
|
||||
nh.clear();
|
||||
return {itp.first, true, node_type{}};
|
||||
@ -425,7 +422,7 @@ namespace boost {
|
||||
|
||||
BOOST_ASSERT(get_allocator() == nh.get_allocator());
|
||||
|
||||
auto itp = table_.emplace_impl(map_types::move(nh.element()));
|
||||
auto itp = table_.insert(map_types::move(nh.element()));
|
||||
return itp.first;
|
||||
}
|
||||
|
||||
@ -597,12 +594,7 @@ namespace boost {
|
||||
node_type extract(key_type const& key)
|
||||
{
|
||||
auto pos = find(key);
|
||||
node_type nh;
|
||||
if (pos != end()) {
|
||||
auto elem = table_.extract(pos);
|
||||
nh.emplace(std::move(elem), get_allocator());
|
||||
}
|
||||
return nh;
|
||||
return pos!=end()?extract(pos):node_type();
|
||||
}
|
||||
|
||||
template <class K>
|
||||
@ -613,12 +605,7 @@ namespace boost {
|
||||
extract(K const& key)
|
||||
{
|
||||
auto pos = find(key);
|
||||
node_type nh;
|
||||
if (pos != end()) {
|
||||
auto elem = table_.extract(pos);
|
||||
nh.emplace(std::move(elem), get_allocator());
|
||||
}
|
||||
return nh;
|
||||
return pos!=end()?extract(pos):node_type();
|
||||
}
|
||||
|
||||
template <class H2, class P2>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#endif
|
||||
|
||||
#include <boost/unordered/detail/foa.hpp>
|
||||
#include <boost/unordered/detail/foa/node_handle.hpp>
|
||||
#include <boost/unordered/detail/type_traits.hpp>
|
||||
#include <boost/unordered/unordered_node_set_fwd.hpp>
|
||||
|
||||
@ -121,16 +122,12 @@ namespace boost {
|
||||
using base_type =
|
||||
detail::foa::node_handle_base<NodeSetTypes, Allocator>;
|
||||
|
||||
using base_type::element;
|
||||
using typename base_type::type_policy;
|
||||
|
||||
template <class Key, class Hash, class Pred, class Alloc>
|
||||
friend class boost::unordered::unordered_node_set;
|
||||
|
||||
public:
|
||||
using base_type::empty;
|
||||
using base_type::swap;
|
||||
|
||||
using value_type = typename NodeSetTypes::value_type;
|
||||
|
||||
constexpr node_set_handle() noexcept = default;
|
||||
@ -139,8 +136,8 @@ namespace boost {
|
||||
|
||||
value_type& value() const
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return const_cast<value_type&>(element());
|
||||
BOOST_ASSERT(!this->empty());
|
||||
return const_cast<value_type&>(this->element());
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
@ -396,7 +393,7 @@ namespace boost {
|
||||
typename set_types::element_type x;
|
||||
x.p=std::addressof(nh.element());
|
||||
|
||||
auto itp = table_.emplace_impl(std::move(x));
|
||||
auto itp = table_.insert(std::move(x));
|
||||
if (itp.second) {
|
||||
nh.clear();
|
||||
return {itp.first, true, node_type{}};
|
||||
@ -413,7 +410,7 @@ namespace boost {
|
||||
|
||||
BOOST_ASSERT(get_allocator() == nh.get_allocator());
|
||||
|
||||
auto itp = table_.emplace_impl(set_types::move(nh.element()));
|
||||
auto itp = table_.insert(set_types::move(nh.element()));
|
||||
return itp.first;
|
||||
}
|
||||
|
||||
@ -473,12 +470,7 @@ namespace boost {
|
||||
node_type extract(key_type const& key)
|
||||
{
|
||||
auto pos = find(key);
|
||||
node_type nh;
|
||||
if (pos != end()) {
|
||||
auto elem = table_.extract(pos);
|
||||
nh.emplace(std::move(elem), get_allocator());
|
||||
}
|
||||
return nh;
|
||||
return pos!=end()?extract(pos):node_type();
|
||||
}
|
||||
|
||||
template <class K>
|
||||
@ -489,12 +481,7 @@ namespace boost {
|
||||
extract(K const& key)
|
||||
{
|
||||
auto pos = find(key);
|
||||
node_type nh;
|
||||
if (pos != end()) {
|
||||
auto elem = table_.extract(pos);
|
||||
nh.emplace(std::move(elem), get_allocator());
|
||||
}
|
||||
return nh;
|
||||
return pos!=end()?extract(pos):node_type();
|
||||
}
|
||||
|
||||
template <class H2, class P2>
|
||||
|
Reference in New Issue
Block a user