[Interest] Best way to invoke a slot after some time with QObject::sender
bm_witness at yahoo.com
Tue Aug 28 15:20:23 CEST 2012
> From: Bo Thorsen <bo at fioniasoftware.dk>
>Den 28-08-2012 04:10, Preet skrev:
>> I have a project where I'm trying to asynchronously reply to a signal.
>> So if ObjectA sends ObjectB a signal, ObjectB will send ObjectA a
>> reply signal at some later point in time. ObjectA is guaranteed to be
>> alive when ObjectB decides to send a reply. ObjectAs and ObjectB also
>> live in different QThreads. ObjectB doesn't know about ObjectA in
>> advance, so I use QObject::sender() to store ObjectA's pointer in a
>> queue for when ObjectB is ready to reply. There are many such
>> "ObjectA"s out there that ObjectB can reply to.
>> I see three ways to implement this in an application:
>> When ObjectB is ready to reply,
>> 1 have it connect to the right ObjectA, emit a signal, then disconnect.
>> 2 use QMetaObject::invoke() to invoke the right ObjectA's corresponding slot
>> 3 be connected to all ObjectA's and just emit a signal with the
>> QObject sender pointer; this way the ObjectAs can filter out which
>> signals are for them in the slot itself
>> I'd like to know what the best method is in terms of speed/minimal
>> complexity, or if there's a better method I haven't listed. ObjectB
>> may be required to send hundreds of replies every second, so speed is
>> important. 3 seems like its the worst, since every reply will invoke
>> multiple slots. 1 and 2 seem similar; I'm kind of concerned about
>> calling "connect" and "disconnect" so often in 1.
>The third is the worst, if you have a bunch of ObjectA's. If you only
>have a couple of them, this is by far the best. Because this also means
>you don't have to worry about whether the object has been deleted since
>it emitted the signal.
>The first actually uses the second, because those are cross thread
>signal slot connections. But by using the connect, you will
>automatically get the call moved across to the other thread. If you use
>invoke, you don't get this. If it's okay to call across threads, invoke
>is the fastest.
>You have to figure out how to make sure the ObjectA still exists at the
>point where ObjectB wants to call it. This is the part that really
>worries me with the situation you have described here.
>Instead of doing this, I'd probably implement some kind of multiplexer
>object that sits between the two threads and handles all the
>communication and knows the lifetime of both ObjectA and ObjectB.
>Whether you would want one big object that handles all of them, or
>create a connection object for each connect, that's up to you.
I had a similar situation where I had an inverse of QSignalMapper - I had a signal with a QByteArray for data and a uint32_t "key".
Only receives with the same "key" were to get the data. The senders, multiplexer, and receives were all in their own threads.
Now, the nice thing about #2 is that QMetaMethod::invoke()'s second argument is the same as the last argument in QObject::connect().
Would it not be wrong to say that that handles the movement across the threads for you then? It's worked very well for me at least.
More information about the Interest