#include #include #include #include "mimalloc.h" namespace detail { template struct hasher { size_t operator()(const K& k) const; }; template struct tagged_hasher { size_t operator()(const K& k) const; }; template struct eq_compare { bool operator()(const K& lhs, const K& rhs) const { return lhs == rhs; } }; template struct default_elem_ctor { V operator()(const K& k) const; }; template , template typename Allocator = std::allocator> struct flat_object_map { using key_type = K; using value_type = V; using value_pointer_t = pointer_wrapper; std::pair acquire(const K& key) { auto [iter, is_new] = data.try_emplace(key, object_with_refcount{}); auto& value = iter->second; if (is_new) { value.refcount = 1; V* new_value = static_cast(mi_aligned_alloc(alignof(V), sizeof(V))); value.object_pointer = make_pointer_wrapper(new_value); *value.object_pointer = std::move(default_elem_ctor{}(key)); return {value.object_pointer, true}; } else { value.refcount++; return {value.object_pointer, false}; } } void release(const K& key) { if (auto iter = data.find(key); iter == data.end()) { throw std::runtime_error("Key not found in refcount map."); } else if (--iter->second.refcount == 0) { data.erase(iter); } } protected: struct object_with_refcount { size_t refcount{}; value_pointer_t object_pointer{}; }; flat_hash_map, Allocator>> data{}; }; template typename Allocator = std::allocator> struct flat_object_set { using value_pointer_t = pointer_wrapper; std::pair acquire(const K& key) { size_t hash_key = element_hasher{}(key); auto [iter, is_new] = data.emplace_with_hash(hash_key, nullptr, size_t{1}); auto object_pointer = const_cast(iter->first); auto& refcount = iter->second; if (is_new) { object_pointer = static_cast(mi_aligned_alloc(alignof(K), sizeof(K))); *object_pointer = std::move(key); return {make_pointer_wrapper(object_pointer), true}; } else { refcount++; return {make_pointer_wrapper(object_pointer), false}; } } void release(const K& key) { K* key_ptr = const_cast(&key); if (auto iter = data.find(key_ptr); iter == data.end()) { throw std::runtime_error("Key not found in refcount map."); } else if (--iter->second == 0) { iter->first->~K(); mi_free_aligned(iter->first, alignof(K)); data.erase(iter); } } protected: using value_type = K*; using element_hasher = hasher; struct inernal_hasher { size_t operator()(value_type ptr) const { if (ptr == nullptr) return size_t{0}; return element_hasher{}(*ptr); } }; flat_hash_map_mp, Allocator>> data{}; }; // template typename Allocator> // struct flat_object_set { // using object_type = K; // using value_pointer_t = pointer_wrapper; // using Hasher = hasher; // std::pair acquire(const K& key) // { // size_t hash_key = Hasher()(key); // auto [iter, is_new] = refcount_data_map.try_emplace(hash_key, object_with_refcount{}); // auto& [refcount, object_iter] = iter->second; // if (is_new) { // refcount = 1; // object_iter = data.emplace(key); // return {make_pointer_wrapper(object_iter.operator->()), true}; // } else { // refcount++; // return {make_pointer_wrapper(object_iter.operator->()), false}; // } // } // void release(const K& key) // { // size_t hash_key = Hasher()(key); // if (auto iter = refcount_data_map.find(hash_key); iter == refcount_data_map.end()) { // throw std::runtime_error("Key not found in refcount map."); // } else if (--iter->second.refcount == 0) { // data.erase(iter->second.object_iter); // refcount_data_map.erase(iter); // } // } // protected: // hive> data{}; // using iterator = typename decltype(data)::iterator; // struct object_with_refcount { // size_t refcount{}; // iterator object_iter{}; // }; // flat_hash_map, // phmap::priv::hash_default_eq, // Allocator>> // refcount_data_map{}; // }; } // namespace detail template using flat_object_map_mp = detail::flat_object_map, mi_stl_allocator>; template using flat_object_set_mp = detail::flat_object_set; template using tagged_flat_object_map_mp = detail::flat_object_map, mi_stl_allocator>;