6 #ifndef XENIUM_VYUKOV_HASH_MAP_HPP
7 #define XENIUM_VYUKOV_HASH_MAP_HPP
9 #include <xenium/acquire_guard.hpp>
10 #include <xenium/backoff.hpp>
11 #include <xenium/hash.hpp>
12 #include <xenium/parameter.hpp>
13 #include <xenium/policy.hpp>
14 #include <xenium/utils.hpp>
35 template <
class Key,
class Value,
class ValueReclaimer,
class Reclaimer,
bool TrivialKey,
bool TrivialValue>
36 struct vyukov_hash_map_traits;
46 template <
class T,
class Reclaimer>
51 struct vyukov_supported_type {
52 static constexpr
bool value = std::is_trivial<T>::value && (
sizeof(T) == 4 ||
sizeof(T) == 8);
54 template <
class T,
class Reclaimer>
55 struct vyukov_supported_type<
managed_ptr<T, Reclaimer>> {
56 static_assert(std::is_base_of<
typename Reclaimer::template enable_concurrent_ptr<T>, T>::value,
57 "The type T specified in managed_ptr must derive from Reclaimer::enable_concurrent_ptr");
58 static constexpr
bool value =
true;
134 template <
class Key,
class Value,
class... Policies>
136 using reclaimer = parameter::type_param_t<
policy::reclaimer, parameter::nil, Policies...>;
138 using hash = parameter::type_param_t<policy::hash, xenium::hash<Key>, Policies...>;
141 template <
class... NewPolicies>
144 static_assert(parameter::is_set<reclaimer>::value,
"reclaimer policy must be specified");
147 using traits =
typename impl::vyukov_hash_map_traits<Key,
151 detail::vyukov_supported_type<Key>::value,
152 detail::vyukov_supported_type<Value>::value>;
159 using accessor =
typename traits::accessor;
161 using key_type =
typename traits::key_type;
162 using value_type =
typename traits::value_type;
177 bool emplace(key_type key, value_type value);
194 template <
class... Args>
195 std::pair<accessor, bool>
get_or_emplace(key_type key, Args&&... args);
215 template <
class Factory>
230 bool extract(
const key_type& key, accessor& accessor);
242 bool erase(
const key_type& key);
268 bool try_get_value(
const key_type& key, accessor& result)
const;
308 struct extension_item;
309 struct extension_bucket;
311 using block_ptr =
typename reclaimer::template concurrent_ptr<block, 0>;
312 using guarded_block =
typename block_ptr::guard_ptr;
314 static constexpr std::uint32_t bucket_to_extension_ratio = 128;
315 static constexpr std::uint32_t bucket_item_count = 3;
316 static constexpr std::uint32_t extension_item_count = 10;
318 static constexpr std::size_t item_counter_bits = utils::find_last_bit_set(bucket_item_count);
319 static constexpr std::size_t lock_bit = 2 * item_counter_bits + 1;
320 static constexpr std::size_t version_shift = lock_bit;
322 static constexpr std::uint32_t lock = 1u << (lock_bit - 1);
323 static constexpr std::size_t version_inc =
static_cast<std::size_t
>(1) << lock_bit;
325 static constexpr std::uint32_t item_count_mask = (1u << item_counter_bits) - 1;
326 static constexpr std::uint32_t delete_item_mask = item_count_mask << item_counter_bits;
328 static constexpr std::align_val_t cacheline_size{64};
330 block_ptr data_block;
331 std::atomic<int> resize_lock;
333 block* allocate_block(std::uint32_t bucket_count);
335 bucket& lock_bucket(hash_t hash, guarded_block& block, bucket_state& state);
336 void grow(bucket& bucket, bucket_state state);
339 template <
bool AcquireAccessor,
class Factory,
class Callback>
340 bool do_get_or_emplace(Key&& key, Factory&& factory, Callback&& callback);
342 bool do_extract(
const key_type& key, accessor& result);
344 static extension_item* allocate_extension_item(block* b, hash_t hash);
345 static void free_extension_item(extension_item* item);
366 template <
class Key,
class Value,
class... Policies>
369 using iterator_category = std::forward_iterator_tag;
370 using difference_type = std::ptrdiff_t;
371 using value_type =
typename traits::iterator_value_type;
372 using reference =
typename traits::iterator_reference;
373 using pointer = value_type*;
384 bool operator==(
const iterator& r)
const;
385 bool operator!=(
const iterator& r)
const;
388 reference operator*();
389 pointer operator->();
399 guarded_block block{};
400 bucket* current_bucket{};
401 bucket_state current_bucket_state{};
402 std::uint32_t index{};
403 extension_item* extension{};
404 std::atomic<extension_item*>* prev{};
407 void move_to_next_bucket();
408 Value* erase_current();
413 #define XENIUM_VYUKOV_HASH_MAP_IMPL
414 #include <xenium/impl/vyukov_hash_map.hpp>
415 #include <xenium/impl/vyukov_hash_map_traits.hpp>
416 #undef XENIUM_VYUKOV_HASH_MAP_IMPL