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 --
- Use newPromise instead of js's new Promise
- Use lambda instead of js function
- Use d.resolve instead of js's resolve
- 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.