[Interest] Best way to invoke a slot after some time with QObject::sender

BRM 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:
>> Hiya,
>>
>> 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[1] 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.

http://doc.qt.nokia.com/4.7-snapshot/qmetamethod.html#invoke

Ben




More information about the Interest mailing list