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
|
\nextpage Synchronizing Threads
|
||||||
|
|
||||||
Qt offers many classes and functions for working with threads. Below are
|
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.
|
multithreaded applications.
|
||||||
|
|
||||||
|
|
||||||
@ -163,19 +163,47 @@
|
|||||||
\section1 Qt Concurrent: Using a High-level API
|
\section1 Qt Concurrent: Using a High-level API
|
||||||
|
|
||||||
The \l{Qt Concurrent} module provides high-level functions that deal with some
|
The \l{Qt Concurrent} module provides high-level functions that deal with some
|
||||||
common parallel computation patterns: map, filter, and reduce. Unlike QThread
|
common parallel computation patterns: map, filter, and reduce. Unlike using
|
||||||
and QRunnable, these functions do not require the use of low-level threading
|
QThread and QRunnable, these functions never require the use of \l{Synchronizing
|
||||||
primitives such as mutexes or semaphores. \l {Qt Concurrent} will automatically
|
Threads#Low-Level Synchronization Primitives}{low-level threading primitives}
|
||||||
adjust the number of threads used according to the number of processor cores
|
such as mutexes or semaphores. Instead, they return a QFuture object which can
|
||||||
available, so applications written today will continue to scale when deployed
|
be used to retrieve the functions' results when they are ready. QFuture can
|
||||||
later on a system with more cores.
|
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
|
\l{Qt Concurrent}'s map, filter and reduce algorithms automatically distribute
|
||||||
any function in a thread managed by the global QThreadPool.
|
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.
|
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
|
\section1 Choosing an Appropriate Approach
|
||||||
|
|
||||||
As demonstrated above, Qt provides different solutions for developing threaded
|
As demonstrated above, Qt provides different solutions for developing threaded
|
||||||
@ -187,52 +215,62 @@
|
|||||||
|
|
||||||
\table
|
\table
|
||||||
\header
|
\header
|
||||||
\li Feature/Characteristic
|
\li Feature
|
||||||
\li QThread
|
\li QThread
|
||||||
\li QRunnable
|
\li QRunnable and QThreadPool
|
||||||
\li Qt Concurrent\sup{*}
|
\li QtConcurrent::run()
|
||||||
|
\li Qt Concurrent (Map, Filter, Reduce)
|
||||||
|
\li WorkerScript
|
||||||
\row
|
\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 Yes
|
||||||
\li
|
\li
|
||||||
\li
|
\li
|
||||||
|
\li
|
||||||
\row
|
\row
|
||||||
\li Supports an event loop
|
\li Thread can run an event loop
|
||||||
\li Yes
|
\li Yes
|
||||||
\li
|
\li
|
||||||
\li
|
\li
|
||||||
|
\li
|
||||||
|
\li
|
||||||
\row
|
\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 Yes (received by a worker QObject)
|
||||||
\li
|
\li
|
||||||
\li
|
\li
|
||||||
|
\li
|
||||||
|
\li Yes (received by WorkerScript)
|
||||||
\row
|
\row
|
||||||
\li Supports controlling the thread using signals
|
\li Thread can be controlled using signals
|
||||||
\li Yes (received by QThread)
|
\li Yes (received by QThread)
|
||||||
\li
|
\li
|
||||||
|
\li
|
||||||
\li Yes (received by QFutureWatcher)
|
\li Yes (received by QFutureWatcher)
|
||||||
|
\li
|
||||||
\row
|
\row
|
||||||
\li Supports thread reuse
|
\li Thread can be monitored through a QFuture
|
||||||
\li
|
\li
|
||||||
|
\li
|
||||||
|
\li Partially
|
||||||
\li Yes
|
\li Yes
|
||||||
\li Yes
|
\li
|
||||||
\row
|
\row
|
||||||
\li Task-oriented
|
\li Built-in ability to pause/resume/cancel
|
||||||
\li
|
\li
|
||||||
\li Yes
|
|
||||||
\li Yes
|
|
||||||
\row
|
|
||||||
\li High level API
|
|
||||||
\li
|
\li
|
||||||
\li
|
\li
|
||||||
\li Yes
|
\li Yes
|
||||||
\row
|
|
||||||
\li Supports pausing/resuming/canceling
|
|
||||||
\li
|
\li
|
||||||
\li
|
|
||||||
\li Yes
|
|
||||||
\endtable
|
\endtable
|
||||||
\sup{\e{*Except QtConcurrent::run(), which is like QRunnable}}
|
|
||||||
|
|
||||||
|
|
||||||
\section2 Example Use Cases
|
\section2 Example Use Cases
|
||||||
@ -244,7 +282,7 @@
|
|||||||
\li Solution
|
\li Solution
|
||||||
\row
|
\row
|
||||||
\li One call
|
\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.
|
updates during the run.
|
||||||
\li Qt provides different solutions:
|
\li Qt provides different solutions:
|
||||||
\list
|
\list
|
||||||
@ -256,6 +294,13 @@
|
|||||||
\li Run the function using QtConcurrent::run(). Write to a \l{Synchronizing
|
\li Run the function using QtConcurrent::run(). Write to a \l{Synchronizing
|
||||||
Threads}{thread-safe variable} to update progress.
|
Threads}{thread-safe variable} to update progress.
|
||||||
\endlist
|
\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
|
\row
|
||||||
\li One call
|
\li One call
|
||||||
\li Perform an operation on all items of a container, using all available
|
\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
|
\li Use Qt Concurrent's \l{QtConcurrent::}{filter()} function to select
|
||||||
container elements, and the \l{QtConcurrent::}{map()} function to apply
|
container elements, and the \l{QtConcurrent::}{map()} function to apply
|
||||||
an operation to each element. To fold the output into a single result,
|
an operation to each element. To fold the output into a single result,
|
||||||
use \l{QtConcurrent::}{filterReduced()} and \l{QtConcurrent::}{mapReduced()}
|
use \l{QtConcurrent::}{filteredReduced()} and
|
||||||
instead.
|
\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
|
\row
|
||||||
\li Permanent
|
\li Permanent
|
||||||
\li Have an object living in another thread that can perform different
|
\li Have an object living in another thread that can perform different
|
||||||
|
Loading…
Reference in New Issue
Block a user