-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: add future on asynchronous methods that trigger alerts (should I continue?) #7558
Conversation
a simple example: auto f = th.async_flush_cache();
f.wait() and an other more complex: std::future<const lt::save_resume_data_alert*> f = th.async_save_resume_data();
try {
const auto* alert = f.get();
std::vector<char> buf = lt::write_torrent_file_buf(alert->params);
} catch (lt::alert_exception<lt::save_resume_data_failed_alert> const& e) {
const auto* alert = e.get_failed_alert();
} |
@@ -69,7 +69,7 @@ | |||
~alert_manager(); | |||
|
|||
template <class T, typename... Args> | |||
void emplace_alert(Args&&... args) try | |||
const T* emplace_alert(Args&&... args) try |
Check notice
Code scanning / CodeQL
Unused local variable Note
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks like a parse failure in CodeQL..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would think a much simpler approach would be to add client_data_t
to the alerts, and accept an optional client_data_t
when making the calls.
That way, at least the alert can be associated with the corresponding call in a simple and cheap way. the client_data_t
object could even point to a promise object to be invoked.
Although, having the promise be invoked directly by the main thread would save time in synchronizing the threads. It would be possible to do call the promise in a plugin, but it wouldn't be super elegant
@@ -82,13 +82,15 @@ namespace aux { | |||
{ | |||
// record that we dropped an alert of this type | |||
m_dropped.set(T::alert_type); | |||
return; | |||
return nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you need a return nullptr;
on lines 100 as well
@@ -69,7 +69,7 @@ | |||
~alert_manager(); | |||
|
|||
template <class T, typename... Args> | |||
void emplace_alert(Args&&... args) try | |||
const T* emplace_alert(Args&&... args) try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks like a parse failure in CodeQL..
} | ||
|
||
private: | ||
const T* m_alert; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks a bit suspicious. alert allocated in the heterogeneous queue have their lifetimes tied to that queue. throwing exceptions with pointers into it seems like asking for accessing danging pointers
, boost::asio::error::operation_aborted | ||
, "", operation_t::unknown); | ||
|
||
if (promise) promise->set_exception(std::make_exception_ptr(alert_exception(a))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a
is a non-owning pointer to the alert, and the life-time of the alert is tied to when the user calls pop_alerts()
. This seems really risky as the future may be checked after the alert object has been deleted.
alerts().emplace_alert<storage_moved_alert>(get_handle(), save_path, m_save_path); | ||
if (alerts().should_post<storage_moved_alert>()) { | ||
auto* a = alerts().emplace_alert<storage_moved_alert>(get_handle(), save_path, m_save_path); | ||
if (promise) promise->set_value(a); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
passing the pointer to the alert to the future is risky in the same way as the exception. Making sure that the client gets the future's value before calling pop_alerts()
is not trivial and, I would expect, a source of errors.
Offtopic: |
|
Doesn't seem like it actually requires RTTI (except maybe |
requires that the lifetime of alerts be guaranteed after session::pop_alerts is called, if they are still referenced.
this pull request allows you to have a future on asynchronous methods that trigger alerts:
torrent_handle:
session_handle: