From 6bf84067b3292cd7cfcfba90e90bb3366e926df4 Mon Sep 17 00:00:00 2001 From: joaquintides Date: Sat, 22 Jul 2023 17:59:01 +0200 Subject: [PATCH] added unordered_flat_map(concurrent_flat_map&&) --- .../boost/unordered/concurrent_flat_map.hpp | 4 +++ .../unordered/detail/foa/concurrent_table.hpp | 18 +++++++--- include/boost/unordered/detail/foa/core.hpp | 36 +++++++++++++------ include/boost/unordered/detail/foa/table.hpp | 28 +++++++++++++++ .../boost/unordered/unordered_flat_map.hpp | 7 ++++ 5 files changed, 78 insertions(+), 15 deletions(-) diff --git a/include/boost/unordered/concurrent_flat_map.hpp b/include/boost/unordered/concurrent_flat_map.hpp index 9364d349..a5b968c8 100644 --- a/include/boost/unordered/concurrent_flat_map.hpp +++ b/include/boost/unordered/concurrent_flat_map.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -84,6 +85,9 @@ namespace boost { template friend class concurrent_flat_map; + template + friend class unordered_flat_map; using type_policy = detail::foa::flat_map_types; diff --git a/include/boost/unordered/detail/foa/concurrent_table.hpp b/include/boost/unordered/detail/foa/concurrent_table.hpp index 51615446..84a66c4e 100644 --- a/include/boost/unordered/detail/foa/concurrent_table.hpp +++ b/include/boost/unordered/detail/foa/concurrent_table.hpp @@ -281,6 +281,13 @@ struct concurrent_table_arrays:table_arrays template static void delete_(Allocator& al,concurrent_table_arrays& arrays)noexcept + { + delete_group_access(al,arrays); + super::delete_(al,arrays); + } + + template + static void delete_group_access(Allocator& al,concurrent_table_arrays& arrays)noexcept { if(arrays.elements){ using access_alloc= @@ -294,7 +301,6 @@ struct concurrent_table_arrays:table_arrays aal,pointer_traits::pointer_to(*arrays.group_accesses), arrays.groups_size_mask+1); } - super::delete_(al,arrays); } group_access *group_accesses; @@ -391,6 +397,9 @@ inline void swap(atomic_size_control& x,atomic_size_control& y) * over. */ +template +class table; /* concurrent/non-concurrent interop */ + template using concurrent_table_core_impl=table_core< TypePolicy,group15,concurrent_table_arrays, @@ -413,10 +422,6 @@ class concurrent_table: using super::N; using prober=typename super::prober; - template< - typename TypePolicy2,typename Hash2,typename Pred2,typename Allocator2> - friend class concurrent_table; - public: using key_type=typename super::key_type; using init_type=typename super::init_type; @@ -875,6 +880,9 @@ public: } private: + template friend class concurrent_table; + template friend class table; + using mutex_type=rw_spinlock; using multimutex_type=multimutex; // TODO: adapt 128 to the machine using shared_lock_guard=shared_lock; diff --git a/include/boost/unordered/detail/foa/core.hpp b/include/boost/unordered/detail/foa/core.hpp index 239d05d3..ae5c29c7 100644 --- a/include/boost/unordered/detail/foa/core.hpp +++ b/include/boost/unordered/detail/foa/core.hpp @@ -1282,6 +1282,17 @@ public: size_ctrl{initial_max_load(),0} {} + /* bare transfer ctor for concurrent/non-concurrent interop */ + + table_core( + Hash&& h_,Pred&& pred_,Allocator&& al_, + const arrays_type& arrays_,const size_ctrl_type& size_ctrl_): + hash_base{empty_init,h_}, + pred_base{empty_init,pred_}, + allocator_base{empty_init,al_}, + arrays(arrays_),size_ctrl(size_ctrl_) + {} + table_core(const table_core& x): table_core{x,alloc_traits::select_on_container_copy_construction(x.al())}{} @@ -1290,14 +1301,11 @@ public: std::is_nothrow_move_constructible::value&& std::is_nothrow_move_constructible::value&& std::is_nothrow_move_constructible::value): - hash_base{empty_init,std::move(x.h())}, - pred_base{empty_init,std::move(x.pred())}, - allocator_base{empty_init,std::move(x.al())}, - arrays(x.arrays),size_ctrl(x.size_ctrl) + table_core{ + std::move(x.h()),std::move(x.pred()),std::move(x.al()), + x.arrays,x.size_ctrl} { - x.arrays=x.new_arrays(0); - x.size_ctrl.ml=x.initial_max_load(); - x.size_ctrl.size=0; + x.empty_initialize(); } table_core(const table_core& x,const Allocator& al_): @@ -1336,6 +1344,13 @@ public: delete_arrays(arrays); } + void empty_initialize()noexcept + { + arrays=new_arrays(0); + size_ctrl.ml=initial_max_load(); + size_ctrl.size=0; + } + table_core& operator=(const table_core& x) { BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED(Hash, Pred) @@ -1802,9 +1817,10 @@ private: table_core(Hash&& h_,Pred&& pred_,const Allocator& al_): hash_base{empty_init,std::move(h_)}, pred_base{empty_init,std::move(pred_)}, - allocator_base{empty_init,al_},arrays(new_arrays(0)), - size_ctrl{initial_max_load(),0} - {} + allocator_base{empty_init,al_} + { + empty_initialize(); + } arrays_type new_arrays(std::size_t n) { diff --git a/include/boost/unordered/detail/foa/table.hpp b/include/boost/unordered/detail/foa/table.hpp index 85145cb6..3c4ab5ac 100644 --- a/include/boost/unordered/detail/foa/table.hpp +++ b/include/boost/unordered/detail/foa/table.hpp @@ -264,6 +264,9 @@ private: * checking is done by boost::unordered_(flat|node)_(map|set). */ +template +class concurrent_table; /* concurrent/non-concurrent interop */ + template using table_core_impl= table_core,table_arrays, @@ -284,6 +287,8 @@ class table:table_core_impl using group_type=typename super::group_type; using super::N; using prober=typename super::prober; + using arrays_type=typename super::arrays_type; + using size_ctrl_type=typename super::size_ctrl_type; using locator=typename super::locator; public: @@ -323,6 +328,8 @@ public: table(table&& x)=default; table(const table& x,const Allocator& al_):super{x,al_}{} table(table&& x,const Allocator& al_):super{std::move(x),al_}{} + table(concurrent_table&& x): + table(std::move(x),x.exclusive_access()){} ~table()=default; table& operator=(const table& x)=default; @@ -496,6 +503,27 @@ public: friend bool operator!=(const table& x,const table& y){return !(x==y);} private: + template friend class concurrent_table; + using compatible_concurrent_table= + concurrent_table; + + table( + compatible_concurrent_table&& x, + typename compatible_concurrent_table::exclusive_lock_guard): + super{ + std::move(x.h()),std::move(x.pred()),std::move(x.al()), + arrays_type{ + x.arrays.groups_size_index,x.arrays.groups_size_mask, + reinterpret_cast(x.arrays.groups), + reinterpret_cast(x.arrays.elements)}, + size_ctrl_type{ + x.size_ctrl.ml,x.size_ctrl.size}} + { + typename compatible_concurrent_table::arrays_type::delete_group_access( + this->al(),x.arrays); + x.empty_initialize(); + } + struct erase_on_exit { erase_on_exit(table& x_,const_iterator it_):x{x_},it{it_}{} diff --git a/include/boost/unordered/unordered_flat_map.hpp b/include/boost/unordered/unordered_flat_map.hpp index d74de55a..66ce6faf 100644 --- a/include/boost/unordered/unordered_flat_map.hpp +++ b/include/boost/unordered/unordered_flat_map.hpp @@ -10,6 +10,7 @@ #pragma once #endif +#include #include #include #include @@ -173,6 +174,12 @@ namespace boost { { } + unordered_flat_map( + concurrent_flat_map&& other) + : table_(std::move(other.table_)) + { + } + ~unordered_flat_map() = default; unordered_flat_map& operator=(unordered_flat_map const& other)