PDA

View Full Version : Waiting for signal and getting result



midas643
8th April 2016, 09:54
Hello :-). I'm wondering if it's possible to get. result from signal lets say I've got onFinished(bool) signal and I'd like to make synchronous function that waits for this signal and returns bool from slot argument. It's possible to wait using QEventLoop but therr. is no way to return value. QFuture is what I need but it only works with QtConcurrent. I'd need something like QFuture but with possibility to manually set result.

anda_skoa
8th April 2016, 11:01
While it is usually not a good idea to simulate blocking with a nested event loop, I don't see why that would make it impossible to return anything.

Cheers,
_

midas643
8th April 2016, 11:50
Is it possible? Could you propose some kind of solution? That would be good because I could do everything linear then. Like:


if(asyncCallMadeSynchronous()) // returning result of slot or something like that
{
doSomethingElse();
}

One solution is to store some kind of variable in my class like result, set it inside slot and return it after eventLoop.exec(); but I don't think it's pretty and would work as expected.

with signals I have to wrap all this code inside slots and write specific ifs and this is usually more lines to write and I can't really find a good design for this. But that's fine if it's impossible. I will have to find some other way to write my code.

In C# there's something like TaskCompletionSource to manually control task state(in Qt, task is similar to QFuture). And I'm looking for something similar to reproduce it.
I was also thinking to extend QFuture somehow, to try re-implement TaskCompletionSource.

Any ideas ? :o

anda_skoa
8th April 2016, 13:26
if(asyncCallMadeSynchronous()) // returning result of slot or something like that
{
doSomethingElse();
}

As long as you are aware that this is not really blocking synchronous and you can deal with the potential reentrancy.
Experience says that a lot of people who write such things are super surprised when functions like that are called twice without having finished yet, etc.



One solution is to store some kind of variable in my class like result, set it inside slot and return it after eventLoop.exec(); but I don't think it's pretty and would work as expected.

Yes, that would definitely work.
Or you connect to a lambda that captures a local variable by reference (and disconnect once you are done) or you use QSignalSpy, or a receiver object that combines your suggestion and the nested event loop.



I was also thinking to extend QFuture somehow, to try re-implement TaskCompletionSource.

You can also return a "job" object that you can "exec" like a dialog.

But again, in all these sases make sure you are aware of the consequences of nested event loops.

Cheers,
_

midas643
8th April 2016, 13:56
Or you connect to a lambda that captures a local variable by reference (and disconnect once you are done) or you use QSignalSpy, or a receiver object that combines your suggestion and the nested event loop.
_

QSignalSpy seems nice. I don't really get capturing local variable by reference.



You can also return a "job" object that you can "exec" like a dialog.
_

What's the "job" object? Should I make my own class for that?
I've noticed that:


int QEventLoop::exec ( ProcessEventsFlags flags = AllEvents )
Enters the main event loop and waits until exit() is called. Returns the value that was passed to exit().

Can I pass the value to exit SLOT using some signal ?
OK. I can't, it's possible with exit method though.



But again, in all these sases make sure you are aware of the consequences of nested event loops.
_

What are the consequences of nested event loops ?

Thanks for responses :) very very helpful.

anda_skoa
8th April 2016, 14:16
QSignalSpy seems nice. I don't really get capturing local variable by reference.

Something like this:


bool result = false;
QEventLoop l;
auto connectionHandle = connect(sender, &Sender::onFinished, [&result, &l](bool b) { result = b; l.quit(); });
l.exec();
disconnect(connectionHandle);
return result;




What's the "job" object? Should I make my own class for that?

Yes, a job would be an object of a class that encapsulates all data and state for an asynchronous operation.
See for example QNetworkReply.


Can I pass the value to exit SLOT using some signal ?

Not directly, QEventLoop::exit() is not a slot.
Of course you can use a slot, function or lambda that gets connected to and which then calls exit.



What are the consequences of nested event loops ?

As I said above: a nested event loop can lead to reentrancy-like situations.
The call appears to be synchronous to a reader but of course it is not.
Other events (user interaction, timers, sockets, etc) can lead to the method being called again, or the object that has this method being destroyed, etc.

Cheers,
_