summaryrefslogtreecommitdiffstats
path: root/src/corelib/doc/src/threads-basics.qdoc
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-26 22:30:27 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-26 22:35:48 +0100
commit4a8273a6fc2e741e811cf5dabc9a3c240306cf7f (patch)
tree2148abc88f8543eecdc0b97b2dd92594836af9b2 /src/corelib/doc/src/threads-basics.qdoc
parent036c5db468164297d213764c59a4b59daa76d90a (diff)
parent1c2be58fecaff1de5f2849192eb712984ebd59bd (diff)
Merge remote-tracking branch 'origin/stable' into dev
For the conflicts in msvc_nmake.cpp the ifdefs are extended since we need to support windows phone in the target branch while it is not there in the current stable branch (as of Qt 5.2). Conflicts: configure qmake/generators/win32/msvc_nmake.cpp src/3rdparty/angle/src/libEGL/Surface.cpp src/angle/src/common/common.pri src/corelib/global/qglobal.h src/corelib/io/qstandardpaths.cpp src/plugins/platforms/qnx/qqnxintegration.cpp src/plugins/platforms/qnx/qqnxscreeneventhandler.h src/plugins/platforms/xcb/qglxintegration.h src/widgets/kernel/win.pri tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp tools/configure/configureapp.cpp Change-Id: I00b579eefebaf61d26ab9b00046d2b5bd5958812
Diffstat (limited to 'src/corelib/doc/src/threads-basics.qdoc')
-rw-r--r--src/corelib/doc/src/threads-basics.qdoc365
1 files changed, 0 insertions, 365 deletions
diff --git a/src/corelib/doc/src/threads-basics.qdoc b/src/corelib/doc/src/threads-basics.qdoc
deleted file mode 100644
index 4f381421b4..0000000000
--- a/src/corelib/doc/src/threads-basics.qdoc
+++ /dev/null
@@ -1,365 +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
-
- This tutorial comes with examples for Qt's three basic ways of working with
- threads. Two more examples show how to communicate with a running thread
- and how a QObject can be placed in another thread, providing service to the
- main thread.
-
- \list
- \li Using QThread as shown \l{Qt thread basics}{above}
- \li \l{Example 1: Using the Thread Pool}{Using the global QThreadPool}
- \li \l{Example 2: Using QtConcurrent}{Using QtConcurrent}
- \li \l{Example 3: Clock}{Communication with the GUI thread}
- \li \l{Example 4: A Permanent Thread}{A permanent QObject in another thread
- provides service to the main thread}
- \endlist
-
- The following examples can all be compiled and run independently. The source can
- be found in the examples directory: examples/tutorials/threads/
-
- \section2 Example 1: Using the Thread Pool
-
- Creating and destroying threads frequently can be expensive. To avoid the
- cost of thread creation, a thread pool can be used. A thread pool is a
- place where threads can be parked and fetched. We can write the same
- "hello thread" program as \l{Qt Thread Basics}{above} using the global
- thread pool. We derive a class from QRunnable. The code we want to run in
- another thread needs to be placed in the reimplemented QRunnable::run()
- method.
-
- \snippet ../widgets/tutorials/threads/hellothreadpool/hellothreadpool.cpp 1
-
- We instantiate Work in main(), locate the global thread pool and use the
- QThreadPool::start() method. Now the thread pool runs our worker in another
- thread. Using the thread pool has a performance advantage because threads
- are not destroyed after they have finished running. They are kept in a pool
- and wait to be used again later.
-
- \section2 Example 2: Using QtConcurrent
-
- \snippet ../widgets/tutorials/threads/helloconcurrent/helloconcurrent.cpp 1
-
- We write a global function hello() to implement the work. QtConcurrent::run()
- is used to run the function in another thread. The result is a QFuture.
- QFuture provides a method called \l{QFuture::}{waitForFinished()}, which
- blocks until the calculation is completed. The real power of QtConcurrent
- becomes visible when data can be made available in a container. QtConcurrent
- provides several functions that are able to process itemized data on all
- available cores simultaneously. The use of QtConcurrent is very similar to
- applying an STL algorithm to an STL container.
- \l{examples-threadandconcurrent.html}{QtConcurrent Map} is a very short and
- clear example about how a container of images can be scaled on all available
- cores. The image scaling example uses the blocking variants of the functions
- used. For every blocking function there is also a non-blocking, asynchronous
- counterpart. Getting results asynchronously is implemented with QFuture and
- QFutureWatcher.
-
- \section2 Example 3: Clock
-
- \image thread_clock.png "clock"
-
- We want to produce a clock application. The application has a GUI and a
- worker thread. The worker thread checks every 10 milliseconds what time it
- is. If the formatted time has changed, the result will be sent to the GUI
- thread where it is displayed.
-
- Of course, this is an overly complicated way of designing a clock and,
- actually, a separate thread is unnecessary. We would be better off placing
- the timer in the main thread because the calculation made in the timer slot
- is very short-lived. This example is purely for instructional use and shows
- how to communicate from a worker thread to a GUI thread. Note that
- communication in this direction is easy. We only need to add a signal
- to QThread and make a queued signal/slot connection to the main thread.
- Communication from the GUI to the worker thread is shown in the next
- example.
-
- \snippet ../widgets/tutorials/threads/clock/main.cpp 1
-
- We've connected the \c clockThread with the label. The connection must be a
- queued signal-slot connection because we want to put the call in the event
- loop.
-
- \snippet ../widgets/tutorials/threads/clock/clockthread.h 1
-
- We have derived a class from QThread and declared the \c sendTime() signal.
-
- \snippet ../widgets/tutorials/threads/clock/clockthread.cpp 1
-
- The trickiest part of this example is that the timer is connected to its
- slot via a direct connection. A default connection would produce a queued
- signal-slot connection because the connected objects live in different
- threads; remember that QThread does not live in the thread it creates.
-
- Still it is safe to access ClockThread::timerHit() from the worker thread
- because ClockThread::timerHit() is private and only touches local variables
- and a private member that isn't touched by public methods.
- QDateTime::currentDateTime() isn't marked as thread-safe in Qt
- documentation, however we can get away with using it in this small
- example because we know that the QDateTime::currentDateTime() static
- method isn't used in any other threads.
-
- \section2 Example 4: A Permanent Thread
-
- This example shows how it is possible to have a QObject in a worker thread
- that accepts requests from the GUI thread, does polling using a timer and
- continuously reports results back to the GUI thread. The actual work
- including the polling must be implemented in a class derived from QObject.
- We have called this class \c WorkerObject in the code shown below. The
- thread-specific code is hidden in a class called \c Thread, derived from
- QThread.
- \c Thread has two additional public members. The \c launchWorker() member
- takes the worker object and moves it to another thread with a started event
- loop.
- The call blocks for a very short moment until the thread creation operation
- is completed, allowing the worker object to be used again on the next line.
- The \c Thread class's code is short but somewhat involved, so we only show
- how to use the class.
-
- \snippet ../widgets/tutorials/threads/movedobject/main.cpp 1
-
- QMetaObject::invokeMethod() calls a slot via the event loop. The worker
- object's methods should not be called directly after the object has been
- moved to another thread. We let the worker thread do some work and polling,
- and use a timer to shut the application down after 3 seconds. Shutting the
- worker down needs some care. We call \c{Thread::stop()} to exit the event
- loop. We wait for the thread to terminate and, after this has occurred, we
- delete the worker.
-
- \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
-*/