c++ futures/promises like javascript?

While then is proposed, you can implement your own infix then via the named operator technique.

Create a struct then_t {}; and a static then_t then;. Now override operator* on the left and right so that std::future<bool> *then* lambda creates a std::async that waits on the future, and passes the result to the lambda, then returns the return value of the lambda.

This requires lots of care and attention, as you have to carefully create copies to avoid dangling references, and mess around with r and l value syntax to make it fully efficient.

The end syntax you get is:

aut fut = asyncLoader("cat.jpg");
fut *then* [&](Image img) { std::cout << "Image loaded: " << img; };

which is pretty close to what you want.

If you are really smart, you could even have it also support:

aut fut = asyncLoader("cat.jpg");
fut *then* [=] { std::cout << "Image loaded: " << fut.get(); };

which gets rid of some of the boilerplate and would be useful sometimes. This requires asyncLoader to return a std::shared_future instead of a future.


You could pass an object thats for example implementing a Runnable class to the "then" method of the Future class. Once the Future finished its work, call the "run" method of the passed object.


I don't like c++'s future, so i wrote a promise libraries as javascript here https://github.com/xhawk18/promise-cpp

/* Convert callback to a promise (Defer) */
Defer myDelay(boost::asio::io_service &io, uint64_t time_ms) {
    return newPromise([&io, time_ms](Defer &d) {
        setTimeout(io, [d](bool cancelled) {
            if (cancelled)
                d.reject();
            else
                d.resolve();
        }, time_ms);
    });
}


void testTimer(io_service &io) {

    myDelay(io, 3000).then([&] {
        printf("timer after 3000 ms!\n");
        return myDelay(io, 1000);
    }).then([&] {
        printf("timer after 1000 ms!\n");
        return myDelay(io, 2000);
    }).then([] {
        printf("timer after 2000 ms!\n");
    }).fail([] {
        printf("timer cancelled!\n");
    });
}

int main() {
    io_service io;    
    testTimer(io);   
    io.run();
    return 0;
}

compare with Javascript promise, just --

  1. Use newPromise instead of js's new Promise
  2. Use lambda instead of js function
  3. Use d.resolve instead of js's resolve
  4. Use d.reject instead of js's reject

You can resolve/reject with any type of paramters, and need not care about the troublesome of <> in c++ template.


A .then function for std::future has been proposed for the upcoming C++17 standard.

Boost's implementation of future (which is compliant with the current standard, but provides additional features as extensions) already provides parts of that functionality in newer versions (1.53 or newer).

For a more well-established solution, take a look at the Boost.Asio library, which does allow easy implementation of asynchronous control flows as provided by future.then. Asio's concept is slightly more complicated, as it requires access to a central io_service object for dispatching asynchronous callbacks and requires manual management of worker threads. But in principle this is a very good match for what you asked for.

Tags:

C++

Promise