moved async-load-torrent feature out of disk-io-thread (#1282)

moved async-load-torrent feature out of disk-io-thread into a generic worker thread
This commit is contained in:
Arvid Norberg 2016-11-02 01:01:04 -04:00 committed by GitHub
parent 1c2a8fb96e
commit b61ebca14a
8 changed files with 68 additions and 56 deletions

View File

@ -449,7 +449,7 @@ namespace libtorrent
std::pair<std::shared_ptr<torrent>, bool> std::pair<std::shared_ptr<torrent>, bool>
add_torrent_impl(add_torrent_params& p, error_code& ec); add_torrent_impl(add_torrent_params& p, error_code& ec);
void async_add_torrent(add_torrent_params* params); void async_add_torrent(add_torrent_params* params);
void on_async_load_torrent(disk_io_job const* j); void on_async_load_torrent(add_torrent_params* params, error_code ec);
void remove_torrent(torrent_handle const& h, int options) override; void remove_torrent(torrent_handle const& h, int options) override;
void remove_torrent_impl(std::shared_ptr<torrent> tptr, int options) override; void remove_torrent_impl(std::shared_ptr<torrent> tptr, int options) override;
@ -1058,6 +1058,26 @@ namespace libtorrent
std::shared_ptr<upnp> m_upnp; std::shared_ptr<upnp> m_upnp;
std::shared_ptr<lsd> m_lsd; std::shared_ptr<lsd> m_lsd;
struct work_thread_t
{
work_thread_t()
: work(new boost::asio::io_service::work(ios))
, thread([&] { ios.run(); })
{}
~work_thread_t()
{
work.reset();
thread.join();
}
work_thread_t(work_thread_t const&) = delete;
work_thread_t& operator=(work_thread_t const&) = delete;
boost::asio::io_service ios;
std::unique_ptr<boost::asio::io_service::work> work;
std::thread thread;
};
std::unique_ptr<work_thread_t> m_torrent_load_thread;
// mask is a bitmask of which protocols to remap on: // mask is a bitmask of which protocols to remap on:
// 1: NAT-PMP // 1: NAT-PMP
// 2: UPnP // 2: UPnP

View File

@ -86,8 +86,6 @@ namespace libtorrent
virtual void async_set_file_priority(piece_manager* storage virtual void async_set_file_priority(piece_manager* storage
, std::vector<std::uint8_t> const& prio , std::vector<std::uint8_t> const& prio
, std::function<void(disk_io_job const*)> handler) = 0; , std::function<void(disk_io_job const*)> handler) = 0;
virtual void async_load_torrent(add_torrent_params* params
, std::function<void(disk_io_job const*)> handler) = 0;
virtual void async_tick_torrent(piece_manager* storage virtual void async_tick_torrent(piece_manager* storage
, std::function<void(disk_io_job const*)> handler) = 0; , std::function<void(disk_io_job const*)> handler) = 0;

View File

@ -95,7 +95,6 @@ namespace libtorrent
, flush_storage , flush_storage
, trim_cache , trim_cache
, file_priority , file_priority
, load_torrent
, clear_piece , clear_piece
, tick_storage , tick_storage
, resolve_links , resolve_links
@ -150,7 +149,6 @@ namespace libtorrent
char* string; char* string;
add_torrent_params const* check_resume_data; add_torrent_params const* check_resume_data;
std::vector<std::uint8_t>* priorities; std::vector<std::uint8_t>* priorities;
torrent_info* torrent_file;
int delete_options; int delete_options;
} buffer; } buffer;

View File

@ -324,8 +324,6 @@ namespace libtorrent
void async_set_file_priority(piece_manager* storage void async_set_file_priority(piece_manager* storage
, std::vector<std::uint8_t> const& prio , std::vector<std::uint8_t> const& prio
, std::function<void(disk_io_job const*)> handler) override; , std::function<void(disk_io_job const*)> handler) override;
void async_load_torrent(add_torrent_params* params
, std::function<void(disk_io_job const*)> handler) override;
void async_tick_torrent(piece_manager* storage void async_tick_torrent(piece_manager* storage
, std::function<void(disk_io_job const*)> handler) override; , std::function<void(disk_io_job const*)> handler) override;
@ -413,7 +411,6 @@ namespace libtorrent
int do_flush_storage(disk_io_job* j, jobqueue_t& completed_jobs); int do_flush_storage(disk_io_job* j, jobqueue_t& completed_jobs);
int do_trim_cache(disk_io_job* j, jobqueue_t& completed_jobs); int do_trim_cache(disk_io_job* j, jobqueue_t& completed_jobs);
int do_file_priority(disk_io_job* j, jobqueue_t& completed_jobs); int do_file_priority(disk_io_job* j, jobqueue_t& completed_jobs);
int do_load_torrent(disk_io_job* j, jobqueue_t& completed_jobs);
int do_clear_piece(disk_io_job* j, jobqueue_t& completed_jobs); int do_clear_piece(disk_io_job* j, jobqueue_t& completed_jobs);
int do_tick(disk_io_job* j, jobqueue_t& completed_jobs); int do_tick(disk_io_job* j, jobqueue_t& completed_jobs);
int do_resolve_links(disk_io_job* j, jobqueue_t& completed_jobs); int do_resolve_links(disk_io_job* j, jobqueue_t& completed_jobs);

View File

@ -204,7 +204,6 @@ const char* const job_action_name[] =
"flush_storage", "flush_storage",
"trim_cache", "trim_cache",
"set_file_priority", "set_file_priority",
"load_torrent",
"clear_piece", "clear_piece",
"tick_storage", "tick_storage",
"resolve_links" "resolve_links"

