diff --git a/src/RemoteTagCache.hxx b/src/RemoteTagCache.hxx index 9774d3382..5295f46d9 100644 --- a/src/RemoteTagCache.hxx +++ b/src/RemoteTagCache.hxx @@ -100,11 +100,10 @@ class RemoteTagCache final { */ ItemList invoke_list; - using KeyMap = IntrusiveHashSet, - true>; - - KeyMap map; + IntrusiveHashSet, + IntrusiveHashSetBaseHookTraits, + true> map; public: RemoteTagCache(EventLoop &event_loop, diff --git a/src/input/cache/Manager.hxx b/src/input/cache/Manager.hxx index f487a1420..26cba09af 100644 --- a/src/input/cache/Manager.hxx +++ b/src/input/cache/Manager.hxx @@ -48,10 +48,8 @@ class InputCacheManager { IntrusiveList items_by_time; - using UriMap = - IntrusiveHashSet; - - UriMap items_by_uri; + IntrusiveHashSet> items_by_uri; public: explicit InputCacheManager(const InputCacheConfig &config) noexcept; diff --git a/src/util/IntrusiveHashSet.hxx b/src/util/IntrusiveHashSet.hxx index 4f4d2f5fb..ab2f433d5 100644 --- a/src/util/IntrusiveHashSet.hxx +++ b/src/util/IntrusiveHashSet.hxx @@ -75,13 +75,28 @@ struct IntrusiveHashSetMemberHookTraits { } }; +template +struct IntrusiveHashSetOperators { + using hasher = Hash; + using key_equal = Equal; + + [[no_unique_address]] + Hash hash; + + [[no_unique_address]] + Equal equal; +}; + /** * A hash table implementation which stores pointers to items which * have an embedded #IntrusiveHashSetHook. The actual table is * embedded with a compile-time fixed size in this object. + * + * @param Operators a class which contains functions `hash` and + * `equal` */ template, bool constant_time_size=false> class IntrusiveHashSet { @@ -89,10 +104,7 @@ class IntrusiveHashSet { OptionalCounter counter; [[no_unique_address]] - Hash hash; - - [[no_unique_address]] - Equal equal; + Operators ops; struct BucketHookTraits { template @@ -129,20 +141,20 @@ public: using const_pointer = const T *; using size_type = std::size_t; - using hasher = Hash; - using key_equal = Equal; + using hasher = typename Operators::hasher; + using key_equal = typename Operators::key_equal; [[nodiscard]] IntrusiveHashSet() noexcept = default; [[nodiscard]] constexpr const hasher &hash_function() const noexcept { - return hash; + return ops.hash; } [[nodiscard]] constexpr const key_equal &key_eq() const noexcept { - return equal; + return ops.equal; } [[nodiscard]] @@ -192,7 +204,7 @@ public: Disposer auto disposer) noexcept { auto &bucket = GetBucket(key); counter -= bucket.remove_and_dispose_if([this, &key](const auto &item){ - return equal(key, item); + return ops.equal(key, item); }, disposer); } @@ -201,7 +213,7 @@ public: Disposer auto disposer) noexcept { auto &bucket = GetBucket(key); counter -= bucket.remove_and_dispose_if([this, &key, &pred](const auto &item){ - return equal(key, item) && pred(item); + return ops.equal(key, item) && pred(item); }, disposer); } @@ -221,7 +233,7 @@ public: constexpr std::pair insert_check(const auto &key) noexcept { auto &bucket = GetBucket(key); for (auto &i : bucket) - if (equal(key, i)) + if (ops.equal(key, i)) return {bucket.iterator_to(i), false}; /* bucket.end() is a pointer to the bucket's list @@ -269,7 +281,7 @@ public: constexpr bucket_iterator find(const auto &key) noexcept { auto &bucket = GetBucket(key); for (auto &i : bucket) - if (equal(key, i)) + if (ops.equal(key, i)) return bucket.iterator_to(i); return end(); @@ -279,7 +291,7 @@ public: constexpr const_bucket_iterator find(const auto &key) const noexcept { auto &bucket = GetBucket(key); for (auto &i : bucket) - if (equal(key, i)) + if (ops.equal(key, i)) return bucket.iterator_to(i); return end(); @@ -296,7 +308,7 @@ public: std::predicate auto pred) noexcept { auto &bucket = GetBucket(key); for (auto &i : bucket) - if (equal(key, i) && pred(i)) + if (ops.equal(key, i) && pred(i)) return bucket.iterator_to(i); return end(); @@ -323,7 +335,7 @@ public: auto &bucket = GetBucket(key); for (auto i = bucket.begin(), e = bucket.end(); i != e;) { - if (!equal(key, *i)) + if (!ops.equal(key, *i)) ++i; else if (expired_pred(*i)) i = erase_and_dispose(i, disposer); @@ -361,7 +373,7 @@ private: [[gnu::pure]] [[nodiscard]] constexpr auto &GetBucket(K &&key) noexcept { - const auto h = hash(std::forward(key)); + const auto h = ops.hash(std::forward(key)); return table[h % table_size]; } @@ -369,7 +381,7 @@ private: [[gnu::pure]] [[nodiscard]] constexpr const auto &GetBucket(K &&key) const noexcept { - const auto h = hash(std::forward(key)); + const auto h = ops.hash(std::forward(key)); return table[h % table_size]; } }; diff --git a/test/util/TestIntrusiveHashSet.cxx b/test/util/TestIntrusiveHashSet.cxx index bb3b2fc7e..8a66d651a 100644 --- a/test/util/TestIntrusiveHashSet.cxx +++ b/test/util/TestIntrusiveHashSet.cxx @@ -38,7 +38,9 @@ TEST(IntrusiveHashSet, Basic) { IntItem a{1}, b{2}, c{3}, d{4}, e{5}, f{1}; - IntrusiveHashSet set; + IntrusiveHashSet> set; { auto [position, inserted] = set.insert_check(2);