Docs don’t mention how these work. When I call:
The result of that is a DownloadTask pointer. What isn’t clear is who owns this task pointer? Does whatever mechanism in JUCE that downloads things in the background then delete these tasks when no longer used?
Or should I call delete once the callback
This function has been updated to return
unique_ptr, which should make the ownership semantics clearer.
Hmmm, so that makes it interesting. Cause when downloading something in the background, you typically want to fire-and-forget, until you get a callback telling you that it is done.
I guess this means if I don’t capture the
unique_ptr and store it somewhere, then the task is immediately deleted and no download will take place?
If the client code is responsible, when is it safe to delete? Should this be done within
URL::DownloadTask::Listener::finished()? Or should I wait until after that method been called?
I think a few lines of text for the doxygen output is necessary here to clear up usage.
“Fire-and-forget” is usually the wrong approach for any kind of async task. You typically want some kind of handle so you can monitor its progress or cancel it and clean up appropriately (what if you app wants to quit etc.).
The task-based approach that
std::async uses is a pretty good general example of this paradigm.
I agree that a note about whether you can delete a
DownloadTask during its callback would be helpful though.
Why is it the wrong approach? This is why there is a listener for it, right? Shouldn’t the object that inherits from the listener and implements
progress() be the right place to deal with this?
Cause now we’ve got this hybrid where one part of the code starts something, another object gets all the callbacks, but the original piece of code is where the pointer is stored and presumably needs to delete it at some point.
Instead, I think the ownership of the pointer should be handed off to the object that deals with the callbacks, and it should be made more obvious when the pointer is deleted, or when it needs to be deleted.
I think the listener interface is orthogonal to the ownership semantics.
If you’re worried about needing a place to store the pointer, this is much worse than needing a class to inherit from the listener interface just to manage the lifetime of the download.
To me, it’s much cleaner to have your model own the pointer (and hence the download task) and then have any UI elements use the listener interface for reporting info to the user.
To be honest though, I probably wouldn’t use the listener interface at all these days and just poll the pointer for the relevant info. You’ll probably be updating something on a timer anyway to show progress.