refactor: store BT peers with std::shared_ptr (#7837)

* refactor: use weak_from_this()

* refactor: store peers as shared_ptr
This commit is contained in:
Yat Ho
2025-11-23 06:14:10 +08:00
committed by GitHub
parent d044ec82b0
commit 444354e413
4 changed files with 44 additions and 43 deletions

View File

@@ -578,7 +578,7 @@ void tr_peerIo::write_bytes(void const* bytes, size_t n_bytes, bool is_piece_dat
outbuf_.commit_space(n_bytes); outbuf_.commit_space(n_bytes);
session_->queue_session_thread( session_->queue_session_thread(
[ptr = std::weak_ptr{ shared_from_this() }]() [ptr = weak_from_this()]()
{ {
if (auto io = ptr.lock(); io) if (auto io = ptr.lock(); io)
{ {

View File

@@ -372,7 +372,7 @@ constexpr struct
class tr_swarm class tr_swarm
{ {
public: public:
using Peers = std::vector<tr_peerMsgs*>; using Peers = std::vector<std::shared_ptr<tr_peerMsgs>>;
using Pool = small::map<tr_socket_address, std::shared_ptr<tr_peer_info>>; using Pool = small::map<tr_socket_address, std::shared_ptr<tr_peer_info>>;
class WishlistMediator final : public Wishlist::Mediator class WishlistMediator final : public Wishlist::Mediator
@@ -482,7 +482,7 @@ public:
return std::size(peers); return std::size(peers);
} }
void remove_peer(tr_peerMsgs* peer) void remove_peer(std::shared_ptr<tr_peerMsgs> const& peer)
{ {
auto const lock = unique_lock(); auto const lock = unique_lock();
@@ -499,15 +499,13 @@ public:
peers.erase(iter); peers.erase(iter);
TR_ASSERT(stats.peer_count == peerCount()); TR_ASSERT(stats.peer_count == peerCount());
} }
delete peer;
} }
void remove_all_peers() void remove_all_peers()
{ {
auto tmp = Peers{}; auto tmp = Peers{};
std::swap(tmp, peers); std::swap(tmp, peers);
for (auto* peer : tmp) for (auto const& peer : tmp)
{ {
remove_peer(peer); remove_peer(peer);
} }
@@ -760,9 +758,9 @@ private:
void cancel_all_requests_for_block(tr_block_index_t block, tr_peer const* no_notify) void cancel_all_requests_for_block(tr_block_index_t block, tr_peer const* no_notify)
{ {
for (auto* peer : peers) for (auto const& peer : peers)
{ {
maybe_send_cancel_request(peer, block, no_notify); maybe_send_cancel_request(peer.get(), block, no_notify);
} }
} }
@@ -781,7 +779,7 @@ private:
void on_torrent_done() void on_torrent_done()
{ {
std::for_each(std::begin(peers), std::end(peers), [](auto* const peer) { peer->set_interested(false); }); std::for_each(std::begin(peers), std::end(peers), [](auto const& peer) { peer->set_interested(false); });
wishlist.reset(); wishlist.reset();
} }
@@ -801,7 +799,7 @@ private:
{ {
bool piece_came_from_peers = false; bool piece_came_from_peers = false;
for (auto* const peer : peers) for (auto const& peer : peers)
{ {
// notify the peer that we now have this piece // notify the peer that we now have this piece
peer->on_piece_completed(piece); peer->on_piece_completed(piece);
@@ -837,9 +835,9 @@ private:
auto const byte_count = tor->piece_size(piece); auto const byte_count = tor->piece_size(piece);
for (auto* const peer : peers) for (auto const& peer : peers)
{ {
maybe_add_strike(peer); maybe_add_strike(peer.get());
} }
for (auto& webseed : webseeds) for (auto& webseed : webseeds)
@@ -855,7 +853,7 @@ private:
// the webseed list may have changed... // the webseed list may have changed...
rebuild_webseeds(); rebuild_webseeds();
for (auto* peer : peers) for (auto const& peer : peers)
{ {
peer->on_torrent_got_metainfo(); peer->on_torrent_got_metainfo();
} }
@@ -983,7 +981,7 @@ EXIT:
auto const it = std::find_if( auto const it = std::find_if(
std::begin(peers), std::begin(peers),
std::end(peers), std::end(peers),
[&info_that](tr_peerMsgs const* const peer) { return peer->peer_info == info_that; }); [&info_that](auto const& peer) { return peer->peer_info == info_that; });
TR_ASSERT(it != std::end(peers)); TR_ASSERT(it != std::end(peers));
(*it)->disconnect_soon(); (*it)->disconnect_soon();
@@ -1258,7 +1256,7 @@ private:
peer_info->set_blocklisted_dirty(); peer_info->set_blocklisted_dirty();
} }
for (auto* const peer : tor->swarm->peers) for (auto const& peer : tor->swarm->peers)
{ {
peer->peer_info->set_blocklisted_dirty(); peer->peer_info->set_blocklisted_dirty();
if (peer->peer_info->is_blocklisted(blocklists_)) if (peer->peer_info->is_blocklisted(blocklists_))
@@ -1345,9 +1343,9 @@ void create_bit_torrent_peer(
tr_swarm* swarm = tor.swarm; tr_swarm* swarm = tor.swarm;
auto* const auto const
msgs = tr_peerMsgs::create(tor, std::move(peer_info), std::move(io), peer_id, &tr_swarm::peer_callback_bt, swarm); msgs = tr_peerMsgs::create(tor, std::move(peer_info), std::move(io), peer_id, &tr_swarm::peer_callback_bt, swarm);
swarm->peers.push_back(msgs); swarm->peers.emplace_back(msgs);
++swarm->stats.peer_count; ++swarm->stats.peer_count;
++swarm->stats.peer_from_count[msgs->peer_info->from_first()]; ++swarm->stats.peer_from_count[msgs->peer_info->from_first()];
@@ -1657,7 +1655,7 @@ std::vector<tr_pex> tr_peerMgrGetPeers(tr_torrent const* tor, uint8_t address_ty
{ {
auto const& peers = s->peers; auto const& peers = s->peers;
infos.reserve(std::size(peers)); infos.reserve(std::size(peers));
for (auto const* peer : peers) for (auto const& peer : peers)
{ {
if (peer->socket_address().address().type == address_type) if (peer->socket_address().address().type == address_type)
{ {
@@ -1737,7 +1735,7 @@ int8_t tr_peerMgrPieceAvailability(tr_torrent const* tor, tr_piece_index_t piece
} }
auto const& peers = tor->swarm->peers; auto const& peers = tor->swarm->peers;
return std::count_if(std::begin(peers), std::end(peers), [piece](auto const* peer) { return peer->has_piece(piece); }); return std::count_if(std::begin(peers), std::end(peers), [piece](auto const& peer) { return peer->has_piece(piece); });
} }
void tr_peerMgrTorrentAvailability(tr_torrent const* tor, int8_t* tab, unsigned int n_tabs) void tr_peerMgrTorrentAvailability(tr_torrent const* tor, int8_t* tab, unsigned int n_tabs)
@@ -1794,7 +1792,7 @@ uint64_t tr_peerMgrGetDesiredAvailable(tr_torrent const* tor)
} }
auto available = tr_bitfield{ tor->piece_count() }; auto available = tr_bitfield{ tor->piece_count() };
for (auto const* const peer : swarm->peers) for (auto const& peer : swarm->peers)
{ {
available |= peer->has(); available |= peer->has();
} }
@@ -1952,7 +1950,7 @@ tr_peer_stat* tr_peerMgrPeerStats(tr_torrent const* tor, size_t* setme_count)
std::begin(peers), std::begin(peers),
std::end(peers), std::end(peers),
ret, ret,
[&now, &now_msec](auto const* peer) { return peer_stat_helpers::get_peer_stats(peer, now, now_msec); }); [&now, &now_msec](auto const& peer) { return peer_stat_helpers::get_peer_stats(peer.get(), now, now_msec); });
*setme_count = n; *setme_count = n;
return ret; return ret;
@@ -2009,9 +2007,9 @@ void updateInterest(tr_swarm* swarm)
piece_is_interesting[i] = tor->piece_is_wanted(i) && !tor->has_piece(i); piece_is_interesting[i] = tor->piece_is_wanted(i) && !tor->has_piece(i);
} }
for (auto* const peer : peers) for (auto const& peer : peers)
{ {
peer->set_interested(isPeerInteresting(tor, piece_is_interesting, peer)); peer->set_interested(isPeerInteresting(tor, piece_is_interesting, peer.get()));
} }
} }
} }
@@ -2113,7 +2111,7 @@ void rechokeUploads(tr_swarm* s, uint64_t const now)
/* sort the peers by preference and rate */ /* sort the peers by preference and rate */
auto salter = tr_salt_shaker{}; auto salter = tr_salt_shaker{};
for (auto* const peer : peers) for (auto const& peer : peers)
{ {
if (peer->peer_info->is_upload_only()) if (peer->peer_info->is_upload_only())
{ {
@@ -2125,11 +2123,11 @@ void rechokeUploads(tr_swarm* s, uint64_t const now)
/* choke everyone if we're not uploading */ /* choke everyone if we're not uploading */
peer->set_choke(true); peer->set_choke(true);
} }
else if (peer != s->optimistic) else if (peer.get() != s->optimistic)
{ {
choked.emplace_back( choked.emplace_back(
peer, peer.get(),
get_rate(s->tor, peer, now), get_rate(s->tor, peer.get(), now),
salter(), salter(),
peer->peer_is_interested(), peer->peer_is_interested(),
peer->peer_is_choked(), peer->peer_is_choked(),
@@ -2289,15 +2287,15 @@ auto constexpr MaxUploadIdleSecs = time_t{ 60 * 5 };
return false; return false;
} }
void close_peer(tr_peerMsgs* peer) void close_peer(std::shared_ptr<tr_peerMsgs> const& peer)
{ {
TR_ASSERT(peer != nullptr); TR_ASSERT(peer);
peer->swarm->remove_peer(peer); peer->swarm->remove_peer(peer);
} }
constexpr struct constexpr struct
{ {
[[nodiscard]] static int compare(tr_peerMsgs const* a, tr_peerMsgs const* b) // <=> [[nodiscard]] static int compare(std::shared_ptr<tr_peerMsgs> const& a, std::shared_ptr<tr_peerMsgs> const& b) // <=>
{ {
if (a->is_disconnecting() != b->is_disconnecting()) if (a->is_disconnecting() != b->is_disconnecting())
{ {
@@ -2312,18 +2310,19 @@ constexpr struct
return tr_compare_3way(a->swarm->tor->is_done(), b->swarm->tor->is_done()); return tr_compare_3way(a->swarm->tor->is_done(), b->swarm->tor->is_done());
} }
[[nodiscard]] bool operator()(tr_peerMsgs const* a, tr_peerMsgs const* b) const // less than [[nodiscard]] bool operator()(std::shared_ptr<tr_peerMsgs> const& a, std::shared_ptr<tr_peerMsgs> const& b)
const // less than
{ {
return compare(a, b) < 0; return compare(a, b) < 0;
} }
} ComparePeerByMostActive{}; } ComparePeerByMostActive{};
constexpr auto ComparePeerByLeastActive = [](tr_peerMsgs const* a, tr_peerMsgs const* b) constexpr auto ComparePeerByLeastActive = [](std::shared_ptr<tr_peerMsgs> const& a, std::shared_ptr<tr_peerMsgs> const& b)
{ {
return ComparePeerByMostActive(b, a); return ComparePeerByMostActive(b, a);
}; };
using bad_peers_t = small::vector<tr_peerMsgs*, 512U>; using bad_peers_t = small::vector<std::shared_ptr<tr_peerMsgs>, 512U>;
bad_peers_t& get_peers_to_close(tr_swarm const* const swarm, time_t const now_sec, bad_peers_t& bad_peers_buf) bad_peers_t& get_peers_to_close(tr_swarm const* const swarm, time_t const now_sec, bad_peers_t& bad_peers_buf)
{ {
@@ -2332,9 +2331,9 @@ bad_peers_t& get_peers_to_close(tr_swarm const* const swarm, time_t const now_se
bad_peers_buf.clear(); bad_peers_buf.clear();
bad_peers_buf.reserve(peer_count); bad_peers_buf.reserve(peer_count);
for (auto* peer : swarm->peers) for (auto const& peer : swarm->peers)
{ {
if (shouldPeerBeClosed(swarm, peer, peer_count, now_sec)) if (shouldPeerBeClosed(swarm, peer.get(), peer_count, now_sec))
{ {
bad_peers_buf.emplace_back(peer); bad_peers_buf.emplace_back(peer);
} }
@@ -2345,7 +2344,7 @@ bad_peers_t& get_peers_to_close(tr_swarm const* const swarm, time_t const now_se
void close_bad_peers(tr_swarm* s, time_t const now_sec, bad_peers_t& bad_peers_buf) void close_bad_peers(tr_swarm* s, time_t const now_sec, bad_peers_t& bad_peers_buf)
{ {
for (auto* peer : get_peers_to_close(s, now_sec, bad_peers_buf)) for (auto const& peer : get_peers_to_close(s, now_sec, bad_peers_buf))
{ {
tr_logAddTraceSwarm(peer->swarm, fmt::format("removing bad peer {}", peer->display_name())); tr_logAddTraceSwarm(peer->swarm, fmt::format("removing bad peer {}", peer->display_name()));
close_peer(peer); close_peer(peer);
@@ -2362,7 +2361,7 @@ void enforceSwarmPeerLimit(tr_swarm* swarm, size_t max)
} }
// close all but the `max` most active // close all but the `max` most active
auto peers = std::vector<tr_peerMsgs*>(n - max); auto peers = std::vector<std::shared_ptr<tr_peerMsgs>>(n - max);
std::partial_sort_copy( std::partial_sort_copy(
std::begin(swarm->peers), std::begin(swarm->peers),
std::end(swarm->peers), std::end(swarm->peers),
@@ -2382,7 +2381,7 @@ void enforceSessionPeerLimit(size_t global_peer_limit, tr_torrents& torrents)
} }
// make a list of all the peers // make a list of all the peers
auto peers = std::vector<tr_peerMsgs*>{}; auto peers = std::vector<std::shared_ptr<tr_peerMsgs>>{};
peers.reserve(current_size); peers.reserve(current_size);
for (auto const* const tor : torrents) for (auto const* const tor : torrents)
{ {
@@ -2535,7 +2534,7 @@ void pumpAllPeers(tr_peerMgr* mgr)
{ {
for (auto* const tor : mgr->torrents_) for (auto* const tor : mgr->torrents_)
{ {
for (auto* const peer : tor->swarm->peers) for (auto const& peer : tor->swarm->peers)
{ {
peer->pulse(); peer->pulse();
} }

View File

@@ -292,7 +292,9 @@ using ReadResult = std::pair<ReadState, size_t /*n_piece_data_bytes_read*/>;
* @see tr_peer * @see tr_peer
* @see tr_peer_info * @see tr_peer_info
*/ */
class tr_peerMsgsImpl final : public tr_peerMsgs class tr_peerMsgsImpl final
: public tr_peerMsgs
, public std::enable_shared_from_this<tr_peerMsgsImpl>
{ {
public: public:
tr_peerMsgsImpl( tr_peerMsgsImpl(
@@ -2168,7 +2170,7 @@ tr_peerMsgs::~tr_peerMsgs()
--n_peers; --n_peers;
} }
tr_peerMsgs* tr_peerMsgs::create( std::shared_ptr<tr_peerMsgs> tr_peerMsgs::create(
tr_torrent& torrent, tr_torrent& torrent,
std::shared_ptr<tr_peer_info> peer_info, std::shared_ptr<tr_peer_info> peer_info,
std::shared_ptr<tr_peerIo> io, std::shared_ptr<tr_peerIo> io,
@@ -2176,5 +2178,5 @@ tr_peerMsgs* tr_peerMsgs::create(
tr_peer_callback_bt callback, tr_peer_callback_bt callback,
void* callback_data) void* callback_data)
{ {
return new tr_peerMsgsImpl{ torrent, std::move(peer_info), std::move(io), peer_id, callback, callback_data }; return std::make_shared<tr_peerMsgsImpl>(torrent, std::move(peer_info), std::move(io), peer_id, callback, callback_data);
} }

View File

@@ -126,7 +126,7 @@ public:
virtual void on_piece_completed(tr_piece_index_t) = 0; virtual void on_piece_completed(tr_piece_index_t) = 0;
static tr_peerMsgs* create( static std::shared_ptr<tr_peerMsgs> create(
tr_torrent& torrent, tr_torrent& torrent,
std::shared_ptr<tr_peer_info> peer_info, std::shared_ptr<tr_peer_info> peer_info,
std::shared_ptr<tr_peerIo> io, std::shared_ptr<tr_peerIo> io,