From 5844242cfb6587c104e3268da9b8bbac7e929939 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max.kellermann@gmail.com>
Date: Mon, 23 Jan 2023 13:57:31 +0100
Subject: [PATCH] input/cache/Manager: use IntrusiveHashSet instead of
 boost::intrusive::set

---
 src/input/cache/Item.hxx    |  9 ++++-----
 src/input/cache/Manager.cxx | 35 +++++++++++++++++++++++------------
 src/input/cache/Manager.hxx | 24 ++++++++++++++----------
 src/input/cache/Stream.cxx  |  2 +-
 4 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/src/input/cache/Item.hxx b/src/input/cache/Item.hxx
index bff42b04a..cf707c8d2 100644
--- a/src/input/cache/Item.hxx
+++ b/src/input/cache/Item.hxx
@@ -23,8 +23,7 @@
 #include "input/BufferingInputStream.hxx"
 #include "thread/Mutex.hxx"
 #include "util/IntrusiveList.hxx"
-
-#include <boost/intrusive/set_hook.hpp>
+#include "util/IntrusiveHashSet.hxx"
 
 #include <string>
 
@@ -40,7 +39,7 @@ class InputCacheLease;
 class InputCacheItem final
 	: public BufferingInputStream,
 	  public AutoUnlinkIntrusiveListHook,
-	  public boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>
+	  public IntrusiveHashSetHook<>
 {
 	const std::string uri;
 
@@ -53,8 +52,8 @@ public:
 	explicit InputCacheItem(InputStreamPtr _input) noexcept;
 	~InputCacheItem() noexcept;
 
-	const char *GetUri() const noexcept {
-		return uri.c_str();
+	const std::string &GetUri() const noexcept {
+		return uri;
 	}
 
 	using BufferingInputStream::size;
diff --git a/src/input/cache/Manager.cxx b/src/input/cache/Manager.cxx
index 7caa8a4d6..ebc51fafc 100644
--- a/src/input/cache/Manager.cxx
+++ b/src/input/cache/Manager.cxx
@@ -27,25 +27,37 @@
 
 #include <string.h>
 
-inline bool
-InputCacheManager::ItemCompare::operator()(const InputCacheItem &a,
-					   const char *b) const noexcept
+inline std::size_t
+InputCacheManager::ItemHash::operator()(std::string_view uri) const noexcept
 {
-	return strcmp(a.GetUri(), b) < 0;
+	return std::hash<std::string_view>{}(uri);
+}
+
+inline std::size_t
+InputCacheManager::ItemHash::operator()(const InputCacheItem &item) const noexcept
+{
+	return std::hash<std::string_view>{}(item.GetUri());
 }
 
 inline bool
-InputCacheManager::ItemCompare::operator()(const char *a,
-					   const InputCacheItem &b) const noexcept
+InputCacheManager::ItemEqual::operator()(const InputCacheItem &a,
+					 std::string_view b) const noexcept
 {
-	return strcmp(a, b.GetUri()) < 0;
+	return a.GetUri() == b;
 }
 
 inline bool
-InputCacheManager::ItemCompare::operator()(const InputCacheItem &a,
-					   const InputCacheItem &b) const noexcept
+InputCacheManager::ItemEqual::operator()(std::string_view a,
+					 const InputCacheItem &b) const noexcept
 {
-	return strcmp(a.GetUri(), b.GetUri()) < 0;
+	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
@@ -97,8 +109,7 @@ InputCacheManager::Get(const char *uri, bool create)
 	if (!PathTraitsUTF8::IsAbsolute(uri))
 		return {};
 
-	auto iter = items_by_uri.find(uri, items_by_uri.key_comp());
-	if (iter != items_by_uri.end()) {
+	if (auto iter = items_by_uri.find(uri); iter != items_by_uri.end()) {
 		auto &item = *iter;
 
 		/* refresh */
diff --git a/src/input/cache/Manager.hxx b/src/input/cache/Manager.hxx
index 408354eb2..03c0f5042 100644
--- a/src/input/cache/Manager.hxx
+++ b/src/input/cache/Manager.hxx
@@ -21,10 +21,9 @@
 #define MPD_INPUT_CACHE_MANAGER_HXX
 
 #include "thread/Mutex.hxx"
+#include "util/IntrusiveHashSet.hxx"
 #include "util/IntrusiveList.hxx"
 
-#include <boost/intrusive/set.hpp>
-
 class InputStream;
 class InputCacheItem;
 class InputCacheLease;
@@ -41,13 +40,21 @@ class InputCacheManager {
 
 	size_t total_size = 0;
 
-	struct ItemCompare {
+	struct ItemHash {
 		[[gnu::pure]]
-		bool operator()(const InputCacheItem &a,
-				const char *b) const noexcept;
+		std::size_t operator()(std::string_view uri) const noexcept;
 
 		[[gnu::pure]]
-		bool operator()(const char *a,
+		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]]
@@ -58,10 +65,7 @@ class InputCacheManager {
 	IntrusiveList<InputCacheItem> items_by_time;
 
 	using UriMap =
-		boost::intrusive::set<InputCacheItem,
-				      boost::intrusive::base_hook<boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>>,
-				      boost::intrusive::compare<ItemCompare>,
-				      boost::intrusive::constant_time_size<false>>;
+		IntrusiveHashSet<InputCacheItem, 127, ItemHash, ItemEqual>;
 
 	UriMap items_by_uri;
 
diff --git a/src/input/cache/Stream.cxx b/src/input/cache/Stream.cxx
index 451232611..31a39875d 100644
--- a/src/input/cache/Stream.cxx
+++ b/src/input/cache/Stream.cxx
@@ -21,7 +21,7 @@
 
 CacheInputStream::CacheInputStream(InputCacheLease _lease,
 				   Mutex &_mutex) noexcept
-	:InputStream(_lease->GetUri(), _mutex),
+	:InputStream(_lease->GetUri().c_str(), _mutex),
 	 InputCacheLease(std::move(_lease))
 {
 	const auto &i = GetCacheItem();