Doc: Expand thread technology comparisons
Additions/Changes: - Add QML's WorkerScript type - Add QFuture + QFutureWatcher - Clarify differences between QtConcurrent::run() and the map/filter/ reduce functions - Reword table headings - QThreadPool accepts a priority parameter too (although it's not OS- level, unlike QThread) Rows removed from the table: - QThread can be "reused" and "task oriented" too, depending on the program design. It's hard to convey this in a table though, so I just removed it. - "High level" is ambiguous and doesn't really help readers choose a tool to use. Task-number: QTBUG-33360 Change-Id: Idc5100eaf09033998c155572d44c6c0ad0ba9ef6 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
6e4ea62b0a
commit
fd82caf44f
@ -123,7 +123,7 @@
|
||||
\nextpage Synchronizing Threads
|
||||
|
||||
Qt offers many classes and functions for working with threads. Below are
|
||||
three different approaches that Qt programmers can use to implement
|
||||
four different approaches that Qt programmers can use to implement
|
||||
multithreaded applications.
|
||||
|
||||
|
||||
@ -163,19 +163,47 @@
|
||||
\section1 Qt Concurrent: Using a High-level API
|
||||
|
||||
The \l{Qt Concurrent} module provides high-level functions that deal with some
|
||||
common parallel computation patterns: map, filter, and reduce. Unlike QThread
|
||||
and QRunnable, these functions do not require the use of low-level threading
|
||||
primitives such as mutexes or semaphores. \l {Qt Concurrent} will automatically
|
||||
adjust the number of threads used according to the number of processor cores
|
||||
available, so applications written today will continue to scale when deployed
|
||||
later on a system with more cores.
|
||||
common parallel computation patterns: map, filter, and reduce. Unlike using
|
||||
QThread and QRunnable, these functions never require the use of \l{Synchronizing
|
||||
Threads#Low-Level Synchronization Primitives}{low-level threading primitives}
|
||||
such as mutexes or semaphores. Instead, they return a QFuture object which can
|
||||
be used to retrieve the functions' results when they are ready. QFuture can
|
||||
also be used to query computation progress and to pause/resume/cancel the
|
||||
computation. For convenience, QFutureWatcher enables interactions with
|
||||
\l{QFuture}s via signals and slots.
|
||||
|
||||
This module also provides the QtConcurrent::run() function, which can run
|
||||
any function in a thread managed by the global QThreadPool.
|
||||
\l{Qt Concurrent}'s map, filter and reduce algorithms automatically distribute
|
||||
computation across all available processor cores, so applications written today
|
||||
will continue to scale when deployed later on a system with more cores.
|
||||
|
||||
This module also provides the QtConcurrent::run() function, which can run any
|
||||
function in another thread. However, QtConcurrent::run() only supports a subset
|
||||
of features available to the map, filter and reduce functions. The QFuture
|
||||
can be used to retrieve the function's return value and to check if the thread
|
||||
is running. However, a call to QtConcurrent::run() uses one thread only, cannot
|
||||
be paused/resumed/canceled, and cannot be queried for progress.
|
||||
|
||||
See the \l{Qt Concurrent} module documentation for details on the individual functions.
|
||||
|
||||
|
||||
\section1 WorkerScript: Threading in QML
|
||||
|
||||
The WorkerScript QML type lets JavaScript code run in parallel with the GUI
|
||||
thread.
|
||||
|
||||
Each WorkerScript instance can have one \c{.js} script attached to it. When
|
||||
WorkerScript::sendMessage() is called, the script will run in a separate thread
|
||||
(and a separate \l{QQmlContext}{QML context}). When the script finishes
|
||||
running, it can send a reply back to the GUI thread which will invoke the
|
||||
WorkerScript::onMessage() signal handler.
|
||||
|
||||
Using a WorkerScript is similar to using a worker QObject that has been moved
|
||||
to another thread. Data is transferred between threads via signals.
|
||||
|
||||
See the WorkerScript documentation for details on how to implement the script,
|
||||
and for a list of data types that can be passed between threads.
|
||||
|
||||
|
||||
\section1 Choosing an Appropriate Approach
|
||||
|
||||
As demonstrated above, Qt provides different solutions for developing threaded
|
||||
@ -187,52 +215,62 @@
|
||||
|
||||
\table
|
||||
\header
|
||||
\li Feature/Characteristic
|
||||
\li Feature
|
||||
\li QThread
|
||||
\li QRunnable
|
||||
\li Qt Concurrent\sup{*}
|
||||
\li QRunnable and QThreadPool
|
||||
\li QtConcurrent::run()
|
||||
\li Qt Concurrent (Map, Filter, Reduce)
|
||||
\li WorkerScript
|
||||
\row
|
||||
\li Supports different thread priorities
|
||||
\li API
|
||||
\li C++
|
||||
\li C++
|
||||
\li C++
|
||||
\li C++
|
||||
\li QML
|
||||
\row
|
||||
\li Thread priority can be specified
|
||||
\li Yes
|
||||
\li Yes
|
||||
\li
|
||||
\li
|
||||
\li
|
||||
\row
|
||||
\li Supports an event loop
|
||||
\li Thread can run an event loop
|
||||
\li Yes
|
||||
\li
|
||||
\li
|
||||
\li
|
||||
\li
|
||||
\row
|
||||
\li Supports transferring data to the thread using signals
|
||||
\li Thread can receive data updates through signals
|
||||
\li Yes (received by a worker QObject)
|
||||
\li
|
||||
\li
|
||||
\li
|
||||
\li Yes (received by WorkerScript)
|
||||
\row
|
||||
\li Supports controlling the thread using signals
|
||||
\li Thread can be controlled using signals
|
||||
\li Yes (received by QThread)
|
||||
\li
|
||||
\li
|
||||
\li Yes (received by QFutureWatcher)
|
||||
\li
|
||||
\row
|
||||
\li Supports thread reuse
|
||||
\li Thread can be monitored through a QFuture
|
||||
\li
|
||||
\li
|
||||
\li Partially
|
||||
\li Yes
|
||||
\li Yes
|
||||
\li
|
||||
\row
|
||||
\li Task-oriented
|
||||
\li Built-in ability to pause/resume/cancel
|
||||
\li
|
||||
\li Yes
|
||||
\li Yes
|
||||
\row
|
||||
\li High level API
|
||||
\li
|
||||
\li
|
||||
\li Yes
|
||||
\row
|
||||
\li Supports pausing/resuming/canceling
|
||||
\li
|
||||
\li
|
||||
\li Yes
|
||||
\endtable
|
||||
\sup{\e{*Except QtConcurrent::run(), which is like QRunnable}}
|
||||
|
||||
|
||||
\section2 Example Use Cases
|
||||
@ -244,7 +282,7 @@
|
||||
\li Solution
|
||||
\row
|
||||
\li One call
|
||||
\li Run a linear function within another thread, optionally with progress
|
||||
\li Run a new linear function within another thread, optionally with progress
|
||||
updates during the run.
|
||||
\li Qt provides different solutions:
|
||||
\list
|
||||
@ -256,6 +294,13 @@
|
||||
\li Run the function using QtConcurrent::run(). Write to a \l{Synchronizing
|
||||
Threads}{thread-safe variable} to update progress.
|
||||
\endlist
|
||||
\row
|
||||
\li One call
|
||||
\li Run an existing function within another thread and get its return value.
|
||||
\li Run the function using QtConcurrent::run(). Have a QFutureWatcher emit
|
||||
the \l{QFutureWatcher::}{finished()} signal when the function has
|
||||
returned, and call QFutureWatcher::result() to get the function's return
|
||||
value.
|
||||
\row
|
||||
\li One call
|
||||
\li Perform an operation on all items of a container, using all available
|
||||
@ -263,8 +308,17 @@
|
||||
\li Use Qt Concurrent's \l{QtConcurrent::}{filter()} function to select
|
||||
container elements, and the \l{QtConcurrent::}{map()} function to apply
|
||||
an operation to each element. To fold the output into a single result,
|
||||
use \l{QtConcurrent::}{filterReduced()} and \l{QtConcurrent::}{mapReduced()}
|
||||
instead.
|
||||
use \l{QtConcurrent::}{filteredReduced()} and
|
||||
\l{QtConcurrent::}{mappedReduced()} instead.
|
||||
\row
|
||||
\li One call/Permanent
|
||||
\li Perfrom a long computation in a pure QML application, and update the GUI
|
||||
when the results are ready.
|
||||
\li Place the computation code in a \c{.js} script and attach it to a
|
||||
WorkerScript instance. Call \l{WorkerScript::}{sendMessage()} to start the
|
||||
computation in a new thread. Let the script call WorkerScript::sendMessage()
|
||||
too, to pass the result back to the GUI thread. Handle the result in
|
||||
\l{WorkerScript::}{onMessage} and update the GUI there.
|
||||
\row
|
||||
\li Permanent
|
||||
\li Have an object living in another thread that can perform different
|
||||
|
Loading…
Reference in New Issue
Block a user