Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: add callbacks to alerts (should I continue?) #7557

Open
wants to merge 3 commits into
base: RC_2_0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions include/libtorrent/alert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Copyright (c) 2003, Daniel Wallin
Copyright (c) 2004-2005, 2008-2009, 2013-2020, 2022, Arvid Norberg
Copyright (c) 2004, Magnus Jonsson
Copyright (c) 2016, Alden Torres
Copyright (c) 2023, Joris Carrier
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -37,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_ALERT_HPP_INCLUDED

#include <string>
#include <functional>

// OVERVIEW
//
Expand Down Expand Up @@ -186,6 +188,24 @@ namespace alert_category {

#include "libtorrent/aux_/disable_deprecation_warnings_push.hpp"

template<typename T>
struct TORRENT_EXPORT callback_t {
using type = std::function<void(const T*)>;

callback_t(type func) : m_callback(std::move(func)) {}

bool has_callback() const {
return static_cast<bool>(m_callback);
}

void callback() const {
m_callback(static_cast<const T*>(this));
}

private:
type m_callback;
};

// The ``alert`` class is the base class that specific messages are derived from.
// alert types are not copyable, and cannot be constructed by the client. The
// pointers returned by libtorrent are short lived (the details are described
Expand Down
11 changes: 6 additions & 5 deletions include/libtorrent/alert_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,13 @@ TORRENT_VERSION_NAMESPACE_3
// number of bytes that was read.
//
// If the operation fails, ``error`` will indicate what went wrong.
struct TORRENT_EXPORT read_piece_alert final : torrent_alert
struct TORRENT_EXPORT read_piece_alert final : torrent_alert, callback_t<read_piece_alert>
{
// internal
TORRENT_UNEXPORT read_piece_alert(aux::stack_allocator& alloc, torrent_handle const& h
, piece_index_t p, boost::shared_array<char> d, int s);
, piece_index_t p, boost::shared_array<char> d, int s, callback_t<read_piece_alert>::type callback = {});
TORRENT_UNEXPORT read_piece_alert(aux::stack_allocator& alloc, torrent_handle h
, piece_index_t p, error_code e);
, piece_index_t p, error_code e, callback_t<read_piece_alert>::type callback = {});

TORRENT_DEFINE_ALERT_PRIO(read_piece_alert, 5, alert_priority::critical)

Expand Down Expand Up @@ -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)

Expand Down
21 changes: 20 additions & 1 deletion include/libtorrent/aux_/alert_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Copyright (c) 2003-2013, Daniel Wallin
Copyright (c) 2013, 2015-2020, Arvid Norberg
Copyright (c) 2016, 2018, 2020, Alden Torres
Copyright (c) 2023, Joris Carrier
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -48,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <condition_variable>
#include <atomic>
#include <bitset>
#include <type_traits> // for std::is_base_of

