6 #ifndef METALL_CONTAINER_CONCURRENT_MAP_HPP
7 #define METALL_CONTAINER_CONCURRENT_MAP_HPP
11 #include <boost/container/vector.hpp>
12 #include <boost/container/map.hpp>
13 #include <boost/container/scoped_allocator.hpp>
29 template <
typename _key_type,
typename _mapped_type,
30 typename _compare = std::less<_key_type>,
31 typename _bank_no_hasher = std::hash<_key_type>,
33 std::allocator<std::pair<const _key_type, _mapped_type>>,
34 int k_num_banks = 1024>
38 using other_allocator_type =
39 typename std::allocator_traits<_allocator>::template rebind_alloc<T>;
41 using internal_map_type =
42 boost::container::map<_key_type, _mapped_type, _compare, _allocator>;
43 using banked_map_allocator_type = other_allocator_type<internal_map_type>;
46 boost::container::scoped_allocator_adaptor<banked_map_allocator_type>>;
53 using key_type =
typename internal_map_type::key_type;
57 using value_type =
typename internal_map_type::value_type;
59 using size_type =
typename internal_map_type::size_type;
66 typename banked_map_type::const_iterator,
67 typename internal_map_type::const_iterator>;
73 : m_banked_map(k_num_banks, allocator), m_num_items(0) {}
83 const auto bank_no = calc_bank_no(key);
84 return m_banked_map[bank_no].count(key);
97 const auto bank_no = calc_bank_no(value.first);
98 auto lock = metall::utility::mutex::mutex_lock<k_num_banks>(bank_no);
100 m_banked_map[bank_no].insert(std::forward<value_type>(value)).second;
101 m_num_items += (ret) ? 1 : 0;
109 std::pair<mapped_type &, std::unique_lock<std::mutex>>
scoped_edit(
111 const auto bank_no = calc_bank_no(key);
112 auto lock = metall::utility::mutex::mutex_lock<k_num_banks>(bank_no);
114 [[maybe_unused]]
const bool ret = register_key_no_lock(key);
118 return std::make_pair(std::ref(m_banked_map[bank_no].at(key)),
127 const std::function<
void(
mapped_type &mapped_value)> &editor) {
128 const auto bank_no = calc_bank_no(key);
129 auto lock = metall::utility::mutex::mutex_lock<k_num_banks>(bank_no);
131 [[maybe_unused]]
const bool ret = register_key_no_lock(key);
135 editor(m_banked_map[bank_no].at(key));
143 return const_iterator(m_banked_map.cbegin(), m_banked_map.cend());
160 const auto bank_no = calc_bank_no(key);
161 auto itr = m_banked_map[bank_no].find(key);
162 if (itr != m_banked_map[bank_no].end()) {
163 return const_iterator(m_banked_map.cbegin(), itr, m_banked_map.cend());
176 static uint64_t calc_bank_no(
const key_type &key) {
177 return _bank_no_hasher()(key) % k_num_banks;
180 bool register_key_no_lock(
const key_type &key) {
181 const auto bank_no = calc_bank_no(key);
182 return m_banked_map[bank_no].try_emplace(key).second;
185 banked_map_type m_banked_map;