Doc: Move threading overviews from qtbase.git to qtdoc.git

- This topic is  relevant to multiple modules, as illustrated by the
  "Thread-Support in Qt Modules" page. Multithreading can be done in
  both C++ and QML.
- Moving also fixes links to QML-related pages.
- Snippets are copied, not moved. QThreadStorage docs need them.
- QDoc: "DEPENDS += qtdoc" added to keep the "\reentrant" command
  working. It creates a link to the "reentrant" keyword.

Change-Id: I2cdf6139e62d66911561c30fcca7aab160a694b1
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
This commit is contained in:
Sze Howe Koh 2013-11-07 00:24:20 +08:00 committed by The Qt Project
parent 8647bac9cf
commit 706eeadf3a
5 changed files with 1 additions and 1073 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,244 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page thread-basics.html
\ingroup tutorials
\startpage {index.html}{Qt Reference Documentation}
\title Threading Basics
\brief An introduction to threads
\section1 What Are Threads?
Threads are about doing things in parallel, just like processes. So how do
threads differ from processes? While you are making calculations on a
spreadsheet, there may also be a media player running on the same desktop
playing your favorite song. Here is an example of two processes working in
parallel: one running the spreadsheet program; one running a media player.
Multitasking is a well known term for this. A closer look at the media
player reveals that there are again things going on in parallel within one
single process. While the media player is sending music to the audio driver,
the user interface with all its bells and whistles is being constantly
updated. This is what threads are for -- concurrency within one single
process.
So how is concurrency implemented? Parallel work on single core CPUs is an
illusion which is somewhat similar to the illusion of moving images in
cinema.
For processes, the illusion is produced by interrupting the processor's
work on one process after a very short time. Then the processor moves on to
the next process. In order to switch between processes, the current program
counter is saved and the next processor's program counter is loaded. This
is not sufficient because the same needs to be done with registers and
certain architecture and OS specific data.
Just as one CPU can power two or more processes, it is also possible to let
the CPU run on two different code segments of one single process. When a
process starts, it always executes one code segment and therefore the
process is said to have one thread. However, the program may decide to
start a second thread. Then, two different code sequences are processed
simultaneously inside one process. Concurrency is achieved on single core
CPUs by repeatedly saving program counters and registers then loading the
next thread's program counters and registers. No cooperation from the
program is required to cycle between the active threads. A thread may be in
any state when the switch to the next thread occurs.
The current trend in CPU design is to have several cores. A typical
single-threaded application can make use of only one core. However, a
program with multiple threads can be assigned to multiple cores, making
things happen in a truly concurrent way. As a result, distributing work
to more than one thread can make a program run much faster on multicore
CPUs because additional cores can be used.
\section2 GUI Thread and Worker Thread
As mentioned, each program has one thread when it is started. This thread
is called the "main thread" (also known as the "GUI thread" in Qt
applications). The Qt GUI must run in this thread. All widgets and several
related classes, for example QPixmap, don't work in secondary threads.
A secondary thread is commonly referred to as a "worker thread" because it
is used to offload processing work from the main thread.
\section2 Simultaneous Access to Data
Each thread has its own stack, which means each thread has its own call
history and local variables. Unlike processes, threads share the same
address space. The following diagram shows how the building blocks of
threads are located in memory. Program counter and registers of inactive
threads are typically kept in kernel space. There is a shared copy of the
code and a separate stack for each thread.
\image threadvisual-example.png "Thread visualization"
If two threads have a pointer to the same object, it is possible that both
threads will access that object at the same time and this can potentially
destroy the object's integrity. It's easy to imagine the many things that
can go wrong when two methods of the same object are executed
simultaneously.
Sometimes it is necessary to access one object from different threads;
for example, when objects living in different threads need to communicate.
Since threads use the same address space, it is easier and faster for
threads to exchange data than it is for processes. Data does not have to be
serialized and copied. Passing pointers is possible, but there must be a
strict coordination of what thread touches which object. Simultaneous
execution of operations on one object must be prevented. There are several
ways of achieving this and some of them are described below.
So what can be done safely? All objects created in a thread can be used
safely within that thread provided that other threads don't have references
to them and objects don't have implicit coupling with other threads. Such
implicit coupling may happen when data is shared between instances as with
static members, singletons or global data. Familiarize yourself with the
concept of \l{Reentrancy and Thread-Safety}{thread safe and reentrant}
classes and functions.
\section1 Using Threads
There are basically two use cases for threads:
\list
\li Make processing faster by making use of multicore processors.
\li Keep the GUI thread or other time critical threads responsive by
offloading long lasting processing or blocking calls to other threads.
\endlist
\section2 When to Use Alternatives to Threads
Developers need to be very careful with threads. It is easy to start other
threads, but very hard to ensure that all shared data remains consistent.
Problems are often hard to find because they may only show up once in a
while or only on specific hardware configurations. Before creating threads
to solve certain problems, possible alternatives should be considered.
\table
\header
\li Alternative
\li Comment
\row
\li QEventLoop::processEvents()
\li Calling QEventLoop::processEvents() repeatedly during a
time-consuming calculation prevents GUI blocking. However, this
solution doesn't scale well because the call to processEvents() may
occur too often, or not often enough, depending on hardware.
\row
\li QTimer
\li Background processing can sometimes be done conveniently using a
timer to schedule execution of a slot at some point in the future.
A timer with an interval of 0 will time out as soon as there are no
more events to process.
\row
\li QSocketNotifier QNetworkAccessManager QIODevice::readyRead()
\li This is an alternative to having one or multiple threads, each with
a blocking read on a slow network connection. As long as the
calculation in response to a chunk of network data can be executed
quickly, this reactive design is better than synchronous waiting in
threads. Reactive design is less error prone and energy efficient
than threading. In many cases there are also performance benefits.
\endtable
In general, it is recommended to only use safe and tested paths and to
avoid introducing ad-hoc threading concepts. The QtConcurrent module provides an easy
interface for distributing work to all of the processor's cores. The
threading code is completely hidden in the QtConcurrent framework, so you
don't have to take care of the details. However, QtConcurrent can't be used
when communication with the running thread is needed, and it shouldn't be
used to handle blocking operations.
\section2 Which Qt Thread Technology Should You Use?
See the \l{Multithreading Technologies in Qt} page for an introduction to the
different approaches to multithreading to Qt, and for guidelines on how to
choose among them.
\section1 Qt Thread Basics
The following sections describe how QObjects interact with threads, how
programs can safely access data from multiple threads, and how asynchronous
execution produces results without blocking a thread.
\section2 QObject and Threads
As mentioned above, developers must always be careful when calling objects'
methods from other threads. \l{QObject#Thread Affinity}{Thread affinity}
does not change this situation.
Qt documentation marks several methods as thread-safe.
\l{QCoreApplication::}{postEvent()} is a noteworthy example. A thread-safe
method may be called from different threads simultaneously.
In cases where there is usually no concurrent access to methods, calling
non-thread-safe methods of objects in other threads may work thousands
of times before a concurrent access occurs, causing unexpected behavior.
Writing test code does not entirely ensure thread correctness, but it is
still important.
On Linux, Valgrind and Helgrind can help detect threading errors.
\section2 Protecting the Integrity of Data
When writing a multithread application, extra care must be taken to avoid
data corruption. See \l{Synchronizing Threads} for a discussion on how to
use threads safely.
\section2 Dealing with Asynchronous Execution
One way to obtain a worker thread's result is by waiting for the thread
to terminate. In many cases, however, a blocking wait isn't acceptable. The
alternative to a blocking wait are asynchronous result deliveries with
either posted events or queued signals and slots. This generates a certain
overhead because an operation's result does not appear on the next source
line, but in a slot located somewhere else in the source file. Qt
developers are used to working with this kind of asynchronous behavior
because it is much similar to the kind of event-driven programming used in
GUI applications.
\section1 Examples
Qt comes with several examples for using threads. See the class references
for QThread and QThreadPool for simple examples. See the \l{Threading and
Concurrent Programming Examples} page for more advanced ones.
\section1 Digging Deeper
Threading is a very complicated subject. Qt offers more classes for
threading than we have presented in this tutorial. The following materials
can help you go into the subject in more depth:
\list
\li Good video tutorials about threads with Qt can be found in the material
from the \l{Training Day at Qt Developer Days 2009}.
\li The \l{Thread Support in Qt} document is a good starting point into
the reference documentation.
\li Qt comes with several additional examples for
\l{Threading and Concurrent Programming Examples}{QThread and QtConcurrent}.
\li Several good books describe how to work with Qt threads. The most
extensive coverage can be found in \e{Advanced Qt Programming} by Mark
Summerfield, Prentice Hall - roughly 70 of 500 pages cover QThread and
QtConcurrent.
\endlist
*/

View File

@ -1,828 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\group thread
\title Threading Classes
These \l{Qt Core} classes provide threading support to applications.
The \l{Thread Support in Qt} page covers how to use these classes.
*/
/*!
\page threads.html
\title Thread Support in Qt
\ingroup qt-basic-concepts
\brief A detailed discussion of thread handling in Qt.
\ingroup frameworks-technologies
\nextpage Multithreading Technologies in Qt
Qt provides thread support in the form of platform-independent
threading classes, a thread-safe way of posting events, and
signal-slot connections across threads. This makes it easy to
develop portable multithreaded Qt applications and take advantage
of multiprocessor machines. Multithreaded programming is also a
useful paradigm for performing time-consuming operations without
freezing the user interface of an application.
Earlier versions of Qt offered an option to build the library
without thread support. Since Qt 4.0, threads are always enabled.
\section1 Topics:
\list
\li \l{Recommended Reading}
\li \l{The Threading Classes}
\li \l{Multithreading Technologies in Qt}
\li \l{Synchronizing Threads}
\li \l{Reentrancy and Thread-Safety}
\li \l{Threads and QObjects}
\li \l{Thread-Support in Qt Modules}
\endlist
\section1 Recommended Reading
This document is intended for an audience that has knowledge of,
and experience with, multithreaded applications. If you are new
to threading see our Recommended Reading list:
\list
\li \l {http://www.amazon.com/Threads-Primer-Guide-Multithreaded-Programming/dp/0134436989}{Threads Primer: A Guide to Multithreaded Programming}
\li \l {http://www.amazon.com/Thread-Time-MultiThreaded-Programming-Guide/dp/0131900676}{Thread Time: The Multithreaded Programming Guide}
\li \l {http://www.amazon.com/Pthreads-Programming-Standard-Multiprocessing-Nutshell/dp/1565921151a}{Pthreads Programming: A POSIX Standard for Better Multiprocessing}
\li \l {http://www.amazon.com/WIN32-Multithreaded-Programming-Aaron-Cohen/dp/1565922964}{Win32 Multithreaded Programming}
\endlist
\section1 The Threading Classes
These classes are relevant to threaded applications.
\annotatedlist thread
\omit
\list
\li QThread provides the means to start a new thread.
\li QThreadStorage provides per-thread data storage.
\li QThreadPool manages a pool of threads that run QRunnable objects.
\li QRunnable is an abstract class representing a runnable object.
\li QMutex provides a mutual exclusion lock, or mutex.
\li QMutexLocker is a convenience class that automatically locks
and unlocks a QMutex.
\li QReadWriteLock provides a lock that allows simultaneous read access.
\li QReadLocker and QWriteLocker are convenience classes that automatically
lock and unlock a QReadWriteLock.
\li QSemaphore provides an integer semaphore (a generalization of a mutex).
\li QWaitCondition provides a way for threads to go to sleep until
woken up by another thread.
\li QAtomicInt provides atomic operations on integers.
\li QAtomicPointer provides atomic operations on pointers.
\endlist
\endomit
\note Qt's threading classes are implemented with native threading APIs;
e.g., Win32 and pthreads. Therefore, they can be used with threads of the
same native API.
*/
/*!
\page threads-technologies.html
\title Multithreading Technologies in Qt
\ingroup qt-basic-concepts
\brief An overview and comparison of different ways to use threads in Qt.
\ingroup frameworks-technologies
\contentspage Thread Support in Qt
\previouspage Thread Support in Qt
\nextpage Synchronizing Threads
Qt offers many classes and functions for working with threads. Below are
four different approaches that Qt programmers can use to implement
multithreaded applications.
\section1 QThread: Low-Level API with Optional Event Loops
QThread is the foundation of all thread control in Qt. Each QThread
instance represents and controls one thread.
QThread can either be instantiated directly or subclassed. Instantiating a
QThread provides a parallel event loop, allowing QObject slots to be invoked
in a secondary thread. Subclassing a QThread allows the application to initialize
the new thread before starting its event loop, or to run parallel code
without an event loop.
See the \l{QThread}{QThread class reference} and the \l{Threading and
Concurrent Programming Examples}{threading examples} for demonstrations on
how to use QThread.
\section1 QThreadPool and QRunnable: Reusing Threads
Creating and destroying threads frequently can be expensive. To reduce this
overhead, existing threads can be reused for new tasks. QThreadPool is a
collection of reuseable QThreads.
To run code in one of a QThreadPool's threads, reimplement QRunnable::run()
and instantiate the subclassed QRunnable. Use QThreadPool::start() to put
the QRunnable in the QThreadPool's run queue. When a thread becomes available,
the code within QRunnable::run() will execute in that thread.
Each Qt application has a global thread pool, which is accessible through
QThreadPool::globalInstance(). This global thread pool automatically maintains
an optimal number of threads based on the number of cores in the CPU. However,
a separate QThreadPool can be created and managed explicitly.
\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 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.
\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
applications. The right solution for a given application depends on the purpose
of the new thread and the thread's lifetime. Below is a comparison of Qt's
threading technologies, followed by recommended solutions for some example use cases.
\section2 Comparison of Solutions
\table
\header
\li Feature
\li QThread
\li QRunnable and QThreadPool
\li QtConcurrent::run()
\li Qt Concurrent (Map, Filter, Reduce)
\li WorkerScript
\row
\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 Thread can run an event loop
\li Yes
\li
\li
\li
\li
\row
\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 Thread can be controlled using signals
\li Yes (received by QThread)
\li
\li
\li Yes (received by QFutureWatcher)
\li
\row
\li Thread can be monitored through a QFuture
\li
\li
\li Partially
\li Yes
\li
\row
\li Built-in ability to pause/resume/cancel
\li
\li
\li
\li Yes
\li
\endtable
\section2 Example Use Cases
\table
\header
\li Lifetime of thread
\li Operation
\li Solution
\row
\li One call
\li Run a new linear function within another thread, optionally with progress
updates during the run.
\li Qt provides different solutions:
\list
\li Place the function in a reimplementation of QThread::run() and
start the QThread. Emit signals to update progress. OR
\li Place the function in a reimplementation of QRunnable::run() and
add the QRunnable to a QThreadPool. Write to a \l{Synchronizing
Threads}{thread-safe variable} to update progress. OR
\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
cores. For example, producing thumbnails from a list of images.
\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::}{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
tasks upon request and/or can receive new data to work with.
\li Subclass a QObject to create a worker. Instantiate this worker object
and a QThread. Move the worker to the new thread. Send commands or
data to the worker object over queued signal-slot connections.
\row
\li Permanent
\li Repeatedly perform an expensive operation in another thread, where the
thread does not need to receive any signals or events.
\li Write the infinite loop directly within a reimplementation of QThread::run().
Start the thread without an event loop. Let the thread emit signals to
send data back to the GUI thread.
\endtable
*/
/*!
\page threads-synchronizing.html
\title Synchronizing Threads
\previouspage Multithreading Technologies in Qt
\contentspage Thread Support in Qt
\nextpage Reentrancy and Thread-Safety
While the purpose of threads is to allow code to run in parallel,
there are times where threads must stop and wait for other
threads. For example, if two threads try to write to the same
variable simultaneously, the result is undefined. The principle of
forcing threads to wait for one another is called \e{mutual exclusion}.
It is a common technique for protecting shared resources such as data.
Qt provides low-level primitives as well as high-level mechanisms
for synchronizing threads.
\section1 Low-Level Synchronization Primitives
QMutex is the basic class for enforcing mutual exclusion. A thread
locks a mutex in order to gain access to a shared resource. If a second
thread tries to lock the mutex while it is already locked, the second
thread will be put to sleep until the first thread completes its task
and unlocks the mutex.
QReadWriteLock is similar to QMutex, except that it distinguishes
between "read" and "write" access. When a piece of data is not being
written to, it is safe for multiple threads to read from it simultaneously.
A QMutex forces multiple readers to take turns to read shared data, but a
QReadWriteLock allows simultaneous reading, thus improving parallelism.
QSemaphore is a generalization of QMutex that protects a certain
number of identical resources. In contrast, a QMutex protects
exactly one resource. The \l{Semaphores Example} shows a typical application
of semaphores: synchronizing access to a circular buffer between a producer
and a consumer.
QWaitCondition synchronizes threads not by enforcing mutual exclusion but by
providing a \e{condition variable}. While the other primitives make threads
wait until a resource is unlocked, QWaitCondition makes threads wait until a
particular condition has been met. To allow the waiting threads to proceed,
call \l{QWaitCondition::wakeOne()}{wakeOne()} to wake one randomly
selected thread or \l{QWaitCondition::wakeAll()}{wakeAll()} to wake them all
simultaneously. The \l{Wait Conditions Example} shows how to solve the
producer-consumer problem using QWaitCondition instead of QSemaphore.
\note Qt's synchronization classes rely on the use of properly
aligned pointers. For instance, you cannot use packed classes with
MSVC.
These synchronization classes can be used to make a method thread safe.
However, doing so incurs a performance penalty, which is why most Qt methods
are not made thread safe.
\section2 Risks
If a thread locks a resource but does not unlock it, the application may
freeze because the resource will become permanently unavailable to other threads.
This can happen, for example, if an exception is thrown and forces the current
function to return without releasing its lock.
Another similar scenario is a \e{deadlock}. For example, suppose that
thread A is waiting for thread B to unlock a resource. If thread B is also
waiting for thread A to unlock a different resource, then both threads will
end up waiting forever, so the application will freeze.
\section2 Convenience classes
QMutexLocker, QReadLocker and QWriteLocker are convenience classes that make it
easier to use QMutex and QReadWriteLock. They lock a resource when they are
constructed, and automatically unlock it when they are destroyed. They are
designed to simplify code that use QMutex and QReadWriteLock, thus reducing
the chances that a resource becomes permanently locked by accident.
\section1 High-Level Event Queues
Qt's \l{The Event System}{event system} is very useful for inter-thread
communication. Every thread may have its own event loop. To call a slot (or
any \l{Q_INVOKABLE}{invokable} method) in another thread, place that call in
the target thread's event loop. This lets the target thread finish its current
task before the slot starts running, while the original thread continues
running in parallel.
To place an invocation in an event loop, make a queued \l{Signals & Slots}
{signal-slot} connection. Whenever the signal is emitted, its arguments will
be recorded by the event system. The thread that the signal receiver
\l{QObject#Thread Affinity}{lives in} will then run the slot. Alternatively,
call QMetaObject::invokeMethod() to achieve the same effect without signals.
In both cases, a \l{Qt::QueuedConnection}{queued connection} must be used
because a \l{Qt::DirectConnection}{direct connection} bypasses the event
system and runs the method immediately in the current thread.
There is no risk of deadlocks when using the event system for thread
synchronization, unlike using low-level primitives. However, the event system
does not enforce mutual exclusion. If invokable methods access shared data,
they must still be protected with low-level primitives.
Having said that, Qt's event system, along with \l{Implicit Sharing}{implicitly
shared} data structures, offers an alternative to traditional thread locking.
If signals and slots are used exclusively and no variables are shared between
threads, a multithreaded program can do without low-level primitives altogether.
\sa QThread::exec(), {Threads and QObjects}
*/
/*!
\page threads-reentrancy.html
\title Reentrancy and Thread-Safety
\keyword reentrant
\keyword thread-safe
\previouspage Synchronizing Threads
\contentspage Thread Support in Qt
\nextpage Threads and QObjects
Throughout the documentation, the terms \e{reentrant} and
\e{thread-safe} are used to mark classes and functions to indicate
how they can be used in multithread applications:
\list
\li A \e thread-safe function can be called simultaneously from
multiple threads, even when the invocations use shared data,
because all references to the shared data are serialized.
\li A \e reentrant function can also be called simultaneously from
multiple threads, but only if each invocation uses its own data.
\endlist
Hence, a \e{thread-safe} function is always \e{reentrant}, but a
\e{reentrant} function is not always \e{thread-safe}.
By extension, a class is said to be \e{reentrant} if its member
functions can be called safely from multiple threads, as long as
each thread uses a \e{different} instance of the class. The class
is \e{thread-safe} if its member functions can be called safely
from multiple threads, even if all the threads use the \e{same}
instance of the class.
\note Qt classes are only documented as \e{thread-safe} if they
are intended to be used by multiple threads. If a function is not
marked as thread-safe or reentrant, it should not be used from
different threads. If a class is not marked as thread-safe or
reentrant then a specific instance of that class should not be
accessed from different threads.
\section1 Reentrancy
C++ classes are often reentrant, simply because they only access
their own member data. Any thread can call a member function on an
instance of a reentrant class, as long as no other thread can call
a member function on the \e{same} instance of the class at the
same time. For example, the \c Counter class below is reentrant:
\snippet threads/threads.cpp 3
\snippet threads/threads.cpp 4
The class isn't thread-safe, because if multiple threads try to
modify the data member \c n, the result is undefined. This is
because the \c ++ and \c -- operators aren't always atomic.
Indeed, they usually expand to three machine instructions:
\list 1
\li Load the variable's value in a register.
\li Increment or decrement the register's value.
\li Store the register's value back into main memory.
\endlist
If thread A and thread B load the variable's old value
simultaneously, increment their register, and store it back, they
end up overwriting each other, and the variable is incremented
only once!
\section1 Thread-Safety
Clearly, the access must be serialized: Thread A must perform
steps 1, 2, 3 without interruption (atomically) before thread B
can perform the same steps; or vice versa. An easy way to make
the class thread-safe is to protect all access to the data
members with a QMutex:
\snippet threads/threads.cpp 5
\snippet threads/threads.cpp 6
The QMutexLocker class automatically locks the mutex in its
constructor and unlocks it when the destructor is invoked, at the
end of the function. Locking the mutex ensures that access from
different threads will be serialized. The \c mutex data member is
declared with the \c mutable qualifier because we need to lock
and unlock the mutex in \c value(), which is a const function.
\section1 Notes on Qt Classes
Many Qt classes are \e{reentrant}, but they are not made
\e{thread-safe}, because making them thread-safe would incur the
extra overhead of repeatedly locking and unlocking a QMutex. For
example, QString is reentrant but not thread-safe. You can safely
access \e{different} instances of QString from multiple threads
simultaneously, but you can't safely access the \e{same} instance
of QString from multiple threads simultaneously (unless you
protect the accesses yourself with a QMutex).
Some Qt classes and functions are thread-safe. These are mainly
the thread-related classes (e.g. QMutex) and fundamental functions
(e.g. QCoreApplication::postEvent()).
\note Terminology in the multithreading domain isn't entirely
standardized. POSIX uses definitions of reentrant and thread-safe
that are somewhat different for its C APIs. When using other
object-oriented C++ class libraries with Qt, be sure the
definitions are understood.
*/
/*!
\page threads-qobject.html
\title Threads and QObjects
\previouspage Reentrancy and Thread Safety
\contentspage Thread Support in Qt
\nextpage Thread-Support in Qt Modules
QThread inherits QObject. It emits signals to indicate that the
thread started or finished executing, and provides a few slots as
well.
More interesting is that \l{QObject}s can be used in multiple
threads, emit signals that invoke slots in other threads, and
post events to objects that "live" in other threads. This is
possible because each thread is allowed to have its own event
loop.
\section1 QObject Reentrancy
QObject is reentrant. Most of its non-GUI subclasses, such as
QTimer, QTcpSocket, QUdpSocket and QProcess, are also
reentrant, making it possible to use these classes from multiple
threads simultaneously. Note that these classes are designed to be
created and used from within a single thread; creating an object
in one thread and calling its functions from another thread is not
guaranteed to work. There are three constraints to be aware of:
\list
\li \e{The child of a QObject must always be created in the thread
where the parent was created.} This implies, among other
things, that you should never pass the QThread object (\c
this) as the parent of an object created in the thread (since
the QThread object itself was created in another thread).
\li \e{Event driven objects may only be used in a single thread.}
Specifically, this applies to the \l{timers.html}{timer
mechanism} and the \l{QtNetwork}{network module}. For example,
you cannot start a timer or connect a socket in a thread that
is not the \l{QObject::thread()}{object's thread}.
\li \e{You must ensure that all objects created in a thread are
deleted before you delete the QThread.} This can be done
easily by creating the objects on the stack in your
\l{QThread::run()}{run()} implementation.
\endlist
Although QObject is reentrant, the GUI classes, notably QWidget
and all its subclasses, are not reentrant. They can only be used
from the main thread. As noted earlier, QCoreApplication::exec()
must also be called from that thread.
In practice, the impossibility of using GUI classes in other
threads than the main thread can easily be worked around by
putting time-consuming operations in a separate worker thread and
displaying the results on screen in the main thread when the
worker thread is finished. This is the approach used for
implementing the \l{Mandelbrot Example} and
the \l{network/blockingfortuneclient}{Blocking Fortune Client}
example.
\section1 Per-Thread Event Loop
Each thread can have its own event loop. The initial thread
starts its event loops using QCoreApplication::exec(); other
threads can start an event loop using QThread::exec(). Like
QCoreApplication, QThread provides an
\l{QThread::exit()}{exit(int)} function and a
\l{QThread::quit()}{quit()} slot.
An event loop in a thread makes it possible for the thread to use
certain non-GUI Qt classes that require the presence of an event
loop (such as QTimer, QTcpSocket, and QProcess). It also makes it
possible to connect signals from any threads to slots of a
specific thread. This is explained in more detail in the
\l{Signals and Slots Across Threads} section below.
\image threadsandobjects.png Threads, objects, and event loops
A QObject instance is said to \e live in the thread in which it
is created. Events to that object are dispatched by that thread's
event loop. The thread in which a QObject lives is available using
QObject::thread().
Note that for QObjects that are created before QApplication,
QObject::thread() returns zero. This means that the main thread
will only handle posted events for these objects; other event
processing is not done at all for objects with no thread. Use the
QObject::moveToThread() function to change the thread affinity for
an object and its children (the object cannot be moved if it has a
parent).
Calling \c delete on a QObject from a thread other than the one
that \e owns the object (or accessing the object in other ways) is
unsafe, unless you guarantee that the object isn't processing
events at that moment. Use QObject::deleteLater() instead, and a
\l{QEvent::DeferredDelete}{DeferredDelete} event will be posted,
which the event loop of the object's thread will eventually pick
up. By default, the thread that \e owns a QObject is the thread
that \e creates the QObject, but not after QObject::moveToThread()
has been called.
If no event loop is running, events won't be delivered to the
object. For example, if you create a QTimer object in a thread but
never call \l{QThread::exec()}{exec()}, the QTimer will never emit
its \l{QTimer::timeout()}{timeout()} signal. Calling
\l{QObject::deleteLater()}{deleteLater()} won't work
either. (These restrictions apply to the main thread as well.)
You can manually post events to any object in any thread at any
time using the thread-safe function
QCoreApplication::postEvent(). The events will automatically be
dispatched by the event loop of the thread where the object was
created.
Event filters are supported in all threads, with the restriction
that the monitoring object must live in the same thread as the
monitored object. Similarly, QCoreApplication::sendEvent()
(unlike \l{QCoreApplication::postEvent()}{postEvent()}) can only
be used to dispatch events to objects living in the thread from
which the function is called.
\section1 Accessing QObject Subclasses from Other Threads
QObject and all of its subclasses are not thread-safe. This
includes the entire event delivery system. It is important to keep
in mind that the event loop may be delivering events to your
QObject subclass while you are accessing the object from another
thread.
If you are calling a function on an QObject subclass that doesn't
live in the current thread and the object might receive events,
you must protect all access to your QObject subclass's internal
data with a mutex; otherwise, you may experience crashes or other
undesired behavior.
Like other objects, QThread objects live in the thread where the
object was created -- \e not in the thread that is created when
QThread::run() is called. It is generally unsafe to provide slots
in your QThread subclass, unless you protect the member variables
with a mutex.
On the other hand, you can safely emit signals from your
QThread::run() implementation, because signal emission is
thread-safe.
\section1 Signals and Slots Across Threads
Qt supports these signal-slot connection types:
\list
\li \l{Qt::AutoConnection}{Auto Connection} (default) If the signal is
emitted in the thread which the receiving object has affinity then
the behavior is the same as the Direct Connection. Otherwise,
the behavior is the same as the Queued Connection."
\li \l{Qt::DirectConnection}{Direct Connection} The slot is invoked
immediately, when the signal is emitted. The slot is executed
in the emitter's thread, which is not necessarily the
receiver's thread.
\li \l{Qt::QueuedConnection}{Queued Connection} The slot is invoked
when control returns to the event loop of the receiver's
thread. The slot is executed in the receiver's thread.
\li \l{Qt::BlockingQueuedConnection}{Blocking Queued Connection}
The slot is invoked as for the Queued Connection, except the
current thread blocks until the slot returns. \note Using this
type to connect objects in the same thread will cause deadlock.
\li \l{Qt::UniqueConnection}{Unique Connection} The behavior is the
same as the Auto Connection, but the connection is made only if
it does not duplicate an existing connection. i.e., if the same
signal is already connected to the same slot for the same pair
of objects, then the connection is not made and connect()
returns \c false.
\endlist
The connection type can be specified by passing an additional
argument to \l{QObject::connect()}{connect()}. Be aware that
using direct connections when the sender and receiver live in
different threads is unsafe if an event loop is running in the
receiver's thread, for the same reason that calling any function
on an object living in another thread is unsafe.
QObject::connect() itself is thread-safe.
The \l{Mandelbrot Example} uses a queued
connection to communicate between a worker thread and the main
thread. To avoid freezing the main thread's event loop (and, as a
consequence, the application's user interface), all the
Mandelbrot fractal computation is done in a separate worker
thread. The thread emits a signal when it is done rendering the
fractal.
Similarly, the \l{network/blockingfortuneclient}{Blocking Fortune
Client} example uses a separate thread for communicating with
a TCP server asynchronously.
*/
/*!
\page threads-modules.html
\title Thread-Support in Qt Modules
\previouspage Threads and QObjects
\contentspage Thread Support in Qt
\section1 Threads and the SQL Module
A connection can only be used from within the thread that created it.
Moving connections between threads or creating queries from a different
thread is not supported.
In addition, the third party libraries used by the QSqlDrivers can impose
further restrictions on using the SQL Module in a multithreaded program.
Consult the manual of your database client for more information
\section1 Painting in Threads
QPainter can be used in a thread to paint onto QImage, QPrinter, and
QPicture paint devices. Painting onto QPixmaps and QWidgets is \e not
supported. On Mac OS X the automatic progress dialog will not be
displayed if you are printing from outside the GUI thread.
Any number of threads can paint at any given time, however only
one thread at a time can paint on a given paint device. In other
words, two threads can paint at the same time if each paints onto
separate QImages, but the two threads cannot paint onto the same
QImage at the same time.
\section1 Threads and Rich Text Processing
The QTextDocument, QTextCursor, and \l{richtext.html}{all related classes} are reentrant.
Note that a QTextDocument instance created in the GUI thread may
contain QPixmap image resources. Use QTextDocument::clone() to
create a copy of the document, and pass the copy to another thread for
further processing (such as printing).
\section1 Threads and the SVG module
The QSvgGenerator and QSvgRenderer classes in the QtSvg module
are reentrant.
\section1 Threads and Implicitly Shared Classes
Qt uses an optimization called \l{implicit sharing} for many of
its value class, notably QImage and QString. Beginning with Qt 4,
implicit shared classes can safely be copied across threads, like
any other value classes. They are fully
\l{Reentrancy and Thread-Safety}{reentrant}. The implicit sharing
is really \e implicit.
In many people's minds, implicit sharing and multithreading are
incompatible concepts, because of the way the reference counting
is typically done. Qt, however, uses atomic reference counting to
ensure the integrity of the shared data, avoiding potential
corruption of the reference counter.
Note that atomic reference counting does not guarantee
\l{Reentrancy and Thread-Safety}{thread-safety}. Proper locking should be used
when sharing an instance of an implicitly shared class between
threads. This is the same requirement placed on all
\l{Reentrancy and Thread-Safety}{reentrant} classes, shared or not. Atomic reference
counting does, however, guarantee that a thread working on its
own, local instance of an implicitly shared class is safe. We
recommend using \l{Signals and Slots Across Threads}{signals and
slots} to pass data between threads, as this can be done without
the need for any explicit locking.
To sum it up, implicitly shared classes in Qt 4 are really \e
implicitly shared. Even in multithreaded applications, you can
safely use them as if they were plain, non-shared, reentrant
value-based classes.
*/

View File

@ -27,7 +27,7 @@ qhp.QtXml.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtxml/qtxml.tags tagfile = ../../../doc/qtxml/qtxml.tags
depends += qtcore qtnetwork depends += qtcore qtnetwork qtdoc
headerdirs += .. headerdirs += ..