#ifndef TORRENT_DISABLE_EXTENSIONS
#include "libtorrent/extensions.hpp"
Expand All @@ -58,6 +60,16 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent {
namespace aux {

template<typename T>
void handle_alert_callback_impl(const T& a, std::true_type) {
if (a.has_callback()) a.callback();
}

template<typename T>
void handle_alert_callback_impl(const T&, std::false_type) {
// Do nothing if alert is not derivied from callback_t
}

struct TORRENT_EXTRA_EXPORT alert_manager
{
explicit alert_manager(int queue_limit
Expand All @@ -68,6 +80,13 @@ namespace aux {

~alert_manager();

template<typename T>
void handle_alert(T& a) {
handle_alert_callback_impl(a, std::is_base_of<callback_t<T>, T>());

maybe_notify(&a);
}

template <class T, typename... Args>
void emplace_alert(Args&&... args) try
{
Expand All @@ -88,7 +107,7 @@ namespace aux {
T& alert = queue.emplace_back<T>(
m_allocations[m_generation], std::forward<Args>(args)...);

maybe_notify(&alert);
handle_alert(alert);
}
catch (std::bad_alloc const&)
{
Expand Down
8 changes: 5 additions & 3 deletions include/libtorrent/torrent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Copyright (c) 2018, d-komarov
Copyright (c) 2019, ghbplayer
Copyright (c) 2020, Paul-Louis Ageneau
Copyright (c) 2021, AdvenT
Copyright (c) 2023, Joris Carrier
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -485,8 +486,9 @@ namespace libtorrent {
int blocks_left;
bool fail;
error_code error;
callback_t<read_piece_alert>::type callback;
};
void read_piece(piece_index_t);
void read_piece(piece_index_t, callback_t<read_piece_alert>::type callback = {});
void on_disk_read_complete(disk_buffer_holder, storage_error const&
, peer_request const&, std::shared_ptr<read_piece_struct>);

Expand Down Expand Up @@ -563,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();

Expand Down Expand Up @@ -1307,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
Expand Down
6 changes: 4 additions & 2 deletions include/libtorrent/torrent_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Copyright (c) 2017, 2020, AllSeeingEyeTolledEweSew
Copyright (c) 2017, Falcosc
Copyright (c) 2019, Andrei Kurushin
Copyright (c) 2019, ghbplayer
Copyright (c) 2023, Joris Carrier
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -69,6 +70,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/pex_flags.hpp"
#include "libtorrent/client_data.hpp"
#include "libtorrent/address.hpp" // for address_v4 and address_v6
#include "libtorrent/alert.hpp" // for callback_t

namespace libtorrent {
namespace aux {
Expand Down Expand Up @@ -309,7 +311,7 @@ namespace aux {
//
// Note that if you read multiple pieces, the read operations are not
// guaranteed to finish in the same order as you initiated them.
void read_piece(piece_index_t piece) const;
void read_piece(piece_index_t piece, callback_t<read_piece_alert>::type callback = {}) const;

// Returns true if this piece has been completely downloaded and written
// to disk, and false otherwise.
Expand Down Expand Up @@ -658,7 +660,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
Expand Down
13 changes: 9 additions & 4 deletions src/alert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,16 +200,20 @@ namespace libtorrent {

read_piece_alert::read_piece_alert(aux::stack_allocator& alloc
, torrent_handle const& h
, piece_index_t p, boost::shared_array<char> d, int s)
, piece_index_t p, boost::shared_array<char> d, int s
, callback_t<read_piece_alert>::type c)
: torrent_alert(alloc, h)
, callback_t<read_piece_alert>(std::move(c))
, buffer(std::move(d))
, piece(p)
, size(s)
{}

read_piece_alert::read_piece_alert(aux::stack_allocator& alloc
, torrent_handle h, piece_index_t p, error_code e)
, torrent_handle h, piece_index_t p, error_code e
, callback_t<read_piece_alert>::type c)
: torrent_alert(alloc, h)
, callback_t<read_piece_alert>(std::move(c))
, error(e)
, piece(p)
, size(0)
Expand Down Expand Up @@ -1561,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
Expand Down
25 changes: 13 additions & 12 deletions src/torrent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Copyright (c) 2018, airium
Copyright (c) 2018, d-komarov
Copyright (c) 2020, Paul-Louis Ageneau
Copyright (c) 2021, AdvenT
Copyright (c) 2021, Joris CARRIER
Copyright (c) 2021, 2023 Joris CARRIER
Copyright (c) 2021, thrnz
All rights reserved.

Expand Down Expand Up @@ -743,7 +743,7 @@ bool is_downloading_state(int const st)
m_ses.close_connection(p);
}

void torrent::read_piece(piece_index_t const piece)
void torrent::read_piece(piece_index_t const piece, callback_t<read_piece_alert>::type callback)
{
error_code ec;
if (m_abort || m_deleted)
Expand All @@ -761,7 +761,7 @@ bool is_downloading_state(int const st)

if (ec)
{
m_ses.alerts().emplace_alert<read_piece_alert>(get_handle(), piece, ec);
m_ses.alerts().emplace_alert<read_piece_alert>(get_handle(), piece, ec, callback);
return;
}

Expand All @@ -776,7 +776,7 @@ bool is_downloading_state(int const st)
// this shouldn't actually happen
boost::shared_array<char> buf;
m_ses.alerts().emplace_alert<read_piece_alert>(
get_handle(), piece, buf, 0);
get_handle(), piece, buf, 0, callback);
return;
}

Expand All @@ -785,11 +785,12 @@ bool is_downloading_state(int const st)
if (!rp->piece_data)
{
m_ses.alerts().emplace_alert<read_piece_alert>(
get_handle(), piece, error_code(boost::system::errc::not_enough_memory, generic_category()));
get_handle(), piece, error_code(boost::system::errc::not_enough_memory, generic_category()), callback);
return;
}
rp->blocks_left = blocks_in_piece;
rp->fail = false;
rp->callback = callback;

disk_job_flags_t flags{};
auto const read_mode = settings().get_int(settings_pack::disk_io_read_mode);
Expand Down Expand Up @@ -1216,12 +1217,12 @@ bool is_downloading_state(int const st)
if (rp->fail)
{
m_ses.alerts().emplace_alert<read_piece_alert>(
get_handle(), r.piece, rp->error);
get_handle(), r.piece, rp->error, rp->callback);
}
else
{
m_ses.alerts().emplace_alert<read_piece_alert>(
get_handle(), r.piece, rp->piece_data, size);
get_handle(), r.piece, rp->piece_data, size, rp->callback);
}
}
}
Expand Down Expand Up @@ -8397,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();
}

Expand Down Expand Up @@ -9462,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());

Expand All @@ -9473,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(); }

Expand Down
11 changes: 6 additions & 5 deletions src/torrent_handle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Copyright (c) 2017, Falcosc
Copyright (c) 2018, Steven Siloti
Copyright (c) 2019, Andrei Kurushin
Copyright (c) 2019, ghbplayer
Copyright (c) 2023, Joris Carrier
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -356,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(
Expand Down Expand Up @@ -742,9 +743,9 @@ namespace libtorrent {
async_call(&torrent::add_piece_async, piece, std::move(data), flags);
}

void torrent_handle::read_piece(piece_index_t piece) const
void torrent_handle::read_piece(piece_index_t piece, callback_t<read_piece_alert>::type callback) const
{
async_call(&torrent::read_piece, piece);
async_call(&torrent::read_piece, piece, callback);
}

bool torrent_handle::have_piece(piece_index_t piece) const
Expand Down Expand Up @@ -926,7 +927,7 @@ namespace libtorrent {
#else
TORRENT_UNUSED(deadline);
if (flags & alert_when_available)
async_call(&torrent::read_piece, index);
async_call(&torrent::read_piece, index, callback_t<read_piece_alert>::type{});
#endif
}

Expand Down
Loading