0

I am using boost.future<T> with continuations, in boost 1.56.

I have an API that returns a future, that I want to use from inside a continuation. So in theory, I need to .unwrap the future before chaining the second continuation.

So I do the following:

auto result = api_returns_future().then([](boost::future<R> && result) {
                    do_something_with_result();

                    //Note I could call .get() here, but I don't
                    return api_returns_future();
              }).unwrap() //Now I unwrap the future here
              .then([](boost::future<R> && result) { ... });

Namely, I have:

  1. future<R>::then
  2. In the first continuation, I return from the lambda with an API call that returns a boost::future<R> and later I unwrap it.
  3. After that I want to attach another continuation, but this continuation is never called.

Question:

  1. It would be correct to do this in the first continuation: return api_returns_future().get() (note I call .get() from inside the continuation directly` and give up on unwrapping?. Has this alternative some drawback for the asynchroncity of my code?

EDIT: I updated the question to better reflect what I want to ask after some more research.

Thanks

roalz
  • 2,699
  • 3
  • 25
  • 42
Germán Diago
  • 7,473
  • 1
  • 36
  • 59

1 Answers1

5

If you look in the boost docs, there's an example of how to use then():

future<int> f1 = async([]() { return 123; });
future<string> f2 = f1.then([](future<int> f) { 
    return f.get().to_string(); // here .get() won't block 
});

Note that then wraps its lambda's result in a future too. Now in your case, your lambda returns a future, so as a first go, you'd have to write:

auto result = api_returns_future().then([](future<R> result) {
    // stuff
    return api_returns_future();
}).then([](future<future<R>> result2) {
//         ^^^^^^^^^^^^^^^^^
    // other stuff
});

But for this reason, the docs also indicate that there is an unwrap move constructor:

Unwrap Move Constructor - EXTENSION

 future( future< future<R>>& other); // EXTENSION

Postconditions
this->get_state() returns the value of other->get_state() prior to the call. other->get_state() returns boost::future_state::uninitialized. The associated shared state is now unwrapped and the inner future shared state is associated with *this. other is not associated with any shared state, ! other.valid().

Thus I would expect you to be able to just write the following:

auto result = api_returns_future().then([](future<R> result) {
    // stuff
    return api_returns_future();
}).then([](future<R> result2) {
//         ^^^^^^^^^
    // other stuff
});

since the library will take care of the unwrapping itself.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • I see what you mean. But my question actually is: I have an API that *already* returns a future. I want to call it from inside the continuation. So if I call `.get()` inside the continuation, will this have adverse effects? I tried to not call `.get` inside the continuation and use `unwrap()` but it is blocked forever for some reason. – Germán Diago Jan 23 '15 at 06:32
  • I modified the code to reflect better what I mean, take another look please if you could help. – Germán Diago Jan 23 '15 at 06:33
  • I modified my question to more clearly state my current question, which evolved since I wrote it, but it is still basically the same. – Germán Diago Jan 23 '15 at 06:41
  • @GermánDiago I believe I understand your question better and updated. Did you ask the [same question](http://stackoverflow.com/questions/28103562/boost-future-are-these-two-pieces-of-code-equivalent) twice in a row? – Barry Jan 23 '15 at 12:45
  • 1
    I will try again but I believe that last time I tried automatic unwrap did not happen. – Germán Diago Jan 25 '15 at 03:33