[Development] QThread usage/guidance
Giuseppe D'Angelo
dangelog at gmail.com
Wed Oct 10 18:45:51 CEST 2012
On 10 October 2012 16:00, Tony Van Eerd <tvaneerd at rim.com> wrote:
> I don't have any use cases, but I can't imagine the example recommendation
> of
>
> connect(thread, SIGNAL(finished()), worker, SLOT(deleteLater()));
>
> working as expected unless deleteLater() happens on the same thread as
> finished(), via a direct call.
Why do you say so?
Without looking at the implementation, the theory should tell us:
1) finished() emitted from the "new thread", QThread living in the
"parent thread": a queued call is used automatically. Since you can't
be certain about when the event loop in the parent thread picks the
deletion event up (*) and tries to delete the QThread object (which
can happily crash your program, if the managed thread is still
running), lock a mutex before emitting finished() and unlock it when
you're really done with the thread. Then lock the same mutex in the
QThread dtor, so it can't be run while you're cleaning up.
(*) ... the long story is that first the metacall event is picked up,
which causes deleteLater to be called, which in turn posts the
deferred delete event.
2) finished() emitted from the "new thread", QThread living in its
thread (moveToThread(this), etc.): direct connection used
automatically, which will cause deleteLater to immediately post a
deferred delete event. It will be picked up some time later (i.e. it
won't deadlock with the aforementioned mutex), when the last round of
deferred events is dispatched. By carefully coding it, you can achieve
"delete this" in C++.
3) finished() emitted from the "parent thread", QThread living in the
"parent thread": this requires us to reason about how do you emit such
signal from the parent thread. If you resort to post an event to the
QThread instance, event which will be dispatched from the parent
thread's event loop and will cause the emission of the signal, you
pretty much reinvented 1)... (Before you think about doing something
strange, you can't emit Qt signals from, say, UNIX signal handlers.)
4) finished() emitted from the "parent thread", QThread living in its
thread: this can't work in all cases, as the deletion event may be
posted (to the thread's own event loop) after the thread itself has
fully finished. In other words, this will leak the QThread instance;
it's the equivalent of posting an event to an object living in a
thread without an event loop running.
Cheers,
--
Giuseppe D'Angelo
More information about the Development
mailing list