From 76e4ff49d952cb9479efb7884ff7b873ddfb08bb Mon Sep 17 00:00:00 2001
From: Joris CARRIER <joris@carrier.casa>
Date: Fri, 17 Nov 2023 11:06:10 +0100
Subject: [PATCH] Implemented cache flushed callbacks in torrent handling.

---
 include/libtorrent/alert_types.hpp    |  5 +++--
 include/libtorrent/torrent.hpp        |  4 ++--
 include/libtorrent/torrent_handle.hpp |  3 ++-
 src/alert.cpp                         |  5 +++--
 src/torrent.cpp                       | 10 +++++-----
 src/torrent_handle.cpp                |  4 ++--
 6 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp
index ae1fa5d1b17..945d76fee62 100644
--- a/include/libtorrent/alert_types.hpp
+++ b/include/libtorrent/alert_types.hpp
@@ -1888,10 +1888,11 @@ TORRENT_VERSION_NAMESPACE_3
 	// enabled to let this alert through. The alert is also posted when removing
 	// a torrent from the session, once the outstanding cache flush is complete
 	// and the torrent does no longer have any files open.
-	struct TORRENT_EXPORT cache_flushed_alert final : torrent_alert
+	struct TORRENT_EXPORT cache_flushed_alert final : torrent_alert, callback_t<cache_flushed_alert>
 	{
 		// internal
-		TORRENT_UNEXPORT cache_flushed_alert(aux::stack_allocator& alloc, torrent_handle const& h);
+		TORRENT_UNEXPORT cache_flushed_alert(aux::stack_allocator& alloc,
+			torrent_handle const& h, callback_t<cache_flushed_alert>::type callback = {});
 
 		TORRENT_DEFINE_ALERT_PRIO(cache_flushed_alert, 58, alert_priority::high)
 
diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp
index cc523de0fd1..9a74ecfed6d 100644
--- a/include/libtorrent/torrent.hpp
+++ b/include/libtorrent/torrent.hpp
@@ -565,7 +565,7 @@ namespace libtorrent {
 		bool has_error() const { return !!m_error; }
 		error_code error() const { return m_error; }
 
-		void flush_cache();
+		void flush_cache(callback_t<cache_flushed_alert>::type callback = {});
 		void pause(pause_flags_t flags = {});
 		void resume();
 
@@ -1309,7 +1309,7 @@ namespace libtorrent {
 		void on_file_renamed(std::string const& filename
 			, file_index_t file_idx
 			, storage_error const& error);
-		void on_cache_flushed(bool manually_triggered);
+		void on_cache_flushed(bool manually_triggered, callback_t<cache_flushed_alert>::type callback = {});
 
 		// this is used when a torrent is being removed.It synchronizes with the
 		// disk thread
diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp
index 984a8f5c508..85942aa7d36 100644
--- a/include/libtorrent/torrent_handle.hpp
+++ b/include/libtorrent/torrent_handle.hpp
@@ -88,6 +88,7 @@ namespace aux {
 #endif
 
 	struct read_piece_alert;
+	struct cache_flushed_alert;
 
 	using status_flags_t = flags::bitfield_flag<std::uint32_t, struct status_flags_tag>;
 	using add_piece_flags_t = flags::bitfield_flag<std::uint8_t, struct add_piece_flags_tag>;
@@ -662,7 +663,7 @@ namespace aux {
 		// more data for the torrent, but you are guaranteed that whatever cached
 		// data libtorrent had by the time you called
 		// ``torrent_handle::flush_cache()`` has been written to disk.
-		void flush_cache() const;
+		void flush_cache(callback_t<cache_flushed_alert>::type callback = {}) const;
 
 		// ``force_recheck`` puts the torrent back in a state where it assumes to
 		// have no resume data. All peers will be disconnected and the torrent
diff --git a/src/alert.cpp b/src/alert.cpp
index f28d9da6fe5..1eff12144c4 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -1565,8 +1565,9 @@ namespace {
 #endif // TORRENT_ABI_VERSION
 
 	cache_flushed_alert::cache_flushed_alert(aux::stack_allocator& alloc
-		, torrent_handle const& h)
-		: torrent_alert(alloc, h) {}
+		, torrent_handle const& h, callback_t<cache_flushed_alert>::type c)
+		: torrent_alert(alloc, h)
+		, callback_t<cache_flushed_alert>(std::move(c)) {}
 
 #if TORRENT_ABI_VERSION == 1
 	anonymous_mode_alert::anonymous_mode_alert(aux::stack_allocator& alloc
diff --git a/src/torrent.cpp b/src/torrent.cpp
index ddaa533abac..2193362f64a 100644
--- a/src/torrent.cpp
+++ b/src/torrent.cpp
@@ -8398,7 +8398,7 @@ namespace {
 		{
 			// we need to keep the object alive during this operation
 			m_ses.disk_thread().async_release_files(m_storage
-				, std::bind(&torrent::on_cache_flushed, shared_from_this(), false));
+				, std::bind(&torrent::on_cache_flushed, shared_from_this(), false, nullptr));
 			m_ses.deferred_submit_jobs();
 		}
 
@@ -9463,7 +9463,7 @@ namespace {
 			&& !m_session_paused;
 	}
 
-	void torrent::flush_cache()
+	void torrent::flush_cache(callback_t<cache_flushed_alert>::type callback)
 	{
 		TORRENT_ASSERT(is_single_thread());
 
@@ -9474,18 +9474,18 @@ namespace {
 			return;
 		}
 		m_ses.disk_thread().async_release_files(m_storage
-			, std::bind(&torrent::on_cache_flushed, shared_from_this(), true));
+			, std::bind(&torrent::on_cache_flushed, shared_from_this(), true, callback));
 		m_ses.deferred_submit_jobs();
 	}
 
-	void torrent::on_cache_flushed(bool const manually_triggered) try
+	void torrent::on_cache_flushed(bool const manually_triggered, callback_t<cache_flushed_alert>::type callback) try
 	{
 		TORRENT_ASSERT(is_single_thread());
 
 		if (m_ses.is_aborted()) return;
 
 		if (manually_triggered || alerts().should_post<cache_flushed_alert>())
-			alerts().emplace_alert<cache_flushed_alert>(get_handle());
+			alerts().emplace_alert<cache_flushed_alert>(get_handle(), callback);
 	}
 	catch (...) { handle_exception(); }
 
diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp
index c6936ce67ce..a131907f479 100644
--- a/src/torrent_handle.cpp
+++ b/src/torrent_handle.cpp
@@ -357,9 +357,9 @@ namespace libtorrent {
 	{ async_call(&torrent::set_sequential_download, sd); }
 #endif
 
-	void torrent_handle::flush_cache() const
+	void torrent_handle::flush_cache(callback_t<cache_flushed_alert>::type callback) const
 	{
-		async_call(&torrent::flush_cache);
+		async_call(&torrent::flush_cache, callback);
 	}
 
 	void torrent_handle::set_ssl_certificate(