Closed Gei0r closed 4 years ago
In that case it is not really possible to convert the execution to an eager one, however it is possible to do the following:
cti::continuable<> root()
{
std::vector<cti::continuable<>> promises;
promises.push_back(backgroundWork(std::chrono::seconds{1}));
promises.push_back(backgroundWork(std::chrono::seconds{2}));
promises.push_back(backgroundWork(std::chrono::seconds{3}));
co_await cti::when_all(std::move(promises), cti::async([] {
std::cout << "Now doing some expensive calculations..." << std::endl;
// the idea is that the backgroundWork tasks should have started
// their async operation already so that they can complete while we're
// doing the foreground calculation.
std::this_thread::sleep_for(std::chrono::seconds{5});
std::cout << "Calculations done" << std::endl;
}));
}
Which yields the following output:
Starting background work... Starting background work... Starting background work... Now doing some expensive calculations... Calculations done background work done background work done background work done all done
The trick here is that when_all
requests the execution in a depth first visit way such as elements are invoked deeply after each other from left to right. Just make sure that the blocking call happens at the end because continuables that come afterwards are not requested until the thread has resumed.
What I meant in the documentation is that you always can convert the following lazy function:
continuable<> dosth() {
return async([] {
// do something
});
}
To the following eager code which evenatually continues asynchronously or finishes immediately:
continuable<> dosth() {
// do something
return make_ready_continuable();
}
The disadvantage of the latter one is that it will be incoked immediately on creation making it impossible to make the execution deterministic (or possibly ellide it when the result is not needed anymore).
Could you add a method to continuable to start processing without consuming the awaitable? This way one could replicate the javascript behavior.
This is not possible with the design of this library.
You would have to switch to a future
implementation which is implemented on the basis of a shared state.
It seems like this issue was resolved. If you have any further questions or issue reports open a new ticket please.
@Naios
TLDR: Is there a way to get eager continuable invocation for async code like in javascript?
A common use pattern of async code is this (javascript):
Output:
Because the background work (1 s, 2 s, and 3 s) were all started before the foreground calculation (5 s), the whole program ran only 5 s.
Now I'm trying to replicate the same with C++ and continuable, using the same structure as in javascript:
Output:
As you can see, the background tasks started only after the foreground work completed. As a result, the whole program required 8 s to run. This is documented in the tutorial, but is there a way to get eager evaluation like in javascript?