diff options
Diffstat (limited to 'src/corelib/doc')
-rw-r--r-- | src/corelib/doc/images/thread_clock.png | bin | 5964 -> 0 bytes | |||
-rw-r--r-- | src/corelib/doc/images/threadsandobjects.png | bin | 66096 -> 0 bytes | |||
-rw-r--r-- | src/corelib/doc/images/threadvisual-example.png | bin | 16823 -> 0 bytes | |||
-rw-r--r-- | src/corelib/doc/qtcore.qdocconf | 4 | ||||
-rw-r--r-- | src/corelib/doc/snippets/code/doc_src_resources.cpp | 15 | ||||
-rw-r--r-- | src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp | 4 | ||||
-rw-r--r-- | src/corelib/doc/snippets/qtracer/ftracer.cpp | 180 | ||||
-rw-r--r-- | src/corelib/doc/snippets/qtracer/main.cpp | 59 | ||||
-rw-r--r-- | src/corelib/doc/snippets/qtracer/qtracer.pro | 2 | ||||
-rw-r--r-- | src/corelib/doc/src/custom-types.qdoc | 7 | ||||
-rw-r--r-- | src/corelib/doc/src/objectmodel/object.qdoc | 3 | ||||
-rw-r--r-- | src/corelib/doc/src/objectmodel/signalsandslots.qdoc | 2 | ||||
-rw-r--r-- | src/corelib/doc/src/plugins-howto.qdoc | 5 | ||||
-rw-r--r-- | src/corelib/doc/src/resource-system.qdoc | 34 | ||||
-rw-r--r-- | src/corelib/doc/src/threads-basics.qdoc | 365 | ||||
-rw-r--r-- | src/corelib/doc/src/threads.qdoc | 828 |
16 files changed, 54 insertions, 1454 deletions
diff --git a/src/corelib/doc/images/thread_clock.png b/src/corelib/doc/images/thread_clock.png Binary files differdeleted file mode 100644 index b8a8aa0a39..0000000000 --- a/src/corelib/doc/images/thread_clock.png +++ /dev/null diff --git a/src/corelib/doc/images/threadsandobjects.png b/src/corelib/doc/images/threadsandobjects.png Binary files differdeleted file mode 100644 index 8357d2532a..0000000000 --- a/src/corelib/doc/images/threadsandobjects.png +++ /dev/null diff --git a/src/corelib/doc/images/threadvisual-example.png b/src/corelib/doc/images/threadvisual-example.png Binary files differdeleted file mode 100644 index 2a49874719..0000000000 --- a/src/corelib/doc/images/threadvisual-example.png +++ /dev/null diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf index fdd46995c5..9ab66c6645 100644 --- a/src/corelib/doc/qtcore.qdocconf +++ b/src/corelib/doc/qtcore.qdocconf @@ -2,7 +2,7 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) project = QtCore description = Qt Core Reference Documentation -url = http://qt-project.org/doc/qt-$QT_VER/qtcore +url = http://qt-project.org/doc/qt-$QT_VER version = $QT_VERSION examplesinstallpath = core @@ -26,7 +26,7 @@ qhp.QtCore.subprojects.classes.sortPages = true tagfile = ../../../doc/qtcore/qtcore.tags -depends += qtgui qtwidgets qtnetwork qtdoc qtquick qtlinguist qtdesigner +depends += qtgui qtwidgets qtnetwork qtdoc qtquick qtlinguist qtdesigner qtconcurrent qtxml headerdirs += .. diff --git a/src/corelib/doc/snippets/code/doc_src_resources.cpp b/src/corelib/doc/snippets/code/doc_src_resources.cpp index 482c25a222..8ac7b0e970 100644 --- a/src/corelib/doc/snippets/code/doc_src_resources.cpp +++ b/src/corelib/doc/snippets/code/doc_src_resources.cpp @@ -44,11 +44,24 @@ QResource::registerResource("/path/to/myresource.rcc"); //! [5] +MyClass::MyClass() : BaseClass() +{ + Q_INIT_RESOURCE(resources); + + QFile file("qrc:/myfile.dat"); + ... +} +//! [5] + + +//! [6] int main(int argc, char *argv[]) { QApplication app(argc, argv); Q_INIT_RESOURCE(graphlib); + + QFile file("qrc:/graph.png"); ... return app.exec(); } -//! [5] +//! [6] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp index 003fce580b..9210d2737f 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp @@ -416,7 +416,7 @@ text.data(); // returns "Qt is great!" //! [46] QString tmp = "test"; QByteArray text = tmp.toLocal8Bit(); -char *data = new char[text.size()] +char *data = new char[text.size()]; strcpy(data, text.data()); delete [] data; //! [46] @@ -424,7 +424,7 @@ delete [] data; //! [47] QString tmp = "test"; QByteArray text = tmp.toLocal8Bit(); -char *data = new char[text.size() + 1] +char *data = new char[text.size() + 1]; strcpy(data, text.data()); delete [] data; //! [47] diff --git a/src/corelib/doc/snippets/qtracer/ftracer.cpp b/src/corelib/doc/snippets/qtracer/ftracer.cpp deleted file mode 100644 index b12e3ed9c3..0000000000 --- a/src/corelib/doc/snippets/qtracer/ftracer.cpp +++ /dev/null @@ -1,180 +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 examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> - -#include <QCoreApplication> -#include <QLoggingCategory> - - -//![1] -QLoggingCategory theFooArea("foo"); -QLoggingCategory theBarArea("bar"); -QLoggingCategory theBazArea("baz"); -//![1] - -// Note: These locations are Ubuntu specific. - -// Note: To make the example work with user permissions, make sure -// the files are user-writable and the path leading there accessible. - -const char traceSwitch[] = "/sys/kernel/debug/tracing/tracing_on"; -const char traceSink[] = "/sys/kernel/debug/tracing/trace_marker"; - -// The base class only serves as a facility to share code -// between the "single line" data logging aspect and the -// scoped "measuring" aspect. - -// Both aspects and the base class could be combined into -// a single tracer serving both purposes, but are split -// here for clarity. - -// Error handling is left as an exercise. - -//![2] -class MyTracerBase : public QTracer -{ -public: - MyTracerBase() { - enable = ::open(traceSwitch, O_WRONLY); - marker = ::open(traceSink, O_WRONLY); - } - - ~MyTracerBase() { - ::close(enable); - ::close(marker); - } - -protected: - int enable; - int marker; -}; -//![2] - - -//![2] -class MyTracer : public MyTracerBase -{ -public: - void start() { ::write(marker, "B", 1); } - void end() { ::write(marker, "E", 1); } -}; -//![2] - - -//![3] -class MyDataLogger : public MyTracerBase -{ -public: - MyDataLogger() { - buf[0] = 0; - pos = 0; - } - - void record(int i) { pos += sprintf(buf + pos, "%d", i); } - void record(const char *msg) { pos += sprintf(buf + pos, "%s", msg); } - void end() { ::write(marker, buf, pos); pos = 0; } - -private: - char buf[100]; - int pos; -}; -//![3] - -// Simplest possible example for "measuring". -//![4] -int foo(int i) -{ - qCTraceGuard(theFooArea); - // Here could be some lengthy code. - return i * i; -} -//![4] - -// We can switch on/off tracing dynamically. -// The tracer will be temporarily switched off at the third call -// and re-enabled at the eighth. -//![5] -int bar(int i) -{ - static int n = 0; - ++n; - if (n == 3) - theBarArea.setEnabled(QtTraceMsg, false); - if (n == 8) - theBarArea.setEnabled(QtTraceMsg, true); - - qCTraceGuard(theBarArea); - return i * i; -} -//![5] - -// An example to create "complex" log messages. -//![6] -int baz(int i) -{ - qCTrace(theBazArea) << 32 << "some stuff"; - - return i * i; -} -//![6] - - - -//![7] -namespace { -static struct Init -{ - Init() { - tracer.addToCategory(theFooArea); - tracer.addToCategory(theBarArea); - logger.addToCategory(theBazArea); - } - - MyTracer tracer; - MyDataLogger logger; - -} initializer; -} -//![7] diff --git a/src/corelib/doc/snippets/qtracer/main.cpp b/src/corelib/doc/snippets/qtracer/main.cpp deleted file mode 100644 index 758a2bbdb8..0000000000 --- a/src/corelib/doc/snippets/qtracer/main.cpp +++ /dev/null @@ -1,59 +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 examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -int foo(int i); -int bar(int i); -int baz(int i); - -int main() -{ - int s = 0; - for (int i = 0; i != 10; ++i) - s += foo(i); - - for (int i = 0; i != 10; ++i) - s += bar(i); - - for (int i = 0; i != 10; ++i) - s += baz(i); - - return s; -} - diff --git a/src/corelib/doc/snippets/qtracer/qtracer.pro b/src/corelib/doc/snippets/qtracer/qtracer.pro deleted file mode 100644 index 254e22be76..0000000000 --- a/src/corelib/doc/snippets/qtracer/qtracer.pro +++ /dev/null @@ -1,2 +0,0 @@ - -SOURCES += ftracer.cpp main.cpp diff --git a/src/corelib/doc/src/custom-types.qdoc b/src/corelib/doc/src/custom-types.qdoc index cbf347a2f7..ed846aee83 100644 --- a/src/corelib/doc/src/custom-types.qdoc +++ b/src/corelib/doc/src/custom-types.qdoc @@ -155,10 +155,9 @@ The Q_DECLARE_METATYPE() macro and qRegisterMetaType() function documentation contain more detailed information about their uses and limitations. - The \l{Custom Type Example}{Custom Type}, - \l{Custom Type Sending Example}{Custom Type Sending} - and \l{Queued Custom Type Example}{Queued Custom Type} examples show how to - implement a custom type with the features outlined in this document. + The \l{Custom Type Example}{Custom Type} and \l{Queued Custom Type Example} + {Queued Custom Type} examples show how to implement a custom type with the + features outlined in this document. The \l{Debugging Techniques} document provides an overview of the debugging mechanisms discussed above. diff --git a/src/corelib/doc/src/objectmodel/object.qdoc b/src/corelib/doc/src/objectmodel/object.qdoc index 89a781da39..8d24096b7a 100644 --- a/src/corelib/doc/src/objectmodel/object.qdoc +++ b/src/corelib/doc/src/objectmodel/object.qdoc @@ -46,7 +46,8 @@ \li queryable and designable \l{Qt's Property System}{object properties} \li powerful \l{The Event System}{events and event filters} - \li contextual \l{i18n}{string translation for internationalization} + \li contextual \l{Internationalization with Qt}{string translation for + internationalization} \li sophisticated interval driven \l {Timers}{timers} that make it possible to elegantly integrate many tasks in an event-driven GUI \li hierarchical and queryable \l{Object Trees & Ownership}{object diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc index dd93b80cae..e894d547d0 100644 --- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc +++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc @@ -275,7 +275,7 @@ and slot members, as well as pointers to these functions. The meta-object contains additional information such as the - object's \l{QObject::className()}{class name}. You can + object's \l{QMetaObject::className()}{class name}. You can also check if an object \l{QObject::inherits()}{inherits} a specific class, for example: diff --git a/src/corelib/doc/src/plugins-howto.qdoc b/src/corelib/doc/src/plugins-howto.qdoc index 2dbf1f8141..7565d610cc 100644 --- a/src/corelib/doc/src/plugins-howto.qdoc +++ b/src/corelib/doc/src/plugins-howto.qdoc @@ -35,10 +35,7 @@ These \l{Qt Core} classes deal with shared libraries, (e.g. .so and DLL files), and with Qt plugins. - See the \l{How to Create Qt Plugins} page for more information.. - - See also the \l{ActiveQt framework} for Windows. - + See the \l{How to Create Qt Plugins} page for more information. */ /*! diff --git a/src/corelib/doc/src/resource-system.qdoc b/src/corelib/doc/src/resource-system.qdoc index 5ef6bb285c..91ce8afcf8 100644 --- a/src/corelib/doc/src/resource-system.qdoc +++ b/src/corelib/doc/src/resource-system.qdoc @@ -184,15 +184,39 @@ path list is empty at startup; call QDir::addSearchPath() to add paths to it. - If you have resources in a static library, you might need to - force initialization of your resources by calling \l - Q_INIT_RESOURCE() with the base name of the \c .qrc file. For - example: + \section1 Using Resources in a Library + + If you have resources in a library, you need to force initialization + of your resources by calling \l Q_INIT_RESOURCE() with the base name + of the \c .qrc file. For example: \snippet code/doc_src_resources.cpp 5 + This ensures that the resources are linked into the final application + binary in the case of static linking. You should put the initialization + code close to where the resources are used in your library, so that + clients of your library will only link in the resources if they use + the feature of the library that depends on them. + + Note: As the resource initializers generated by rcc are declared in the + global namespace, your calls to \l Q_INIT_RESOURCE() also need to be done + outside of any namespace. + + If the library includes resources that are not used internally, but + instead exposed to clients of the library, the initialization needs + to happen in the application code. For example: + + \snippet code/doc_src_resources.cpp 6 + + As before, this ensures that the resources are linked into the final + application binary in the case of static linking, but also triggers + loading of the library in the case of dynamic linking, such as plugins. + Similarly, if you must unload a set of resources explicitly (because a plugin is being unloaded or the resources are not valid any longer), you can force removal of your resources by calling - Q_CLEANUP_RESOURCE() with the same base name as above. + \l Q_CLEANUP_RESOURCE() with the same base name as above. + + Note: The use of \l Q_INIT_RESOURCE() and \l Q_CLEANUP_RESOURCE() is + not necessary when the resource is built as part of the application. */ 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 -*/ diff --git a/src/corelib/doc/src/threads.qdoc b/src/corelib/doc/src/threads.qdoc deleted file mode 100644 index 890fd9f6ff..0000000000 --- a/src/corelib/doc/src/threads.qdoc +++ /dev/null @@ -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 a 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 QReadWriteLocker, 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{threads/mandelbrot}{Mandelbrot} 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{threads/mandelbrot}{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. -*/ |