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 Change-Id: I5e7e6c848596e72c0bb623f8442c8389b81ad9ef Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
This commit is contained in:
parent
4e337ee703
commit
3b45dfe6e6
@ -185,19 +185,9 @@
|
|||||||
|
|
||||||
\section2 QObject and Threads
|
\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'
|
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.
|
Qt documentation marks several methods as thread-safe.
|
||||||
\l{QCoreApplication::}{postEvent()} is a noteworthy example. A thread-safe
|
\l{QCoreApplication::}{postEvent()} is a noteworthy example. A thread-safe
|
||||||
method may be called from different threads simultaneously.
|
method may be called from different threads simultaneously.
|
||||||
@ -234,18 +224,6 @@
|
|||||||
has terminated.
|
has terminated.
|
||||||
\endlist
|
\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 <QObject> object3(new QObject); // OK
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
|
|
||||||
\section2 Using a Mutex to Protect the Integrity of Data
|
\section2 Using a Mutex to Protect the Integrity of Data
|
||||||
|
|
||||||
A mutex is an object that has \l{QMutex::}{lock()} and \l{QMutex::}{unlock()}
|
A mutex is an object that has \l{QMutex::}{lock()} and \l{QMutex::}{unlock()}
|
||||||
|
@ -522,13 +522,6 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
|
|||||||
details. A convenience handler, childEvent(), can be reimplemented
|
details. A convenience handler, childEvent(), can be reimplemented
|
||||||
to catch child events.
|
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
|
Last but not least, QObject provides the basic timer support in
|
||||||
Qt; see QTimer for high-level support for timers.
|
Qt; see QTimer for high-level support for timers.
|
||||||
|
|
||||||
@ -549,6 +542,41 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
|
|||||||
Some QObject functions, e.g. children(), return a QObjectList.
|
Some QObject functions, e.g. children(), return a QObjectList.
|
||||||
QObjectList is a typedef for QList<QObject *>.
|
QObjectList is a typedef for QList<QObject *>.
|
||||||
|
|
||||||
|
\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
|
\target No copy constructor
|
||||||
\section1 No copy constructor or assignment operator
|
\section1 No copy constructor or assignment operator
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user