/* Fast open-addressing concurrent hash table. * * 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. */ /* Reference: * https://github.com/joaquintides/concurrent_hashmap_api#proposed-synopsis */ #ifndef BOOST_UNORDERED_CONCURRENT_FLAT_MAP_HPP #define BOOST_UNORDERED_CONCURRENT_FLAT_MAP_HPP #include #include #include #include #include #include namespace boost { namespace unordered { namespace detail { template struct concurrent_map_types { using key_type = Key; using raw_key_type = typename std::remove_const::type; using raw_mapped_type = typename std::remove_const::type; using init_type = std::pair; using moved_type = std::pair; using value_type = std::pair; using element_type = value_type; static value_type& value_from(element_type& x) { return x; } template static raw_key_type const& extract(std::pair const& kv) { return kv.first; } static moved_type move(init_type& x) { return {std::move(x.first), std::move(x.second)}; } static moved_type move(element_type& x) { // TODO: we probably need to launder here return {std::move(const_cast(x.first)), std::move(const_cast(x.second))}; } template static void construct(A& al, init_type* p, Args&&... args) { boost::allocator_construct(al, p, std::forward(args)...); } template static void construct(A& al, value_type* p, Args&&... args) { boost::allocator_construct(al, p, std::forward(args)...); } template static void destroy(A& al, init_type* p) noexcept { boost::allocator_destroy(al, p); } template static void destroy(A& al, value_type* p) noexcept { boost::allocator_destroy(al, p); } }; } // namespace detail template , class Pred = std::equal_to, class Allocator = std::allocator > > class concurrent_flat_map { private: using type_policy = detail::concurrent_map_types; detail::foa::concurrent_table table_; public: using key_type = Key; using mapped_type = T; using value_type = typename type_policy::value_type; using init_type = typename type_policy::init_type; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using hasher = typename boost::type_identity::type; using key_equal = typename boost::type_identity::type; using allocator_type = typename boost::type_identity::type; using reference = value_type&; using const_reference = value_type const&; using pointer = typename boost::allocator_pointer::type; using const_pointer = typename boost::allocator_const_pointer::type; concurrent_flat_map() : concurrent_flat_map(0) {} explicit concurrent_flat_map(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()) : table_(n, hf, eql, a) { } /// Capacity /// size_type size() const noexcept { return table_.size(); } /// Modifiers /// bool insert(value_type const& obj) { return table_.insert(obj); } bool insert(value_type&& obj) { return table_.insert(std::move(obj)); } bool insert(init_type const& obj) { return table_.insert(obj); } bool insert(init_type&& obj) { return table_.insert(std::move(obj)); } template void insert(InputIterator begin, InputIterator end) { for (auto pos = begin; pos != end; ++pos) { table_.insert(*pos); } } template std::size_t visit_all(F f) { return table_.visit_all(std::move(f)); } /// Hash Policy /// void rehash(size_type n) { table_.rehash(n); } }; } // namespace unordered } // namespace boost #endif // BOOST_UNORDERED_CONCURRENT_FLAT_MAP_HPP