[Interest] Poor QMethod::invoke performance across threads on i.MX53

Bo Thorsen bo at vikingsoft.eu
Thu May 28 07:22:35 CEST 2015


Den 27-05-2015 kl. 23:16 skrev Matthew Woehlke:
> On 2015-05-27 16:41, Thiago Macieira wrote:
>> On Wednesday 27 May 2015 15:02:36 Matthew Woehlke wrote:
>>> On 2015-05-18 03:46, Thiago Macieira wrote:
>>>> On Thursday 14 May 2015 18:18:52 Robert Daniels wrote:
>>>>>          moveToThread(this);
>>>>
>>>> This is wrong. Never do "moveToThread(this)", since it's very difficult to
>>>> then destroy the QThread object. This is unrelated to the problem and
>>>> it's probably only for simplicity of your testcase.
>>>
>>> Sort of OT, but... why? If the object in question is destroyed by the
>>> same thread that created it, after the thread that the object
>>> "represents" has terminated cleanly, what is the problem?
>>
>> The problem is a QThread living inside the thread that it started.
>>
>> You can't destroy that object inside that thread because the QThread
>> destructor will wait() until the thread exits. And the thread can't exit until
>> the destructor has returned. That's a deadlock.
>
> Right. An example probably helps. What's wrong with this approach?
>
>    class MyThread : public QThread { ... } // has moveToThread(this)
>
>    int main()
>    {
>      auto* t = new MyThread;
>      t.start();
>      // ...
>      t.wait();
>      delete t; // QThread deleted from main thread, not itself
>    }
>
> The QThread is memory-managed from a thread other than itself. It's just
> that the thread affinity is circular. Note that I am *NOT* trying to
> deleteLater the QObject! (Because, yes, that would be horrible! And for
> that matter, would leak, since in my usage, the thread has exited before
> I try to delete it.)
>
> Anyway, a more accurate depiction of my case is:
>
>    class MyThread : public QObject
>    {
>      QThread self;
>      MyThread() { moveToThread(self); }
>    }
>
> ...where again, it is assumed that MyThread is deleted from a thread
> other than MyThread::self. Is this approach broken? (I think no? It
> seems similar to the alternate approach you gave.)

There are a lot of problems with this. Thiago already gave you a couple 
of them. Here are two more:

The finished() signal on QThread - which thread do you expect this to 
run in? And which thread would you expect a slot connected to it to run in?

What about objects with your thread as parent? Those will all be deleted 
by the wrong thread. If you delete them all before the thread itself is 
deleted, then you can only have a single reason left for 
moveToThread(this): Signals and slots on the QThread. Refactor your code 
and create another object that does all the work you put in the run instead.

QThread is an object that you should think of as living between the two 
threads. The object itself is running in the creating thread, anything 
in run() and objects moved to this thread is in the created thread. The 
signals it emits have clearly defined threads they are emitted in - 
finished() in the creating thread, started() in the created etc.

It's not that you can't create code with your way that will work. It's 
more that it will be impossible for anyone schooled in the "proper" way 
of thinking to know what's going on. You will create weird bugs that are 
very hard to fix with this approach.

Bo.

-- 
Viking Software
Qt and C++ developers for hire
http://www.vikingsoft.eu



More information about the Interest mailing list