Browse Source

remove the duplicate storage under case K==V

V2-integral-fix
Zhicheng Wang 4 days ago
parent
commit
c861de92a6
  1. 132
      shared_module/container/hashed_refcount_hive.hpp
  2. 61
      shared_module/container/wrapper/object_map.hpp

132
shared_module/container/hashed_refcount_hive.hpp

@ -0,0 +1,132 @@
#pragma once
#include "hive.hpp"
#include "hashmap.hpp"
namespace detail
{
template <typename K>
struct hasher {
size_t operator()(const K& k) const;
};
// template <typename K>
// struct eq_compare
// {
// bool operator()(const K& lhs, const K& rhs) const;
// };
template <typename K, typename V>
struct default_elem_ctor {
V operator()(const K& k) const;
};
template <typename K, typename V, typename Allocator = std::allocator<V>>
struct hashed_refcount_hive {
using iterator = typename hive<V, Allocator>::iterator;
public:
std::pair<iterator, bool> acquire(const K& key)
{
size_t hash_key = hasher<K>()(key);
auto iter = refcount_data_map.find(hash_key);
if (iter == refcount_data_map.end()) {
auto data_iter = data.emplace(default_elem_ctor<K, V>{}(key));
refcount_data_map.emplace(hash_key, std::make_pair(1, data_iter));
return {data_iter, true};
} else {
iter->second.first += 1;
return {iter->second.second, false};
}
}
void release(const K& key)
{
size_t hash_key = hasher<K>()(key);
auto iter = refcount_data_map.find(hash_key);
if (iter == refcount_data_map.end()) throw std::runtime_error("Key not found in refcount map.");
if (--iter->second.first == 0) {
data.erase(iter->second.second);
refcount_data_map.erase(iter);
}
}
void release(const iterator& ptr)
{
for (auto iter = refcount_data_map.begin(); iter != refcount_data_map.end(); ++iter) {
if (iter->second.second == ptr) {
if (--iter->second.first == 0) {
data.erase(iter->second.second);
refcount_data_map.erase(iter);
}
return;
}
}
throw std::runtime_error("Pointer not found in refcount map.");
}
protected:
hive<V, Allocator> data{};
// manually calculate hash for the key, so that we do not need to store the key
flat_hash_map<size_t, std::pair<size_t, iterator>> refcount_data_map{};
};
template <typename T, typename Tag>
struct tagged_hasher;
template <typename K, typename V, typename Tag, typename Allocator = std::allocator<V>>
struct tagged_hashed_refcount_hive {
using iterator = typename hive<V, Allocator>::iterator;
public:
std::pair<iterator, bool> acquire(const K& key)
{
size_t hash_key = tagged_hasher<K, Tag>()(key);
auto iter = refcount_data_map.find(hash_key);
if (iter == refcount_data_map.end()) {
auto data_iter = data.emplace(default_elem_ctor<K, V>{}(key));
refcount_data_map.emplace(hash_key, std::make_pair(1, data_iter));
return {data_iter, true};
} else {
iter->second.first += 1;
return {iter->second.second, false};
}
}
void release(const K& key)
{
size_t hash_key = tagged_hasher<K, Tag>()(key);
auto iter = refcount_data_map.find(hash_key);
if (iter == refcount_data_map.end()) throw std::runtime_error("Key not found in refcount map.");
if (--iter->second.first == 0) {
data.erase(iter->second.second);
refcount_data_map.erase(iter);
}
}
void release(const iterator& ptr)
{
for (auto iter = refcount_data_map.begin(); iter != refcount_data_map.end(); ++iter) {
if (iter->second.second == ptr) {
if (--iter->second.first == 0) {
data.erase(iter->second.second);
refcount_data_map.erase(iter);
}
return;
}
}
throw std::runtime_error("Pointer not found in refcount map.");
}
protected:
hive<V, Allocator> data{};
// manually calculate hash for the key, so that we do not need to store the key
flat_hash_map<size_t, std::pair<size_t, iterator>> refcount_data_map{};
};
} // namespace detail
template <typename K, typename V>
using hashed_refcount_hive_mp = detail::hashed_refcount_hive<K, V, mi_stl_allocator<V>>;
template <typename K, typename V, typename Tag>
using tagged_hashed_refcount_hive_mp = detail::tagged_hashed_refcount_hive<K, V, Tag, mi_stl_allocator<V>>;

61
shared_module/container/wrapper/object_map.hpp

@ -1,4 +1,5 @@
#include <container/hashmap.hpp> #include <container/hashmap.hpp>
#include <container/hive.hpp>
#include <utils/pointer_wrapper.hpp> #include <utils/pointer_wrapper.hpp>
namespace detail namespace detail
@ -32,13 +33,10 @@ struct flat_object_map {
auto [iter, is_new] = data.try_emplace(key, object_with_refcount{}); auto [iter, is_new] = data.try_emplace(key, object_with_refcount{});
auto& value = iter->second; auto& value = iter->second;
if (is_new) { if (is_new) {
value.refcount = 1; value.refcount = 1;
V* new_value = static_cast<V*>(mi_aligned_alloc(alignof(V), sizeof(V))); V* new_value = static_cast<V*>(mi_aligned_alloc(alignof(V), sizeof(V)));
value.object_pointer = make_pointer_wrapper(new_value); value.object_pointer = make_pointer_wrapper(new_value);
if constexpr (std::is_same_v<V, K>) *value.object_pointer = std::move(default_elem_ctor<K, V>{}(key));
*value.object_pointer = key;
else
*value.object_pointer = std::move(default_elem_ctor<K, V>{}(key));
return {value.object_pointer, true}; return {value.object_pointer, true};
} else { } else {
value.refcount++; value.refcount++;
@ -61,7 +59,54 @@ protected:
value_pointer_t object_pointer{}; value_pointer_t object_pointer{};
}; };
flat_hash_map<K, object_with_refcount, Hasher, eq_compare<K>, Allocator<std::pair<const K, V>>> data{}; flat_hash_map<K, object_with_refcount, Hasher, eq_compare<K>, Allocator<std::pair<const K, object_with_refcount>>> data{};
};
template <typename K, template <typename> typename Allocator>
struct flat_object_map<K, K, hasher<size_t>, Allocator> {
using value_pointer_t = pointer_wrapper<K>;
std::pair<value_pointer_t, bool> 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<K, Allocator<K>> data{};
using iterator = typename decltype(data)::iterator;
struct object_with_refcount {
size_t refcount{};
iterator object_iter{};
};
flat_hash_map<size_t,
object_with_refcount,
hasher<size_t>,
eq_compare<K>,
Allocator<std::pair<const K, object_with_refcount>>>
refcount_data_map{};
}; };
} // namespace detail } // namespace detail

Loading…
Cancel
Save