On Wednesday 10 October 2012 17:45:51 Giuseppe D'Angelo wrote: > On 10 October 2012 16:00, Tony Van Eerd <[email protected]> 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.
If you connect to an object living in the finishing thread, it will be a direct conection. Also, you could explicitly state Qt::DirectConnection while connecting. > 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) You can safely delete a QThread once the finished signal has been emitted (tested in tst_QThread::destroyFinishRace ) > , 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. We solve it in a similar way, but you can't keep the mutex locked while emiting finished, since signal directly connected to it would possibly lock other mutex and then run into a dead lock. Generaly, you can't keep a mutex locked when you call "user" code (emitting signals or calling virtual method). > 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++. moveToThread(this) is really a bad idea. deleting the QThread object in a slot dirrectly connected to finished is an undefined behaviour, likely a crash. We don't want to support this. > 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. -- Olivier Woboq - Qt services and support - http://woboq.com _______________________________________________ Development mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/development
