Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost::Future deferred continuation unwrapping deadlocks

I am using Boost’s promises and futures and encountered an edge case while using continuations. My code uses a continuation that returns a future, and unwraps then()’s result before getting its value.

#define BOOST_THREAD_VERSION 5

#include <iostream>
#include <boost/thread/future.hpp>

int main(int argc, char* argv[])
{
    boost::promise<int> promise;
    boost::future<int> future = promise.get_future();

    promise.set_value(42);

    int result = future.then(
        boost::launch::async,
        [](boost::future<int> result)
        {
            return boost::make_ready_future(result.get());
        }
    ).unwrap().get();

    std::cout << "Result is: " << result << std::endl;
    return 0;
}

In this example, I explicitly used the boost::launch::async policy to launch the continuation in a new thread, and I get the expected result of 42.

However, as soon as I replace that policy with boost::launch::deferred, the program seems to deadlock. What am I doing wrong?

NB: The deferred continuation works correctly as long as I don’t unwrap() its value. The issue is specifically about unwrapped deferred continuations.

like image 358
matteodelabre Avatar asked Oct 30 '22 06:10

matteodelabre


1 Answers

I think the future continuation paired with unwrap does not make sense. If you create a future with .then, you will get a valid future. So you can call .get() without blocking. That is why I dont see the need for a nested future. However, the way you wrote it should not cause a deadlock and it is probably a bug.

#define BOOST_THREAD_VERSION 5

#include <iostream>
#include <boost/thread/future.hpp>

int main(int argc, char* argv[])
{
    boost::promise<int> promise;
    boost::future<int> future = promise.get_future();

    promise.set_value(42);

    int result = future.then(
        boost::launch::deferred,
        [](boost::future<int> result)
        {
            return result.get(); // get is non-blocking, since it is a continuation
        }
    )/*.unwrap()*/.get();

    std::cout << "Result is: " << result << std::endl;
    return 0;
}

As of boost 1.64, unwrap is still a experimental function. It would be nice, if you communicate this behaviour to the developer of boost::thread.

like image 119
OutOfBound Avatar answered Nov 10 '22 01:11

OutOfBound