High level
I want to call some functions with no return value in a async mode without waiting for them to finish. If I use std::async the future object doesn't destruct until the task is over, this make the call not sync in my case.
Example
void sendMail(const std::string& address, const std::string& message) { //sending the e-mail which takes some time... } myResonseType processRequest(args...) { //Do some processing and valuate the address and the message... //Sending the e-mail async auto f = std::async(std::launch::async, sendMail, address, message); //returning the response ASAP to the client return myResponseType; } //<-- I'm stuck here until the async call finish to allow f to be destructed. // gaining no benefit from the async call.
My questions are
note:
I rather not using the option of thread+detach (suggested by @galop1n) since creating a new thread have an overhead I wish to avoid. While using std::async (at least on MSVC) is using an inner thread pool.
Thanks.
So if you want to make sure that the work is done asynchronously, use std::launch::async . @user2485710 it needs to block when you retrieve the result, if you need the result in the launching thread. It cannot use the result if the result is not ready. So if you go to get the result, you have to wait until it is ready.
For now, we know that if no policy is specified, then std::async launches a callable function in a separate thread. However, the C++ standard does not specify whether the thread is a new one or reused from a thread pool. Let us see how each of the three implementations launches a callable function.
The function template async runs the function f asynchronously (potentially in a separate thread which might be a part of a thread pool) and returns a std::future that will eventually hold the result of that function call. 1) Behaves as if (2) is called with policy being std::launch::async | std::launch::deferred.
std::shared_futureAccess to the same shared state from multiple threads is safe if each thread does it through its own copy of a shared_future object.
You can move the future into a global object, so when the local future's destructor runs it doesn't have to wait for the asynchronous thread to complete.
std::vector<std::future<void>> pending_futures; myResonseType processRequest(args...) { //Do some processing and valuate the address and the message... //Sending the e-mail async auto f = std::async(std::launch::async, sendMail, address, message); // transfer the future's shared state to a longer-lived future pending_futures.push_back(std::move(f)); //returning the response ASAP to the client return myResponseType; }
N.B. This is not safe if the asynchronous thread refers to any local variables in the processRequest
function.
While using
std::async
(at least on MSVC) is using an inner thread pool.
That's actually non-conforming, the standard explicitly says tasks run with std::launch::async
must run as if in a new thread, so any thread-local variables must not persist from one task to another. It doesn't usually matter though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With