[Development] invokeMethod() with function pointers
Thiago Macieira
thiago.macieira at intel.com
Sat Jan 21 00:20:53 CET 2017
On sexta-feira, 20 de janeiro de 2017 17:34:50 PST Grégoire Barbier wrote:
> > See the discussion in https://codereview.qt-project.org/83404/ for why
> > this is not a good idea.
> > In summary, BlockingQueuedConnection is dangerous as it can lead to
> > deadlock if the other thread is waiting on your thread. In order to use
> > it properly, you really need to know, while programming in which thread
> > you are and which thread you try to communicate to, and be sure that
> > there is never in your program cases where the other thread may be
> > waiting on a QWaitCondition for your other thread. So this pattern with
> > QThread::currentThread() == this->
> >>thread() before a BlockingQueuedConnection is really dangerous.
> I respect the fact that you rejected Qt::BlockingAutoConnection in 2014
> because of its potential danger, but I'm not sure that it's better to
> let people use the "QThread::currentThread() == this" pattern without
> being warned rather than implementing Qt::BlockingAutoConnection, with a
> detailed warning in the doc.
It's a shift of responsibility. If we had the BlockingAutoConnection (or
SynchronousConnection, which is what I wanted to call it during Qt 4.5 when I
first proposed it), the deadlock would be Qt's fault. Since it's you doing
that, the deadlock becomes your fault and you're the one who needs to fix it.
> Moreover, I don't understand whi BlockingAutoConnection would be more
> dangerous (if it were to be added) than BlockingQueuedConnection is
> currently already dangerous.
Think about this: QueuedConnection and BlockingQueuedConnection chase the
target object across moveToThreads. That is, if thread A is doing
invokeMethod() while thread B does obj->moveToThread(C), then the invocation
chases obj to thread C. That's a good thing.
But what happens if it got moved to thread A? Since thread A is blocked on a
semaphore wait, it can't handle the incoming metacall event. That's a
deadlock.
What's more, we can't solve it: even if we could detect the deadlock formation
before it happens (and I'm not sure we can), we'd need to pick the metacall
event out of the event queue, which means it could jump the queue and things
would execute in the wrong order. So, no, it's impossible to implement
BlockingAutoConnection so long as the object can be moved back to the calling
thread.
> With your own words from 2014:
>
> """
> I would not even try to solve this race with moveToThead, as a mention,
> i think we just need to document that one must not call moveToThread
> when Blocking connecitona re involved.
> """
>
> Maybe it would be interesting to set this comment in enum
> Qt::ConnectionType doc, just right to Qt::BlockingQueuedConnection (or a
> would-be Qt::BlockingAutoConnection) and not only in the "Signals and
> Slots Across Threads" paragraph, to make everything safer with noobs
> (like me) that do not read the whole docs but only spam the F1 key from
> with Qt Creator.
Adding the warning to BlockingQueuedConnection is a good idea.
> > On the other hand, it would be useful to get the return value of a
> > QueuedConnection in a QFuture.
That's no different than a QueuedConnection with a posted event back with the
result. In fact, we have a very good implementation for "post event back with
result": we call it a "signal-slot connection".
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
More information about the Development
mailing list