tokio-rs/tokio-core

How to implement Promises with Tokio-Core?

asomers opened this issue · 3 comments

I'm coming from the world of Seastar. Seastar has chainable futures, like Tokio. But it also has Promises. A Promise is an object that can be used to make Future ready. Typically, you use them like this:

Future do_something() {
    std::pair<Future, Promise> pair = make_future();
    send_to_some_other_time_or_place(pair.second);
    return(pair.first);
}

And then at some later time, the receiver of the Promise calls promise.set_value(), and suddenly its Future is ready.

I'm trying to do this same thing with Tokio-core. It seems that mio supports it by using mio::SetRegistration. I think I can make it work by issuing the low-level I/O at the time my future is created. However, that violates the principal that a future should do nothing until polled. Plus, it's pretty convoluted. I would rather not issue the low-level I/O until my future's poll method. But that's a problem, because the low-level I/O is itself using a Tokio library, and it returns a future. There's no way to return a future from a poll method, so my low-level library won't do anything. It's like this:

fn poll(&mut self) -> futures::Poll<(), io::Error> {
    if ! self.issued {
        let future = LowLevelLibrary::do_something().and_then{||
             self.io.set_readiness(true); //No way to send future to the reactor!
        }
    }
    self.issued = true;
    if self.io.poll_read() == futures::Async::NotReady {
        return Ok(futures::Async::NotReady);
    }
    Ok(futures::Async::Ready(())
}

Has anybody done this before? Any good ideas? If it can be done in a straightforward and reusable way, I might try to write a middleware crate for it.

This sounds exactly like sync::oneshot in futures-rs. Is that correct?

Actually @carllerche I don't think that solves my entire problem in this case, because I want my promise to be triggered by a future that doesn't yet exist at the time when I need to return a future. But it looks like tokio_core::reactor::Handle::spawn may be able to help me, because I can call that from within my poll method. I'll try using those two methods together.

Ok sounds like oneshot and perhaps some other methods should solve this, so I'm going to close this.