-
Notifications
You must be signed in to change notification settings - Fork 655
Add Future::wait() #20
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
Conversation
Thanks for the PR! This is indeed what I would expect for a function to block and wait for the resolution of a future, but I agree that I'm not entirely sure whether we want to bake this in or not. On one hand it's easy enough to implement locally (as you've seen), but on the other hand it's a footgun in many situations. For example as you've mentioned with
The first point is why Another option here would be to modify your local "event loop" to have a method to "await" a future. For example |
/// a deadlock. | ||
fn wait(self) -> Result<Self::Item, Self::Error> where Self: Sized { | ||
let (tx, rx) = channel(); | ||
self.then(move |r| -> Result<(), ()> { let _ = tx.send(r); Ok(()) }).forget(); |
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.
Dropping the Result
seems less-than-ideal.
This is a function I would like to have as well. It's pretty useful for prototyping and testing. Using channels every time you want this behavior is a bit tedious. Since this is a provided implementation, could the mio futures get their own implementation that panics and warns the user? Edit: The panicking probably wouldn't work once you wrap the futures with another one. Perhaps a Waitable trait? |
Perhaps the function could return an
This would allow for something like the following
|
@sbstp yeah it's true that for certain kinds of tests this can be quite useful. I think @nielsle's suggestion may make the most sense to me where it's converted to a I'm still wary of blocking the thread because it assumes that the computation is happening on another thread, which may not always be the case :( |
What if a The mio futures (and any that cannot wait) would not implement |
Perhaps, yeah, but that level of complexity may not be worth it in the long On Monday, August 15, 2016, Simon Bernier St-Pierre <
|
True, there would be a lot of extra code to maintain. How about making the function unsafe? Use at your own risk kind of deal. |
Generally we reserve |
My personal preference would be to have this as a standalone fn. futures::await(my_future); Also... please take a timeout :) |
With #77 we would actually be able to write this without channels at all! Additionally, we could relax the I think we've also got So I'm somewhat leaning towards the following plan of action:
fn await_timeout(self) -> AwaitTimeout<Self>;
enum AwaitTimeout<F: Future> {
Finished(Result<F::Item, F::Error>),
TimedOut(F),
} Now that I think I'm less sure about the signature of In any case, thoughts? |
Ok, I've implemented @carllerche I've avoided implementing I'm thinking we can solve this through an abstraction that represents something like a "fusing" of a future and a task. That way you could In any case I'd like to add this, but it seems somewhat premature as we're still settling I believe on the task/executor/future story, so I figure we can add it at a later date (but soon after that's settled!) |
Could you release a crates.io release with this in? |
@nabijaczleweli soon! We have a few final aspects we'd like to flesh out, like #95, before we make a publish. For now I'd recommend using this library from git as it's where the development is currently happening. |
I can't publish to crates if any of my deps is of the |
I'm currently experimenting using futures in order to dispatch small tasks to a thread pool.
In my main function, every 16ms I create some tasks with
CpuPool::execute()
. These tasks trigger sub-tasks, like with split-join parallelism.If all the tasks and sub-tasks take less than 16 milliseconds in total, everything is fine. However if the user's machine is not powerful enough and they take more than 16 milliseconds, then the next tasks fire before the previous ones have finished. What would end up happening is that the tasks queue would grow more and more. I really don't want this to happen, and therefore I think the best way is to block until all the tasks are over before starting the new ones.
I recognized that adding a
wait
function would be unidiomatic in the context of mio, however I find it useful in my situation. I'm not sure though if my problem wouldn't be solved with an executor.