[Development] Evolving Qt's multithreading API

Sze Howe Koh szehowe.koh at gmail.com
Mon Mar 4 08:58:51 CET 2013

On 26 February 2013 00:06, Thiago Macieira <thiago.macieira at intel.com> wrote:
> Now you're mixing things. First we choose the API: does it start automatically
> or not? After we've done that, we choose how to implement it and that is an
> implementation detail.

Ok. I don't think I can see the big picture just yet, but I get the
impression that users would like the ability to choose between
auto-start and manual-start.

>> Then, should we put this new function outside the QThread class? The
>> task-management interface feels like it abstracts away the underlying
>> QThread, so it would be messy to mix the API.
> We could do that, but I think that putting it in QThread also makes sense
> because that's where people will go to look for it.
> If this method is restricted to a run-replacement -- a static method that
> takes a lambda -- then it should be in QThread and it should return a
> QThread*. It should not be more complex than that.

I initially thought the same as your last paragraph, but Corentin
raised an important point: It's not easy to retrieve the return value
this way.

Later, I realized that this discussion actually stemmed from two
subtly different ideas with subtly different goals. I've tried to
compare & contrast them in the attached diagram (but with updates to
my original proposal). The 2 ideas are:
1) Unify and extend the coverage of existing low-level API (with an
extra: ability to specify auto/manual management)
2) Rewrite or replace the high-level QtConcurrent::run() (with an
extra: allow QRunnable to be used outside of a thread pool)

My proposal to unify the low-level API came about because Qt's
threading approaches feel disparate and "tacked on" (although I don't
know if this was actually the case):
- QThreadPool + QRunnable feels tacked on top of QThread
- The default implementation of QThread::run() feels tacked on top of
an abstract QThread
- QtConcurrent::run() feels tacked on top of the filter-map-reduce
framework and QThreadPool -- most of QFuture's features are exposed
but non-functional for QtConcurrent::run()

We could be in danger of continuing this pattern if we simply add
either of the 2 ideas into Qt. I think we should tackle this
holistically: Itemize all the new abilities that we want, and work out
where they fit in relation to each other and in relation to the
existing framework. Perhaps we should separate out the low-level and
high-level parts of our new API -- the former for fine-grained control
and the latter for simplicity.

The various "requirements" identified so far are:
- Ability to run any function in a new thread or a user-specified thread pool
- Ability to run a QRunnable outside a thread pool
- Ability to specify manual/auto start/delete
- Fast start, if automatic
- Ability to interact with the thread (e.g. query, wait, quit),
including signal/slot interactions
- Better support for clean thread cancellation
- Minimal object construction/destruction on the user side
- Ability to retrieve return value
- Clean, unified and intuitive API

Other relevant suggestions put forward so far:
- Import a 3rd-party, high-level task parallelization library
- Bring Qt Creator's runextensions.h upstream
- Accept an optional _then_ function pointer, to be executed upon
thread completion

I'll continue mapping things out (Stop me if I'm heading the wrong way)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: thread_ideas.png
Type: image/png
Size: 123121 bytes
Desc: not available
URL: <http://lists.qt-project.org/pipermail/development/attachments/20130304/59cdfd0a/attachment.png>

More information about the Development mailing list