I have a signal/slot arrangement for an asynchronous call to request data. Normally that's fine as received data just updates controls. But in a couple instances I have to wait for the reply to the request to be sure an action is complete before moving to the next step. There is a signal that is fired every time valid received data is queued.
There is also a need for blocking writes, but the read/write mechanisms are almost identical.
The following code pattern, using a local event loop, is (I believe) a standard pattern for waiting for a signal.
But the signal is sent with extra data, in this case the address and other stuff.
I need to check that the signal was the one associated with the request or I may continue to the next step far too soon.
How do I receive that extra (address) data when the receiving slot does not know how to handle it, as in this case the slot is an event loop (or a timer).
Do I really have to subclass an QEventLoop or is there a simpler way?
The following is a slightly simplified/contrived example.
quint16 System::blockingRead(quint16 address)
{
QTimer timer;
timer.setSingleShot(true);
QEventLoop loop;
connect( this, &System::readComplete, &loop, &QEventLoop::quit );
connect( &timer, &QTimer::timeout, &loop, &QEventLoop::quit );
timer.start(3000);
ReadFromSystem(address); // Asynchronous call
bool waiting = true;
bool timeout = false
do {
loop.exec();
waiting = loop.getReceivedAddress() == address;
timeout = not timer.isActive();
while(waiting and not timeout);
if(not timeout) {
return(loop.getExtraData());
}
else {
throw ECRException();
qDebug("timeout");
}
}
Final solution without re-writing the entire thing.
Subclass QEventLoop, passing the expected address, then add a check on the received queue item address.
If the expected address turns up in the queue then the loop can quit the event loop and return expected value.
If the timer expires then we've waited too long so raise an exception and also quit the event loop.
Existing code emits readComplete(TransportReply *) every time a valid frame is decoded.
In sys.h
in sys.cpp