View File

@ -1032,7 +1032,6 @@ namespace libtorrent
&disk_io_thread::do_flush_storage, &disk_io_thread::do_flush_storage,
&disk_io_thread::do_trim_cache, &disk_io_thread::do_trim_cache,
&disk_io_thread::do_file_priority, &disk_io_thread::do_file_priority,
&disk_io_thread::do_load_torrent,
&disk_io_thread::do_clear_piece, &disk_io_thread::do_clear_piece,
&disk_io_thread::do_tick, &disk_io_thread::do_tick,
}; };
@ -1963,16 +1962,6 @@ namespace libtorrent
add_fence_job(storage, j); add_fence_job(storage, j);
} }
void disk_io_thread::async_load_torrent(add_torrent_params* params
, std::function<void(disk_io_job const*)> handler)
{
disk_io_job* j = allocate_job(disk_io_job::load_torrent);
j->requester = reinterpret_cast<void*>(params);
j->callback = std::move(handler);
add_job(j);
}
void disk_io_thread::async_tick_torrent(piece_manager* storage void disk_io_thread::async_tick_torrent(piece_manager* storage
, std::function<void(disk_io_job const*)> handler) , std::function<void(disk_io_job const*)> handler)
{ {
@ -2882,28 +2871,6 @@ namespace libtorrent
return 0; return 0;
} }
int disk_io_thread::do_load_torrent(disk_io_job* j, jobqueue_t& /* completed_jobs */ )
{
add_torrent_params* params = reinterpret_cast<add_torrent_params*>(j->requester);
std::string filename = resolve_file_url(params->url);
std::unique_ptr<torrent_info> t{new torrent_info(filename, j->error.ec)};
if (j->error.ec)
{
j->buffer.torrent_file = nullptr;
}
else
{
// do this to trigger parsing of the info-dict here. It's better
// than to have it be done in the network thread. It has enough to
// do as it is.
std::string cert = t->ssl_cert();
j->buffer.torrent_file = t.release();
}
return 0;
}
// this job won't return until all outstanding jobs on this // this job won't return until all outstanding jobs on this
// piece are completed or cancelled and the buffers for it // piece are completed or cancelled and the buffers for it
// have been evicted // have been evicted

View File

@ -4497,8 +4497,18 @@ namespace aux {
if (string_begins_no_case("file://", params->url.c_str()) && !params->ti) if (string_begins_no_case("file://", params->url.c_str()) && !params->ti)
{ {
m_disk_thread.async_load_torrent(params if (!m_torrent_load_thread)
, std::bind(&session_impl::on_async_load_torrent, this, _1)); m_torrent_load_thread.reset(new work_thread_t());
m_torrent_load_thread->ios.post([params, this]
{
std::unique_ptr<add_torrent_params> holder2(params);
error_code ec;
params->ti = std::make_shared<torrent_info>(resolve_file_url(params->url), ec);
this->m_io_service.post(std::bind(&session_impl::on_async_load_torrent
, this, params, ec));
holder2.release();
});
holder.release(); holder.release();
return; return;
} }
@ -4507,22 +4517,19 @@ namespace aux {
add_torrent(*params, ec); add_torrent(*params, ec);
} }
void session_impl::on_async_load_torrent(disk_io_job const* j) void session_impl::on_async_load_torrent(add_torrent_params* params, error_code ec)
{ {
add_torrent_params* params = reinterpret_cast<add_torrent_params*>(j->requester);
std::unique_ptr<add_torrent_params> holder(params); std::unique_ptr<add_torrent_params> holder(params);
if (j->error.ec) if (!ec)
{
add_torrent(*params, ec);
params->url.clear();
}
if (ec)
{ {
m_alerts.emplace_alert<add_torrent_alert>(torrent_handle() m_alerts.emplace_alert<add_torrent_alert>(torrent_handle()
, *params, j->error.ec); , *params, ec);
}
else
{
params->url.clear();
params->ti = std::shared_ptr<torrent_info>(j->buffer.torrent_file);
error_code ec;
add_torrent(*params, ec);
} }
} }

View File

@ -39,6 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/torrent.hpp" #include "libtorrent/torrent.hpp"
#include "libtorrent/peer_info.hpp" #include "libtorrent/peer_info.hpp"
#include "libtorrent/extensions.hpp" #include "libtorrent/extensions.hpp"
#include "libtorrent/file.hpp" // for combine_path, current_working_directory
#include "settings.hpp" #include "settings.hpp"
#include <tuple> #include <tuple>
#include <iostream> #include <iostream>
@ -411,3 +412,28 @@ TORRENT_TEST(rename_file)
TEST_EQUAL(info->files().file_path(0), "tmp1"); TEST_EQUAL(info->files().file_path(0), "tmp1");
} }
TORRENT_TEST(async_load)
{
settings_pack pack = settings();
lt::session ses(pack);
add_torrent_params p;
p.flags &= ~add_torrent_params::flag_paused;
p.flags &= ~add_torrent_params::flag_auto_managed;
std::string dir = parent_path(current_working_directory());
p.url = "file://" + combine_path(combine_path(dir, "test_torrents"), "base.torrent");
p.save_path = ".";
ses.async_add_torrent(p);
alert const* a = wait_for_alert(ses, add_torrent_alert::alert_type);
TEST_CHECK(a);
if (a == nullptr) return;
auto const* ta = alert_cast<add_torrent_alert const>(a);
TEST_CHECK(ta);
if (ta == nullptr) return;
TEST_CHECK(!ta->error);
TEST_CHECK(ta->params.ti->name() == "temp");
}