factor out handler allocator and reuse it for posting deferred peer removals on torrents

This commit is contained in:
arvidn 2017-11-10 09:50:45 +01:00 committed by Arvid Norberg
parent b88c193742
commit 254f813626
5 changed files with 48 additions and 35 deletions

View File

@ -83,7 +83,9 @@ namespace libtorrent { namespace aux {
Handler h, handler_storage<Size>& s, error_handler_interface& eh)
: handler(std::move(h))
, storage(s)
#ifndef BOOST_NO_EXCEPTIONS
, error_handler(eh)
#endif
{}
template <class... A>
@ -142,9 +144,20 @@ namespace libtorrent { namespace aux {
Handler handler;
handler_storage<Size>& storage;
#ifndef BOOST_NO_EXCEPTIONS
error_handler_interface& error_handler;
#endif
};
template <class Handler, size_t Size>
aux::allocating_handler<Handler, Size>
make_handler(Handler const& handler
, handler_storage<Size>& storage
, error_handler_interface& err_handler)
{
return aux::allocating_handler<Handler, Size>(
handler, storage, err_handler);
}
}
}

View File

@ -1168,24 +1168,6 @@ namespace aux {
// outstanding requests need to increase at the same pace to keep up.
bool m_slow_start:1;
template <class Handler>
aux::allocating_handler<Handler, TORRENT_READ_HANDLER_MAX_SIZE>
make_read_handler(Handler const& handler)
{
return aux::allocating_handler<Handler, TORRENT_READ_HANDLER_MAX_SIZE>(
handler, m_read_handler_storage, *this
);
}
template <class Handler>
aux::allocating_handler<Handler, TORRENT_WRITE_HANDLER_MAX_SIZE>
make_write_handler(Handler const& handler)
{
return aux::allocating_handler<Handler, TORRENT_WRITE_HANDLER_MAX_SIZE>(
handler, m_write_handler_storage, *this
);
}
#if TORRENT_USE_ASSERTS
public:
bool m_in_constructor = true;

View File

@ -72,6 +72,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/units.hpp"
#include "libtorrent/aux_/vector.hpp"
#include "libtorrent/aux_/deferred_handler.hpp"
#include "libtorrent/aux_/allocating_handler.hpp"
#ifdef TORRENT_USE_OPENSSL
// there is no forward declaration header for asio
@ -322,6 +323,7 @@ namespace libtorrent {
, private torrent_hot_members
, public request_callback
, public peer_class_set
, public aux::error_handler_interface
, public std::enable_shared_from_this<torrent>
{
public:
@ -652,7 +654,7 @@ namespace libtorrent {
// this will remove the peer and make sure all
// the pieces it had have their reference counter
// decreased in the piece_picker
void remove_peer(peer_connection* p);
void remove_peer(std::shared_ptr<peer_connection> p);
// cancel requests to this block from any peer we're
// connected to on this torrent
@ -1149,6 +1151,9 @@ namespace libtorrent {
private:
void on_exception(std::exception const& e) override;
void on_error(error_code const& ec) override;
// trigger deferred disconnection of peers
void on_remove_peers();
@ -1418,8 +1423,9 @@ namespace libtorrent {
queue_position_t m_sequence_number;
// used to post a message to defer disconnecting peers
std::vector<peer_connection*> m_peers_to_disconnect;
std::vector<std::shared_ptr<peer_connection>> m_peers_to_disconnect;
aux::deferred_handler m_deferred_disconnect;
aux::handler_storage<24> m_deferred_handler_storage;
// for torrents who have a bandwidth limit, this is != 0
// and refers to a peer_class in the session.

View File

@ -4329,7 +4329,7 @@ namespace libtorrent {
#if TORRENT_USE_INVARIANT_CHECKS
check_invariant();
#endif
t->remove_peer(this);
t->remove_peer(self());
// we need to do this here to maintain accurate accounting of number of
// unchoke slots. Ideally the updating of choked state and the
@ -5590,8 +5590,9 @@ namespace libtorrent {
m_socket_is_writing = true;
#endif
m_socket->async_write_some(vec, make_write_handler(std::bind(
&peer_connection::on_send_data, self(), _1, _2)));
m_socket->async_write_some(vec, make_handler(std::bind(
&peer_connection::on_send_data, self(), _1, _2)
, m_write_handler_storage, *this));
m_channel_state[upload_channel] |= peer_info::bw_network;
m_last_sent = aux::time_now();
@ -5675,8 +5676,9 @@ namespace libtorrent {
// utp sockets aren't thread safe...
ADD_OUTSTANDING_ASYNC("peer_connection::on_receive_data");
m_socket->async_read_some(
boost::asio::mutable_buffers_1(vec.data(), vec.size()), make_read_handler(
std::bind(&peer_connection::on_receive_data, self(), _1, _2)));
boost::asio::mutable_buffers_1(vec.data(), vec.size()), make_handler(
std::bind(&peer_connection::on_receive_data, self(), _1, _2)
, m_read_handler_storage, *this));
}
piece_block_progress peer_connection::downloading_piece_progress() const

View File

@ -5422,6 +5422,16 @@ namespace libtorrent {
#endif
void torrent::on_exception(std::exception const&)
{
set_error(errors::no_memory, torrent_status::error_file_none);
}
void torrent::on_error(error_code const& ec)
{
set_error(ec, torrent_status::error_file_none);
}
void torrent::remove_connection(peer_connection const* p)
{
TORRENT_ASSERT(m_iterating_connections == 0);
@ -5430,9 +5440,9 @@ namespace libtorrent {
m_connections.erase(i);
}
void torrent::remove_peer(peer_connection* p)
void torrent::remove_peer(std::shared_ptr<peer_connection> p)
{
TORRENT_ASSERT(p != nullptr);
TORRENT_ASSERT(p);
TORRENT_ASSERT(is_single_thread());
TORRENT_ASSERT(std::count(m_peers_to_disconnect.begin()
, m_peers_to_disconnect.end(), p) == 0);
@ -5452,18 +5462,18 @@ namespace libtorrent {
{
std::weak_ptr<torrent> weak_t = shared_from_this();
m_peers_to_disconnect.push_back(p);
m_deferred_disconnect.post(m_ses.get_io_service(), [=]()
m_deferred_disconnect.post(m_ses.get_io_service(), aux::make_handler([=]()
{
std::shared_ptr<torrent> t = weak_t.lock();
if (t) t->on_remove_peers();
});
}, m_deferred_handler_storage, *this));
}
else
{
// if the peer was inserted in m_connections but instructed to
// be removed from this torrent, just remove it from it, see
// attach_peer logic.
remove_connection(p);
remove_connection(p.get());
}
torrent_peer* pp = p->peer_info_struct();
@ -5530,15 +5540,15 @@ namespace libtorrent {
TORRENT_ASSERT(is_single_thread());
INVARIANT_CHECK;
std::vector<peer_connection*> peers;
std::vector<std::shared_ptr<peer_connection>> peers;
m_peers_to_disconnect.swap(peers);
for (auto p : peers)
{
TORRENT_ASSERT(p != nullptr);
TORRENT_ASSERT(p);
TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
remove_connection(p);
m_ses.close_connection(p);
remove_connection(p.get());
m_ses.close_connection(p.get());
}
if (m_graceful_pause_mode && m_connections.empty())
@ -6977,7 +6987,7 @@ namespace libtorrent {
// we have to do this here because from the peer's point of view
// it wasn't really attached to the torrent, but we do need
// to let peer_list know we're removing it
remove_peer(p);
remove_peer(p->self());
return false;
}
}