2 changed files with 185 additions and 8 deletions
@ -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>>; |
|||
Loading…
Reference in new issue