From 28984cd5ba63c557b88377f996a90b9665f37745 Mon Sep 17 00:00:00 2001 From: Sze Howe Koh Date: Tue, 25 Feb 2014 09:17:08 +0100 Subject: Doc: Discuss the concept of thread affinity in more detail - Create a section dedicated to this concept, which is fundamental to signal/event handling - Move relevant content from the very broad "Thread Basics" page to the QObject class ref - Flesh out existing content, including distinguishing signals from events - Address the common misconception that "member" = "child"; this has been encountered several times in the Qt Project forums This is a cherry-pick from 3b45dfe6e6ff6c0626b in qtbase.git Change-Id: If3b65f3da4e1ca414c7175c4e22bcdef38f45442 Reviewed-by: Sze Howe Koh Reviewed-by: Jerome Pasion --- doc/src/tutorials/threads.qdoc | 26 ++------------------------ src/corelib/kernel/qobject.cpp | 42 +++++++++++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/doc/src/tutorials/threads.qdoc b/doc/src/tutorials/threads.qdoc index 0552908..ad66b9f 100644 --- a/doc/src/tutorials/threads.qdoc +++ b/doc/src/tutorials/threads.qdoc @@ -277,19 +277,9 @@ \section2 QObject and Threads - A QObject is said to have a \e{thread affinity} or, in other words, that it - lives in a certain thread. This means that, at creation time, QObject saves - a pointer to the current thread. This information becomes relevant when an - event is posted with \l{QCoreApplication::}{postEvent()}. The event will be - put in the corresponding thread's event loop. If the thread where the - QObject lives doesn't have an event loop, the event will never be delivered. - - To start an event loop, \l{QThread::}{exec()} must be called inside - \l{QThread::}{run()}. Thread affinity can be changed using - \l{QObject::}{moveToThread()}. - As mentioned above, developers must always be careful when calling objects' - methods from other threads. Thread affinity does not change this situation. + 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. @@ -326,18 +316,6 @@ has terminated. \endlist - A QObject's parent must always be in the same thread. This has a surprising - consequence for objects generated within the \l{QThread::}{run()} method: - - \code - void HelloThread::run() - { - QObject *object1 = new QObject(this); //error, parent must be in the same thread - QObject object2; // OK - QSharedPointer object3(new QObject); // OK - } - \endcode - \section2 Using a Mutex to Protect the Integrity of Data A mutex is an object that has \l{QMutex::}{lock()} and \l{QMutex::}{unlock()} diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index aa1a00c..91e8fbb 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -566,13 +566,6 @@ void QMetaCallEvent::placeMetaCall(QObject *object) details. A convenience handler, childEvent(), can be reimplemented to catch child events. - Events are delivered in the thread in which the object was - created; see \l{Thread Support in Qt} and thread() for details. - Note that event processing is not done at all for QObjects with no - thread affinity (thread() returns zero). Use the moveToThread() - function to change the thread affinity for an object and its - children (the object cannot be moved if it has a parent). - Last but not least, QObject provides the basic timer support in Qt; see QTimer for high-level support for timers. @@ -593,6 +586,41 @@ void QMetaCallEvent::placeMetaCall(QObject *object) Some QObject functions, e.g. children(), return a QObjectList. QObjectList is a typedef for QList. + \section1 Thread Affinity + + A QObject instance is said to have a \e{thread affinity}, or that + it \e{lives} in a certain thread. When a QObject receives a + \l{Qt::QueuedConnection}{queued signal} or a \l{The Event + System#Sending Events}{posted event}, the slot or event handler + will run in the thread that the object lives in. + + \note If a QObject has no thread affinity (that is, if thread() + returns zero), or if it lives in a thread that has no running event + loop, then it cannot receive queued signals or posted events. + + By default, a QObject lives in the thread in which it is created. + An object's thread affinity can be queried using thread() and + changed using moveToThread(). + + All QObjects must live in the same thread as their parent. Consequently: + + \list + \li setParent() will fail if the two QObjects involved live in + different threads. + \li When a QObject is moved to another thread, all its children + will be automatically moved too. + \li moveToThread() will fail if the QObject has a parent. + \li If \l{QObject}s are created within QThread::run(), they cannot + become children of the QThread object because the QThread does + not live in the thread that calls QThread::run(). + \endlist + + \note A QObject's member variables \e{do not} automatically become + its children. The parent-child relationship must be set by either + passing a pointer to the child's \l{QObject()}{constructor}, or by + calling setParent(). Without this step, the object's member variables + will remain in the old thread when moveToThread() is called. + \target No copy constructor \section1 No copy constructor or assignment operator -- cgit v0.12