diff --git a/include/boost/unordered/detail/allocator_constructed.hpp b/include/boost/unordered/detail/allocator_constructed.hpp new file mode 100644 index 00000000..29fb1566 --- /dev/null +++ b/include/boost/unordered/detail/allocator_constructed.hpp @@ -0,0 +1,59 @@ +/* Copyright 2024 Braden Ganetsky. + * 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_ALLOCATOR_CONSTRUCTED_HPP +#define BOOST_UNORDERED_DETAIL_ALLOCATOR_CONSTRUCTED_HPP + +#include +#include + +namespace boost { + namespace unordered { + namespace detail { + + struct allocator_policy + { + template + static void construct(Allocator& a, T* p, Args&&... args) + { + boost::allocator_construct(a, p, std::forward(args)...); + } + + template + static void destroy(Allocator& a, T* p) + { + boost::allocator_destroy(a, p); + } + }; + + /* constructs a stack-based object with the given policy and allocator */ + template + class allocator_constructed + { + opt_storage storage; + Allocator alloc; + + public: + template + allocator_constructed(Allocator const& alloc_, Args&&... args) + : alloc(alloc_) + { + Policy::construct( + alloc, storage.address(), std::forward(args)...); + } + + ~allocator_constructed() { Policy::destroy(alloc, storage.address()); } + + T& value() { return *storage.address(); } + }; + + } /* namespace detail */ + } /* namespace unordered */ +} /* namespace boost */ + +#endif diff --git a/include/boost/unordered/detail/foa/concurrent_table.hpp b/include/boost/unordered/detail/foa/concurrent_table.hpp index 5c6de985..9dbef35c 100644 --- a/include/boost/unordered/detail/foa/concurrent_table.hpp +++ b/include/boost/unordered/detail/foa/concurrent_table.hpp @@ -1320,7 +1320,7 @@ private: { auto lck=shared_access(); - auto x=alloc_make_insert_type( + alloc_cted_insert_type x( this->al(),std::forward(args)...); int res=unprotected_norehash_emplace_or_visit( access_mode,std::forward(f),type_policy::move(x.value())); diff --git a/include/boost/unordered/detail/foa/core.hpp b/include/boost/unordered/detail/foa/core.hpp index 0ffbfc03..64894a04 100644 --- a/include/boost/unordered/detail/foa/core.hpp +++ b/include/boost/unordered/detail/foa/core.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -1220,31 +1221,17 @@ class alloc_cted_insert_type emplace_type,typename TypePolicy::element_type >::type; - alignas(insert_type) unsigned char storage[sizeof(insert_type)]; - Allocator al; + using alloc_cted = allocator_constructed; + alloc_cted val; public: - alloc_cted_insert_type(const Allocator& al_,Args&&... args):al{al_} + alloc_cted_insert_type(const Allocator& al_,Args&&... args):val{al_,std::forward(args)...} { - TypePolicy::construct(al,data(),std::forward(args)...); } - ~alloc_cted_insert_type() - { - TypePolicy::destroy(al,data()); - } - - insert_type* data(){return reinterpret_cast(&storage);} - insert_type& value(){return *data();} + insert_type& value(){return val.value();} }; -template -alloc_cted_insert_type -alloc_make_insert_type(const Allocator& al,Args&&... args) -{ - return {al,std::forward(args)...}; -} - /* table_core. The TypePolicy template parameter is used to generate * instantiations suitable for either maps or sets, and introduces non-standard * init_type and element_type: diff --git a/include/boost/unordered/detail/foa/table.hpp b/include/boost/unordered/detail/foa/table.hpp index 4d248c4a..0cd56de2 100644 --- a/include/boost/unordered/detail/foa/table.hpp +++ b/include/boost/unordered/detail/foa/table.hpp @@ -401,7 +401,7 @@ public: template BOOST_FORCEINLINE std::pair emplace(Args&&... args) { - auto x=alloc_make_insert_type( + alloc_cted_insert_type x( this->al(),std::forward(args)...); return emplace_impl(type_policy::move(x.value())); }