From 6014ac1e7aff4d2ca8871b5c2dcbf21efdd54ca8 Mon Sep 17 00:00:00 2001 From: Daniel Wallin Date: Wed, 20 May 2009 08:57:08 +0000 Subject: [PATCH] Allocate memory for read/write handlers inplace inside peer_connection instance. --- include/libtorrent/config.hpp | 7 +++ include/libtorrent/peer_connection.hpp | 85 ++++++++++++++++++++++++++ src/peer_connection.cpp | 18 ++++-- 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/include/libtorrent/config.hpp b/include/libtorrent/config.hpp index f6f017ddc..dac9136f6 100644 --- a/include/libtorrent/config.hpp +++ b/include/libtorrent/config.hpp @@ -138,6 +138,13 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_USE_LOCALE_FILENAMES 0 #endif +#if !defined(TORRENT_READ_HANDLER_MAX_SIZE) +# define TORRENT_READ_HANDLER_MAX_SIZE 100 +#endif + +#if !defined(TORRENT_WRITE_HANDLER_MAX_SIZE) +# define TORRENT_WRITE_HANDLER_MAX_SIZE 100 +#endif #endif // TORRENT_CONFIG_HPP_INCLUDED diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index d9df58c0f..d87042e4e 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -985,6 +985,91 @@ namespace libtorrent // pick any pieces from this peer bool m_no_download:1; + template + struct handler_storage + { +#ifdef TORRENT_DEBUG + handler_storage() + : used(false) + {} + + bool used; +#endif + boost::aligned_storage bytes; + }; + + handler_storage m_read_handler_storage; + handler_storage m_write_handler_storage; + + template + struct allocating_handler + { + allocating_handler( + Handler const& handler, handler_storage& storage + ) + : handler(handler) + , storage(storage) + {} + + template + void operator()(A0 const& a0) const + { + handler(a0); + } + + template + void operator()(A0 const& a0, A1 const& a1) const + { + handler(a0, a1); + } + + template + void operator()(A0 const& a0, A1 const& a1, A2 const& a2) const + { + handler(a0, a1, a2); + } + + friend void* asio_handler_allocate( + std::size_t size, allocating_handler* ctx) + { + assert(size <= Size); +#ifdef TORRENT_DEBUG + assert(!ctx->storage.used); + ctx->storage.used = true; +#endif + return &ctx->storage.bytes; + } + + friend void asio_handler_deallocate( + void*, std::size_t, allocating_handler* ctx) + { +#ifdef TORRENT_DEBUG + ctx->storage.used = false; +#endif + } + + Handler handler; + handler_storage& storage; + }; + + template + allocating_handler + make_read_handler(Handler const& handler) + { + return allocating_handler( + handler, m_read_handler_storage + ); + } + + template + allocating_handler + make_write_handler(Handler const& handler) + { + return allocating_handler( + handler, m_write_handler_storage + ); + } + #ifdef TORRENT_DEBUG public: bool m_in_constructor:1; diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 664743567..271ef2b60 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -3680,7 +3680,9 @@ namespace libtorrent (*m_logger) << time_now_string() << " *** ASYNC_WRITE [ bytes: " << amount_to_send << " ]\n"; #endif std::list const& vec = m_send_buffer.build_iovec(amount_to_send); - m_socket->async_write_some(vec, bind(&peer_connection::on_send_data, self(), _1, _2)); + m_socket->async_write_some( + vec, make_write_handler(bind( + &peer_connection::on_send_data, self(), _1, _2))); m_channel_state[upload_channel] = peer_info::bw_network; } @@ -3763,7 +3765,10 @@ namespace libtorrent // only receive into regular buffer TORRENT_ASSERT(m_recv_pos + max_receive <= int(m_recv_buffer.size())); m_socket->async_read_some(asio::buffer(&m_recv_buffer[m_recv_pos] - , max_receive), bind(&peer_connection::on_receive_data, self(), _1, _2)); + , max_receive) + , make_read_handler( + bind(&peer_connection::on_receive_data, self(), _1, _2) + )); } else if (m_recv_pos >= regular_buffer_size) { @@ -3772,7 +3777,9 @@ namespace libtorrent TORRENT_ASSERT(m_recv_pos - regular_buffer_size + max_receive <= m_disk_recv_buffer_size); m_socket->async_read_some(asio::buffer(m_disk_recv_buffer.get() + m_recv_pos - regular_buffer_size , max_receive) - , bind(&peer_connection::on_receive_data, self(), _1, _2)); + , make_read_handler( + bind(&peer_connection::on_receive_data, self(), _1, _2) + )); } else { @@ -3787,8 +3794,9 @@ namespace libtorrent , regular_buffer_size - m_recv_pos); vec[1] = asio::buffer(m_disk_recv_buffer.get() , max_receive - regular_buffer_size + m_recv_pos); - m_socket->async_read_some(vec, bind(&peer_connection::on_receive_data - , self(), _1, _2)); + m_socket->async_read_some( + vec, make_read_handler( + bind(&peer_connection::on_receive_data, self(), _1, _2))); } m_channel_state[download_channel] = peer_info::bw_network; }