util/IntrusiveHashSet: add template argument `GetKey`
This is a big simplification of all IntrusiveHashSet users: instead of having to implement multiple overloads of Hash and Equal, the IntrusiveHashSet class can first extract the effective key from an item and then pass it to the Hash/Equal functions.
This commit is contained in:
parent
78801f303e
commit
83a6cb804b
|
@ -52,26 +52,10 @@ class RemoteTagCache final {
|
||||||
void OnRemoteTag(Tag &&tag) noexcept override;
|
void OnRemoteTag(Tag &&tag) noexcept override;
|
||||||
void OnRemoteTagError(std::exception_ptr e) noexcept override;
|
void OnRemoteTagError(std::exception_ptr e) noexcept override;
|
||||||
|
|
||||||
struct Hash : std::hash<std::string> {
|
struct GetUri {
|
||||||
using std::hash<std::string>::operator();
|
|
||||||
|
|
||||||
[[gnu::pure]]
|
[[gnu::pure]]
|
||||||
std::size_t operator()(const Item &item) const noexcept {
|
std::string_view operator()(const Item &item) const noexcept {
|
||||||
return std::hash<std::string>::operator()(item.uri);
|
return item.uri;
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Equal {
|
|
||||||
[[gnu::pure]]
|
|
||||||
bool operator()(const Item &a,
|
|
||||||
const Item &b) const noexcept {
|
|
||||||
return a.uri == b.uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[gnu::pure]]
|
|
||||||
bool operator()(const std::string &a,
|
|
||||||
const Item &b) const noexcept {
|
|
||||||
return a == b.uri;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -101,7 +85,9 @@ class RemoteTagCache final {
|
||||||
ItemList invoke_list;
|
ItemList invoke_list;
|
||||||
|
|
||||||
IntrusiveHashSet<Item, 127,
|
IntrusiveHashSet<Item, 127,
|
||||||
IntrusiveHashSetOperators<Item::Hash, Item::Equal>,
|
IntrusiveHashSetOperators<std::hash<std::string_view>,
|
||||||
|
std::equal_to<std::string_view>,
|
||||||
|
Item::GetUri>,
|
||||||
IntrusiveHashSetBaseHookTraits<Item>,
|
IntrusiveHashSetBaseHookTraits<Item>,
|
||||||
true> map;
|
true> map;
|
||||||
|
|
||||||
|
|
|
@ -11,37 +11,10 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
inline std::size_t
|
inline std::string_view
|
||||||
InputCacheManager::ItemHash::operator()(std::string_view uri) const noexcept
|
InputCacheManager::ItemGetUri::operator()(const InputCacheItem &item) const noexcept
|
||||||
{
|
{
|
||||||
return std::hash<std::string_view>{}(uri);
|
return item.GetUri();
|
||||||
}
|
|
||||||
|
|
||||||
inline std::size_t
|
|
||||||
InputCacheManager::ItemHash::operator()(const InputCacheItem &item) const noexcept
|
|
||||||
{
|
|
||||||
return std::hash<std::string_view>{}(item.GetUri());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
InputCacheManager::ItemEqual::operator()(const InputCacheItem &a,
|
|
||||||
std::string_view b) const noexcept
|
|
||||||
{
|
|
||||||
return a.GetUri() == b;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
InputCacheManager::ItemEqual::operator()(std::string_view a,
|
|
||||||
const InputCacheItem &b) const noexcept
|
|
||||||
{
|
|
||||||
return a == b.GetUri();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
InputCacheManager::ItemEqual::operator()(const InputCacheItem &a,
|
|
||||||
const InputCacheItem &b) const noexcept
|
|
||||||
{
|
|
||||||
return a.GetUri() == b.GetUri();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputCacheManager::InputCacheManager(const InputCacheConfig &config) noexcept
|
InputCacheManager::InputCacheManager(const InputCacheConfig &config) noexcept
|
||||||
|
|
|
@ -24,32 +24,17 @@ class InputCacheManager {
|
||||||
|
|
||||||
size_t total_size = 0;
|
size_t total_size = 0;
|
||||||
|
|
||||||
struct ItemHash {
|
struct ItemGetUri {
|
||||||
[[gnu::pure]]
|
[[gnu::pure]]
|
||||||
std::size_t operator()(std::string_view uri) const noexcept;
|
std::string_view operator()(const InputCacheItem &item) const noexcept;
|
||||||
|
|
||||||
[[gnu::pure]]
|
|
||||||
std::size_t operator()(const InputCacheItem &item) const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ItemEqual {
|
|
||||||
[[gnu::pure]]
|
|
||||||
bool operator()(const InputCacheItem &a,
|
|
||||||
std::string_view b) const noexcept;
|
|
||||||
|
|
||||||
[[gnu::pure]]
|
|
||||||
bool operator()(std::string_view a,
|
|
||||||
const InputCacheItem &b) const noexcept;
|
|
||||||
|
|
||||||
[[gnu::pure]]
|
|
||||||
bool operator()(const InputCacheItem &a,
|
|
||||||
const InputCacheItem &b) const noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IntrusiveList<InputCacheItem> items_by_time;
|
IntrusiveList<InputCacheItem> items_by_time;
|
||||||
|
|
||||||
IntrusiveHashSet<InputCacheItem, 127,
|
IntrusiveHashSet<InputCacheItem, 127,
|
||||||
IntrusiveHashSetOperators<ItemHash, ItemEqual>> items_by_uri;
|
IntrusiveHashSetOperators<std::hash<std::string_view>,
|
||||||
|
std::equal_to<std::string_view>,
|
||||||
|
ItemGetUri>> items_by_uri;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit InputCacheManager(const InputCacheConfig &config) noexcept;
|
explicit InputCacheManager(const InputCacheConfig &config) noexcept;
|
||||||
|
|
|
@ -75,7 +75,12 @@ struct IntrusiveHashSetMemberHookTraits {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Hash, typename Equal>
|
/**
|
||||||
|
* @param GetKey a function object which extracts the "key" part of an
|
||||||
|
* item
|
||||||
|
*/
|
||||||
|
template<typename Hash, typename Equal,
|
||||||
|
typename GetKey=std::identity>
|
||||||
struct IntrusiveHashSetOperators {
|
struct IntrusiveHashSetOperators {
|
||||||
using hasher = Hash;
|
using hasher = Hash;
|
||||||
using key_equal = Equal;
|
using key_equal = Equal;
|
||||||
|
@ -85,6 +90,9 @@ struct IntrusiveHashSetOperators {
|
||||||
|
|
||||||
[[no_unique_address]]
|
[[no_unique_address]]
|
||||||
Equal equal;
|
Equal equal;
|
||||||
|
|
||||||
|
[[no_unique_address]]
|
||||||
|
GetKey get_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -214,7 +222,7 @@ public:
|
||||||
Disposer<value_type> auto disposer) noexcept {
|
Disposer<value_type> auto disposer) noexcept {
|
||||||
auto &bucket = GetBucket(key);
|
auto &bucket = GetBucket(key);
|
||||||
std::size_t n = bucket.remove_and_dispose_if([this, &key](const auto &item){
|
std::size_t n = bucket.remove_and_dispose_if([this, &key](const auto &item){
|
||||||
return ops.equal(key, item);
|
return ops.equal(key, ops.get_key(item));
|
||||||
}, disposer);
|
}, disposer);
|
||||||
counter -= n;
|
counter -= n;
|
||||||
return n;
|
return n;
|
||||||
|
@ -225,7 +233,7 @@ public:
|
||||||
Disposer<value_type> auto disposer) noexcept {
|
Disposer<value_type> auto disposer) noexcept {
|
||||||
auto &bucket = GetBucket(key);
|
auto &bucket = GetBucket(key);
|
||||||
std::size_t n = bucket.remove_and_dispose_if([this, &key, &pred](const auto &item){
|
std::size_t n = bucket.remove_and_dispose_if([this, &key, &pred](const auto &item){
|
||||||
return ops.equal(key, item) && pred(item);
|
return ops.equal(key, ops.get_key(item)) && pred(item);
|
||||||
}, disposer);
|
}, disposer);
|
||||||
counter -= n;
|
counter -= n;
|
||||||
return n;
|
return n;
|
||||||
|
@ -247,7 +255,7 @@ public:
|
||||||
constexpr std::pair<bucket_iterator, bool> insert_check(const auto &key) noexcept {
|
constexpr std::pair<bucket_iterator, bool> insert_check(const auto &key) noexcept {
|
||||||
auto &bucket = GetBucket(key);
|
auto &bucket = GetBucket(key);
|
||||||
for (auto &i : bucket)
|
for (auto &i : bucket)
|
||||||
if (ops.equal(key, i))
|
if (ops.equal(key, ops.get_key(i)))
|
||||||
return {bucket.iterator_to(i), false};
|
return {bucket.iterator_to(i), false};
|
||||||
|
|
||||||
/* bucket.end() is a pointer to the bucket's list
|
/* bucket.end() is a pointer to the bucket's list
|
||||||
|
@ -267,7 +275,7 @@ public:
|
||||||
|
|
||||||
/* using insert_after() so the new item gets inserted
|
/* using insert_after() so the new item gets inserted
|
||||||
at the front of the bucket list */
|
at the front of the bucket list */
|
||||||
GetBucket(item).insert_after(bucket, item);
|
GetBucket(ops.get_key(item)).insert_after(bucket, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -276,12 +284,12 @@ public:
|
||||||
*/
|
*/
|
||||||
constexpr void insert(reference item) noexcept {
|
constexpr void insert(reference item) noexcept {
|
||||||
++counter;
|
++counter;
|
||||||
GetBucket(item).push_front(item);
|
GetBucket(ops.get_key(item)).push_front(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bucket_iterator erase(bucket_iterator i) noexcept {
|
constexpr bucket_iterator erase(bucket_iterator i) noexcept {
|
||||||
--counter;
|
--counter;
|
||||||
return GetBucket(*i).erase(i);
|
return GetBucket(ops.get_key(*i)).erase(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bucket_iterator erase_and_dispose(bucket_iterator i,
|
constexpr bucket_iterator erase_and_dispose(bucket_iterator i,
|
||||||
|
@ -295,7 +303,7 @@ public:
|
||||||
constexpr bucket_iterator find(const auto &key) noexcept {
|
constexpr bucket_iterator find(const auto &key) noexcept {
|
||||||
auto &bucket = GetBucket(key);
|
auto &bucket = GetBucket(key);
|
||||||
for (auto &i : bucket)
|
for (auto &i : bucket)
|
||||||
if (ops.equal(key, i))
|
if (ops.equal(key, ops.get_key(i)))
|
||||||
return bucket.iterator_to(i);
|
return bucket.iterator_to(i);
|
||||||
|
|
||||||
return end();
|
return end();
|
||||||
|
@ -305,7 +313,7 @@ public:
|
||||||
constexpr const_bucket_iterator find(const auto &key) const noexcept {
|
constexpr const_bucket_iterator find(const auto &key) const noexcept {
|
||||||
auto &bucket = GetBucket(key);
|
auto &bucket = GetBucket(key);
|
||||||
for (auto &i : bucket)
|
for (auto &i : bucket)
|
||||||
if (ops.equal(key, i))
|
if (ops.equal(key, ops.get_key(i)))
|
||||||
return bucket.iterator_to(i);
|
return bucket.iterator_to(i);
|
||||||
|
|
||||||
return end();
|
return end();
|
||||||
|
@ -322,7 +330,7 @@ public:
|
||||||
std::predicate<const_reference> auto pred) noexcept {
|
std::predicate<const_reference> auto pred) noexcept {
|
||||||
auto &bucket = GetBucket(key);
|
auto &bucket = GetBucket(key);
|
||||||
for (auto &i : bucket)
|
for (auto &i : bucket)
|
||||||
if (ops.equal(key, i) && pred(i))
|
if (ops.equal(key, ops.get_key(i)) && pred(i))
|
||||||
return bucket.iterator_to(i);
|
return bucket.iterator_to(i);
|
||||||
|
|
||||||
return end();
|
return end();
|
||||||
|
@ -349,7 +357,7 @@ public:
|
||||||
auto &bucket = GetBucket(key);
|
auto &bucket = GetBucket(key);
|
||||||
|
|
||||||
for (auto i = bucket.begin(), e = bucket.end(); i != e;) {
|
for (auto i = bucket.begin(), e = bucket.end(); i != e;) {
|
||||||
if (!ops.equal(key, *i))
|
if (!ops.equal(key, ops.get_key(*i)))
|
||||||
++i;
|
++i;
|
||||||
else if (expired_pred(*i))
|
else if (expired_pred(*i))
|
||||||
i = erase_and_dispose(i, disposer);
|
i = erase_and_dispose(i, disposer);
|
||||||
|
|
Loading…
Reference in New Issue