[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