From 847ae7dd7c947eef2c00de972eabe8bc32f56f83 Mon Sep 17 00:00:00 2001 From: Max Kellermann <max.kellermann@gmail.com> Date: Mon, 11 Sep 2023 20:57:51 +0200 Subject: [PATCH] util/IntrusiveHashSet: add insert_check_if() --- src/util/IntrusiveHashSet.hxx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/util/IntrusiveHashSet.hxx b/src/util/IntrusiveHashSet.hxx index 07fe3ccaf..69603ab1c 100644 --- a/src/util/IntrusiveHashSet.hxx +++ b/src/util/IntrusiveHashSet.hxx @@ -276,6 +276,25 @@ public: return {bucket.end(), true}; } + /** + * Like insert_check(), but existing items are only considered + * conflicting if they match the given predicate. + */ + [[nodiscard]] [[gnu::pure]] + constexpr std::pair<bucket_iterator, bool> insert_check_if(const auto &key, + std::predicate<const_reference> auto pred) noexcept { + auto &bucket = GetBucket(key); + for (auto &i : bucket) + if (ops.equal(key, ops.get_key(i)) && pred(i)) + return {bucket.iterator_to(i), false}; + + /* bucket.end() is a pointer to the bucket's list + head, a stable value that is guaranteed to be still + valid when insert_commit() gets called + eventually */ + return {bucket.end(), true}; + } + /** * Finish the insertion if insert_check() has returned true. *