[Development] Evolving Qt's multithreading API

Thiago Macieira thiago.macieira at intel.com
Sat Feb 23 18:24:44 CET 2013


On sábado, 23 de fevereiro de 2013 20.26.11, Sze Howe Koh wrote:
> On 23 February 2013 00:11, Thiago Macieira <thiago.macieira at intel.com> 
wrote:
> > The fact is that any QObject that is returned from those functions -- if
> > any -- must belong to the calling thread. That implies the necessary
> > guarantees in terms of signal emissions.
> > 
> > For example, if the functions return a QObject pointer, a signal-signal
> > connection from the actual target object's finished() signal to the
> > returned object's finished() will apply the necessary queueing semantics.
> > 
> > That also speaks against returning a QThread*.
> 
> I haven't understood your point, sorry. Can you please clarify what
> "necessary guarantees" you were referring to, and how this "speaks
> against returning a QThread*"?

Sure.

This is an un-optimised approach. There are a few ways to make it more 
efficient, but that's for later.

Suppose we have:
	Result *QThread::start(<task functor or object>)

Internally, it will use an internal class derived from QThread that runs the 
task in its run() function. When the thread finishes, QThread finished(). Now, 
as you noticed, unless we do something, the thread could start and finish 
before the user has a chance to connect the finished() signal from the returned 
object.

What I am suggesting is a trampoline object: in the setup phase, a this 
trampoline QObject is created and it contains just one signal: finished(). That 
signal is connected to the Result object's finished(). When the task finishes 
and run() is about to return, it emits that signal -- from the auxiliary 
thread. That means the actual thread might have emitted finished(), but the 
Result object didn't -- that can only happen at the next event loop iteration, 
due to the queue semantics.

So you note that the returned object cannot be the QThread that we created. It 
must be something else. Interestingly, since it can't be the QThread, it means 
the trampoline object *can* be the QThread: we just need to connect 
QThread::finished() to QThreadTask::finished().

> I thought QThread and QFutureWatcher were designed to signal the
> status of the new thread while living in the original thread. I also
> couldn't find a need to link up 2 finished() signals -- QThread will
> emit finished() when QThread::run() returns, and QFutureWatcher emits
> finished() in response to a callout event, not another signal.

QThread signals the status of the thread, but QFutureWatcher signals the 
status of the future, the task. The thread itself may not have finished.

What I'm saying is that you should not return a QThread, but something else. 
And then you can connect QThread's finished() signal to that something else's 
finished(). As I described above, that alone will be enough to guarantee the 
right semantics.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.qt-project.org/pipermail/development/attachments/20130223/4ded9fb8/attachment.sig>


More information about the Development mailing list