make session_handle hold a weak_ptr and be copyable (#2034)
This commit is contained in:
parent
660cdaf2d1
commit
353ab20280
|
@ -231,6 +231,7 @@ namespace aux {
|
||||||
, boost::noncopyable
|
, boost::noncopyable
|
||||||
, single_threaded
|
, single_threaded
|
||||||
, aux::error_handler_interface
|
, aux::error_handler_interface
|
||||||
|
, std::enable_shared_from_this<session_impl>
|
||||||
{
|
{
|
||||||
// the size of each allocation that is chained in the send buffer
|
// the size of each allocation that is chained in the send buffer
|
||||||
enum { send_buffer_size_impl = 128 };
|
enum { send_buffer_size_impl = 128 };
|
||||||
|
|
|
@ -320,6 +320,8 @@ namespace libtorrent {
|
||||||
// peer was banned because its listen port is within a banned port
|
// peer was banned because its listen port is within a banned port
|
||||||
// range, as specified by the port_filter.
|
// range, as specified by the port_filter.
|
||||||
banned_by_port_filter,
|
banned_by_port_filter,
|
||||||
|
// The session_handle is not referring to a valid session_impl
|
||||||
|
invalid_session_handle,
|
||||||
|
|
||||||
|
|
||||||
// The NAT-PMP router responded with an unsupported protocol version
|
// The NAT-PMP router responded with an unsupported protocol version
|
||||||
|
|
|
@ -184,7 +184,6 @@ namespace aux {
|
||||||
// configuring it, you can pass in a session_params object. Its settings
|
// configuring it, you can pass in a session_params object. Its settings
|
||||||
// will take effect before the session starts up.
|
// will take effect before the session starts up.
|
||||||
explicit session(session_params params = session_params())
|
explicit session(session_params params = session_params())
|
||||||
: session_handle(nullptr)
|
|
||||||
{
|
{
|
||||||
TORRENT_CFG();
|
TORRENT_CFG();
|
||||||
start(std::move(params), nullptr);
|
start(std::move(params), nullptr);
|
||||||
|
@ -204,7 +203,6 @@ namespace aux {
|
||||||
// destruct the session object, then sync with the io_service, then
|
// destruct the session object, then sync with the io_service, then
|
||||||
// destruct the session_proxy object.
|
// destruct the session_proxy object.
|
||||||
session(session_params params, io_service& ios)
|
session(session_params params, io_service& ios)
|
||||||
: session_handle(nullptr)
|
|
||||||
{
|
{
|
||||||
TORRENT_CFG();
|
TORRENT_CFG();
|
||||||
start(std::move(params), &ios);
|
start(std::move(params), &ios);
|
||||||
|
@ -223,7 +221,6 @@ namespace aux {
|
||||||
// pass 0 as the flags parameter.
|
// pass 0 as the flags parameter.
|
||||||
session(settings_pack pack
|
session(settings_pack pack
|
||||||
, int flags = start_default_features | add_default_plugins)
|
, int flags = start_default_features | add_default_plugins)
|
||||||
: session_handle(nullptr)
|
|
||||||
{
|
{
|
||||||
TORRENT_CFG();
|
TORRENT_CFG();
|
||||||
start(flags, std::move(pack), nullptr);
|
start(flags, std::move(pack), nullptr);
|
||||||
|
@ -253,7 +250,6 @@ namespace aux {
|
||||||
session(settings_pack pack
|
session(settings_pack pack
|
||||||
, io_service& ios
|
, io_service& ios
|
||||||
, int flags = start_default_features | add_default_plugins)
|
, int flags = start_default_features | add_default_plugins)
|
||||||
: session_handle(nullptr)
|
|
||||||
{
|
{
|
||||||
TORRENT_CFG();
|
TORRENT_CFG();
|
||||||
start(flags, std::move(pack), &ios);
|
start(flags, std::move(pack), &ios);
|
||||||
|
@ -276,7 +272,6 @@ namespace aux {
|
||||||
session(fingerprint const& print
|
session(fingerprint const& print
|
||||||
, int flags = start_default_features | add_default_plugins
|
, int flags = start_default_features | add_default_plugins
|
||||||
, std::uint32_t alert_mask = alert::error_notification)
|
, std::uint32_t alert_mask = alert::error_notification)
|
||||||
: session_handle(nullptr)
|
|
||||||
{
|
{
|
||||||
TORRENT_CFG();
|
TORRENT_CFG();
|
||||||
settings_pack pack;
|
settings_pack pack;
|
||||||
|
@ -299,7 +294,6 @@ namespace aux {
|
||||||
, char const* listen_interface = "0.0.0.0"
|
, char const* listen_interface = "0.0.0.0"
|
||||||
, int flags = start_default_features | add_default_plugins
|
, int flags = start_default_features | add_default_plugins
|
||||||
, int alert_mask = alert::error_notification)
|
, int alert_mask = alert::error_notification)
|
||||||
: session_handle(nullptr)
|
|
||||||
{
|
{
|
||||||
TORRENT_CFG();
|
TORRENT_CFG();
|
||||||
TORRENT_ASSERT(listen_port_range.first > 0);
|
TORRENT_ASSERT(listen_port_range.first > 0);
|
||||||
|
|
|
@ -69,21 +69,17 @@ namespace libtorrent {
|
||||||
|
|
||||||
struct TORRENT_EXPORT session_handle
|
struct TORRENT_EXPORT session_handle
|
||||||
{
|
{
|
||||||
session_handle() : m_impl(nullptr) {}
|
friend class session;
|
||||||
|
friend struct aux::session_impl;
|
||||||
|
|
||||||
explicit session_handle(aux::session_impl* impl)
|
session_handle() {}
|
||||||
: m_impl(impl)
|
|
||||||
{}
|
|
||||||
|
|
||||||
// moveable
|
session_handle(session_handle const& t) = default;
|
||||||
session_handle(session_handle&&) = default;
|
session_handle(session_handle&& t) = default;
|
||||||
|
session_handle& operator=(session_handle const&) = default;
|
||||||
session_handle& operator=(session_handle&&) = default;
|
session_handle& operator=(session_handle&&) = default;
|
||||||
|
|
||||||
// non copyable
|
bool is_valid() const { return !m_impl.expired(); }
|
||||||
session_handle(session_handle const&) = delete;
|
|
||||||
session_handle& operator=(session_handle const&) = delete;
|
|
||||||
|
|
||||||
bool is_valid() const { return m_impl != nullptr; }
|
|
||||||
|
|
||||||
// TODO: 2 the ip filter should probably be saved here too
|
// TODO: 2 the ip filter should probably be saved here too
|
||||||
|
|
||||||
|
@ -1021,8 +1017,8 @@ namespace libtorrent {
|
||||||
|
|
||||||
// This function is intended only for use by plugins. This type does
|
// This function is intended only for use by plugins. This type does
|
||||||
// not have a stable API and should be relied on as little as possible.
|
// not have a stable API and should be relied on as little as possible.
|
||||||
aux::session_impl* native_handle() const
|
std::shared_ptr<aux::session_impl> native_handle() const
|
||||||
{ return m_impl; }
|
{ return m_impl.lock(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -1035,7 +1031,11 @@ namespace libtorrent {
|
||||||
template <typename Ret, typename Fun, typename... Args>
|
template <typename Ret, typename Fun, typename... Args>
|
||||||
Ret sync_call_ret(Fun f, Args&&... a) const;
|
Ret sync_call_ret(Fun f, Args&&... a) const;
|
||||||
|
|
||||||
aux::session_impl* m_impl;
|
explicit session_handle(std::weak_ptr<aux::session_impl> impl)
|
||||||
|
: m_impl(impl)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::weak_ptr<aux::session_impl> m_impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace libtorrent
|
} // namespace libtorrent
|
||||||
|
|
|
@ -168,7 +168,7 @@ namespace libtorrent {
|
||||||
"invalid SSL certificate",
|
"invalid SSL certificate",
|
||||||
"not an SSL torrent",
|
"not an SSL torrent",
|
||||||
"banned by port filter",
|
"banned by port filter",
|
||||||
"",
|
"invalid session handle used",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
|
|
@ -306,7 +306,7 @@ namespace libtorrent {
|
||||||
}
|
}
|
||||||
|
|
||||||
m_impl = std::make_shared<aux::session_impl>(*ios);
|
m_impl = std::make_shared<aux::session_impl>(*ios);
|
||||||
*static_cast<session_handle*>(this) = session_handle(m_impl.get());
|
*static_cast<session_handle*>(this) = session_handle(m_impl);
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
for (auto const& ext : params.extensions)
|
for (auto const& ext : params.extensions)
|
||||||
|
|
|
@ -54,19 +54,21 @@ namespace libtorrent {
|
||||||
template <typename Fun, typename... Args>
|
template <typename Fun, typename... Args>
|
||||||
void session_handle::async_call(Fun f, Args&&... a) const
|
void session_handle::async_call(Fun f, Args&&... a) const
|
||||||
{
|
{
|
||||||
m_impl->get_io_service().dispatch([=]() mutable
|
std::shared_ptr<session_impl> s = m_impl.lock();
|
||||||
|
if (!s) aux::throw_ex<system_error>(errors::invalid_session_handle);
|
||||||
|
s->get_io_service().dispatch([=]() mutable
|
||||||
{
|
{
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
try {
|
try {
|
||||||
#endif
|
#endif
|
||||||
(m_impl->*f)(std::forward<Args>(a)...);
|
(s.get()->*f)(std::forward<Args>(a)...);
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
} catch (system_error const& e) {
|
} catch (system_error const& e) {
|
||||||
m_impl->alerts().emplace_alert<session_error_alert>(e.code(), e.what());
|
s->alerts().emplace_alert<session_error_alert>(e.code(), e.what());
|
||||||
} catch (std::exception const& e) {
|
} catch (std::exception const& e) {
|
||||||
m_impl->alerts().emplace_alert<session_error_alert>(error_code(), e.what());
|
s->alerts().emplace_alert<session_error_alert>(error_code(), e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
m_impl->alerts().emplace_alert<session_error_alert>(error_code(), "unknown error");
|
s->alerts().emplace_alert<session_error_alert>(error_code(), "unknown error");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
@ -75,58 +77,64 @@ namespace libtorrent {
|
||||||
template<typename Fun, typename... Args>
|
template<typename Fun, typename... Args>
|
||||||
void session_handle::sync_call(Fun f, Args&&... a) const
|
void session_handle::sync_call(Fun f, Args&&... a) const
|
||||||
{
|
{
|
||||||
|
std::shared_ptr<session_impl> s = m_impl.lock();
|
||||||
|
if (!s) aux::throw_ex<system_error>(errors::invalid_session_handle);
|
||||||
|
|
||||||
// this is the flag to indicate the call has completed
|
// this is the flag to indicate the call has completed
|
||||||
// capture them by pointer to allow everything to be captured by value
|
// capture them by pointer to allow everything to be captured by value
|
||||||
// and simplify the capture expression
|
// and simplify the capture expression
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
std::exception_ptr ex;
|
std::exception_ptr ex;
|
||||||
m_impl->get_io_service().dispatch([=, &done, &ex]() mutable
|
s->get_io_service().dispatch([=, &done, &ex]() mutable
|
||||||
{
|
{
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
try {
|
try {
|
||||||
#endif
|
#endif
|
||||||
(m_impl->*f)(std::forward<Args>(a)...);
|
(s.get()->*f)(std::forward<Args>(a)...);
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
ex = std::current_exception();
|
ex = std::current_exception();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
std::unique_lock<std::mutex> l(m_impl->mut);
|
std::unique_lock<std::mutex> l(s->mut);
|
||||||
done = true;
|
done = true;
|
||||||
m_impl->cond.notify_all();
|
s->cond.notify_all();
|
||||||
});
|
});
|
||||||
|
|
||||||
aux::torrent_wait(done, *m_impl);
|
aux::torrent_wait(done, *s);
|
||||||
if (ex) std::rethrow_exception(ex);
|
if (ex) std::rethrow_exception(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ret, typename Fun, typename... Args>
|
template<typename Ret, typename Fun, typename... Args>
|
||||||
Ret session_handle::sync_call_ret(Fun f, Args&&... a) const
|
Ret session_handle::sync_call_ret(Fun f, Args&&... a) const
|
||||||
{
|
{
|
||||||
|
std::shared_ptr<session_impl> s = m_impl.lock();
|
||||||
|
if (!s) aux::throw_ex<system_error>(errors::invalid_session_handle);
|
||||||
|
|
||||||
// this is the flag to indicate the call has completed
|
// this is the flag to indicate the call has completed
|
||||||
// capture them by pointer to allow everything to be captured by value
|
// capture them by pointer to allow everything to be captured by value
|
||||||
// and simplify the capture expression
|
// and simplify the capture expression
|
||||||
bool done = false;
|
bool done = false;
|
||||||
Ret r;
|
Ret r;
|
||||||
std::exception_ptr ex;
|
std::exception_ptr ex;
|
||||||
m_impl->get_io_service().dispatch([=, &r, &done, &ex]() mutable
|
s->get_io_service().dispatch([=, &r, &done, &ex]() mutable
|
||||||
{
|
{
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
try {
|
try {
|
||||||
#endif
|
#endif
|
||||||
r = (m_impl->*f)(std::forward<Args>(a)...);
|
r = (s.get()->*f)(std::forward<Args>(a)...);
|
||||||
#ifndef BOOST_NO_EXCEPTIONS
|
#ifndef BOOST_NO_EXCEPTIONS
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
ex = std::current_exception();
|
ex = std::current_exception();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
std::unique_lock<std::mutex> l(m_impl->mut);
|
std::unique_lock<std::mutex> l(s->mut);
|
||||||
done = true;
|
done = true;
|
||||||
m_impl->cond.notify_all();
|
s->cond.notify_all();
|
||||||
});
|
});
|
||||||
|
|
||||||
aux::torrent_wait(done, *m_impl);
|
aux::torrent_wait(done, *s);
|
||||||
if (ex) std::rethrow_exception(ex);
|
if (ex) std::rethrow_exception(ex);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +183,9 @@ namespace libtorrent {
|
||||||
|
|
||||||
io_service& session_handle::get_io_service()
|
io_service& session_handle::get_io_service()
|
||||||
{
|
{
|
||||||
return m_impl->get_io_service();
|
std::shared_ptr<session_impl> s = m_impl.lock();
|
||||||
|
if (!s) aux::throw_ex<system_error>(errors::invalid_session_handle);
|
||||||
|
return s->get_io_service();
|
||||||
}
|
}
|
||||||
|
|
||||||
torrent_handle session_handle::find_torrent(sha1_hash const& info_hash) const
|
torrent_handle session_handle::find_torrent(sha1_hash const& info_hash) const
|
||||||
|
@ -1055,17 +1065,23 @@ namespace {
|
||||||
// the alerts are const, they may not be deleted by the client
|
// the alerts are const, they may not be deleted by the client
|
||||||
void session_handle::pop_alerts(std::vector<alert*>* alerts)
|
void session_handle::pop_alerts(std::vector<alert*>* alerts)
|
||||||
{
|
{
|
||||||
m_impl->pop_alerts(alerts);
|
std::shared_ptr<session_impl> s = m_impl.lock();
|
||||||
|
if (!s) aux::throw_ex<system_error>(errors::invalid_session_handle);
|
||||||
|
s->pop_alerts(alerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
alert* session_handle::wait_for_alert(time_duration max_wait)
|
alert* session_handle::wait_for_alert(time_duration max_wait)
|
||||||
{
|
{
|
||||||
return m_impl->wait_for_alert(max_wait);
|
std::shared_ptr<session_impl> s = m_impl.lock();
|
||||||
|
if (!s) aux::throw_ex<system_error>(errors::invalid_session_handle);
|
||||||
|
return s->wait_for_alert(max_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_handle::set_alert_notify(std::function<void()> const& fun)
|
void session_handle::set_alert_notify(std::function<void()> const& fun)
|
||||||
{
|
{
|
||||||
m_impl->alerts().set_notify_function(fun);
|
std::shared_ptr<session_impl> s = m_impl.lock();
|
||||||
|
if (!s) aux::throw_ex<system_error>(errors::invalid_session_handle);
|
||||||
|
s->alerts().set_notify_function(fun);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
|
|
|
@ -890,7 +890,7 @@ namespace aux {
|
||||||
m_ses_extensions[plugins_dht_request_idx].push_back(ext);
|
m_ses_extensions[plugins_dht_request_idx].push_back(ext);
|
||||||
if (features & plugin::alert_feature)
|
if (features & plugin::alert_feature)
|
||||||
m_alerts.add_extension(ext);
|
m_alerts.add_extension(ext);
|
||||||
session_handle h(this);
|
session_handle h(shared_from_this());
|
||||||
ext->added(h);
|
ext->added(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue