Overview :
I have a client-server implementation, which uses DBus(sdbus-c++) to send asynchronous requests to a server. Now my server interacts with hardware APIs which behaves synchronously and also takes significant time to generate a reply. So I have a std::queue
at server, that holds all the asynchronous requests received, and processes them one by one. After processing the server, sends the reply back in the form of callback that was registered for the request sent.
#client.h
class Client
{
Client();
~Client();
void sendRequestA()
{
... use DBus async call to send request to server
}
void sendRequestB() {...}
protected:
virtual void replyCallbackA(const uint8_t& status) = 0 ; // ... callback invoked by the DBus server
virtual void replyCallbackB(const uint8_t& status) = 0 ;
}
Ì am facing issues with using std::async
to test this particular usecase.
#test.cpp
//std::future<void> gFuture;
class ClientTest : public Client
{
ClientTest();
~ClientTest();
std::future<void> m_future;
virtual void replyCallbackA(const uint8_t& status) override
{
std::cout<<"replyCallbackA status = "<< status<< "\n";
m_future.get();
//gFuture.get();
}
virtual void replyCallbackB(const uint8_t& status) override
{
std::cout<<"replyCallbackB status = "<< status<< "\n";
m_future.get();
//gFuture.get();
}
}
int main()
{
ClientTest cTest;
cTest.m_future = std::async(std::launch::async, &ClientTest::sendRequestA, &cTest);
cTest.m_future = std::async(std::launch::async, &ClientTest::sendRequestB, &cTest);
//gFuture = = std::async(std::launch::async, &ClientTest::sendRequestA, &cTest); -- no change in behavior with use of a global std::future.
}
My understanding here was that the sendRequestA
& sendRequestB
, would be called and as well the callback functions will be invoked.
However, in this case, the main
exits immediately after calling the sendRequestA
& sendRequestB
and the callback response is not received.
Edit: I have also tried using a global variable for std::future
, but the behavior was the same.
Could anyone tell where my understanding is at fault?
std::async
returns a future that completes with the return value of the function passed to std::async
.
The second assignment to the future will block until the call to sendRequestA
completes (it blocks because of the destructor of the previous std::future
instance). It does not wait until the reply callback is received (unless you are blocking in sendRequestA
but that would be strange).
m_future.get()
in your reply callbacks will block until the future is resolved (sendRequestA
returns). However, it will have been sent already (because that is the only way you would get a reply) and so the .get()
call would return immediately.
I think you want to be using something more like std::promise
. In your reply callback you would call std::promise::set_value
to resolve the future. Calls to the destructor of the future associated with the std::promise
or to std::future::get
will block until std::promise::set_value
is called (or the promise is destroyed).