QtBase  v6.3.1
qthread.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qthread.h"
42 #include "qthreadstorage.h"
43 #include "qmutex.h"
44 #include "qreadwritelock.h"
46 
47 #include <qeventloop.h>
48 
49 #include "qthread_p.h"
50 #include "private/qcoreapplication_p.h"
51 
52 #include <limits>
53 
55 
56 /*
57  QThreadData
58 */
59 
60 QThreadData::QThreadData(int initialRefCount)
61  : _ref(initialRefCount), loopLevel(0), scopeLevel(0),
62  eventDispatcher(nullptr),
63  quitNow(false), canWait(true), isAdopted(false), requiresCoreApplication(true)
64 {
65  // fprintf(stderr, "QThreadData %p created\n", this);
66 }
67 
69 {
70 #if QT_CONFIG(thread)
71  Q_ASSERT(_ref.loadRelaxed() == 0);
72 #endif
73 
74  // In the odd case that Qt is running on a secondary thread, the main
75  // thread instance will have been dereffed asunder because of the deref in
76  // QThreadData::current() and the deref in the pthread_destroy. To avoid
77  // crashing during QCoreApplicationData's global static cleanup we need to
78  // safeguard the main thread here.. This fix is a bit crude, but it solves
79  // the problem...
83  }
84 
85  // ~QThread() sets thread to nullptr, so if it isn't null here, it's
86  // because we're being run before the main object itself. This can only
87  // happen for QAdoptedThread. Note that both ~QThreadPrivate() and
88  // ~QObjectPrivate() will deref this object again, but that is acceptable
89  // because this destructor is still running (the _ref sub-object has not
90  // been destroyed) and there's no reentrancy. The refcount will become
91  // negative, but that's acceptable.
93  thread.storeRelease(nullptr);
94  delete t;
95 
96  for (int i = 0; i < postEventList.size(); ++i) {
97  const QPostEvent &pe = postEventList.at(i);
98  if (pe.event) {
99  --pe.receiver->d_func()->postedEvents;
100  pe.event->m_posted = false;
101  delete pe.event;
102  }
103  }
104 
105  // fprintf(stderr, "QThreadData %p destroyed\n", this);
106 }
107 
109 {
110 #if QT_CONFIG(thread)
111  (void) _ref.ref();
112  Q_ASSERT(_ref.loadRelaxed() != 0);
113 #endif
114 }
115 
117 {
118 #if QT_CONFIG(thread)
119  if (!_ref.deref())
120  delete this;
121 #endif
122 }
123 
125 {
128  return ed;
129 }
130 
131 /*
132  QAdoptedThread
133 */
134 
136  : QThread(*new QThreadPrivate(data))
137 {
138  // thread should be running and not finished for the lifetime
139  // of the application (even if QCoreApplication goes away)
140 #if QT_CONFIG(thread)
141  d_func()->running = true;
142  d_func()->finished = false;
143  init();
144 #endif
145 
146  // fprintf(stderr, "new QAdoptedThread = %p\n", this);
147 }
148 
150 {
151  // fprintf(stderr, "~QAdoptedThread = %p\n", this);
152 }
153 
154 #if QT_CONFIG(thread)
155 void QAdoptedThread::run()
156 {
157  // this function should never be called
158  qFatal("QAdoptedThread::run(): Internal error, this implementation should never be called.");
159 }
160 
161 /*
162  QThreadPrivate
163 */
164 
166  : QObjectPrivate(), running(false), finished(false),
167  isInFinish(false), interruptionRequested(false),
168  exited(false), returnCode(-1),
169  stackSize(0), priority(QThread::InheritPriority), data(d)
170 {
171 
172 // INTEGRITY doesn't support self-extending stack. The default stack size for
173 // a pthread on INTEGRITY is too small so we have to increase the default size
174 // to 128K.
175 #ifdef Q_OS_INTEGRITY
176  stackSize = 128 * 1024;
177 #elif defined(Q_OS_RTEMS)
178  static bool envStackSizeOk = false;
179  static const int envStackSize = qEnvironmentVariableIntValue("QT_DEFAULT_THREAD_STACK_SIZE", &envStackSizeOk);
180  if (envStackSizeOk)
181  stackSize = envStackSize;
182 #endif
183 
184 #if defined (Q_OS_WIN)
185  handle = 0;
186  id = 0;
187  waiters = 0;
188  terminationEnabled = true;
189  terminatePending = false;
190 #endif
191 
192  if (!data)
193  data = new QThreadData;
194 }
195 
197 {
198  data->deref();
199 }
200 
401 {
403  Q_ASSERT(data != nullptr);
404  return data->thread.loadAcquire();
405 }
406 
415  : QObject(*(new QThreadPrivate), parent)
416 {
417  Q_D(QThread);
418  // fprintf(stderr, "QThreadData %p created for thread %p\n", d->data, this);
419  d->data->thread.storeRelaxed(this);
420 }
421 
426  : QObject(dd, parent)
427 {
428  Q_D(QThread);
429  // fprintf(stderr, "QThreadData %p taken from private data for thread %p\n", d->data, this);
430  d->data->thread.storeRelaxed(this);
431 }
432 
452 {
453  Q_D(QThread);
454  {
455  QMutexLocker locker(&d->mutex);
456  if (d->isInFinish) {
457  locker.unlock();
458  wait();
459  locker.relock();
460  }
461  if (d->running && !d->finished && !d->data->isAdopted)
462  qFatal("QThread: Destroyed while thread is still running");
463 
464  d->data->thread.storeRelease(nullptr);
465  }
466 }
467 
474 bool QThread::isFinished() const
475 {
476  Q_D(const QThread);
477  QMutexLocker locker(&d->mutex);
478  return d->finished || d->isInFinish;
479 }
480 
487 bool QThread::isRunning() const
488 {
489  Q_D(const QThread);
490  QMutexLocker locker(&d->mutex);
491  return d->running && !d->isInFinish;
492 }
493 
506 void QThread::setStackSize(uint stackSize)
507 {
508  Q_D(QThread);
509  QMutexLocker locker(&d->mutex);
510  Q_ASSERT_X(!d->running, "QThread::setStackSize",
511  "cannot change stack size while the thread is running");
512  d->stackSize = stackSize;
513 }
514 
521 uint QThread::stackSize() const
522 {
523  Q_D(const QThread);
524  QMutexLocker locker(&d->mutex);
525  return d->stackSize;
526 }
527 
541 int QThread::exec()
542 {
543  Q_D(QThread);
544  QMutexLocker locker(&d->mutex);
545  d->data->quitNow = false;
546  if (d->exited) {
547  d->exited = false;
548  return d->returnCode;
549  }
550  locker.unlock();
551 
552  QEventLoop eventLoop;
553  int returnCode = eventLoop.exec();
554 
555  locker.relock();
556  d->exited = false;
557  d->returnCode = -1;
558  return returnCode;
559 }
560 
583 void QThread::exit(int returnCode)
584 {
585  Q_D(QThread);
586  QMutexLocker locker(&d->mutex);
587  d->exited = true;
588  d->returnCode = returnCode;
589  d->data->quitNow = true;
590  for (int i = 0; i < d->data->eventLoops.size(); ++i) {
591  QEventLoop *eventLoop = d->data->eventLoops.at(i);
592  eventLoop->exit(returnCode);
593  }
594 }
595 
606 void QThread::quit()
607 { exit(); }
608 
620 void QThread::run()
621 {
622  (void) exec();
623 }
624 
644 void QThread::setPriority(Priority priority)
645 {
647  qWarning("QThread::setPriority: Argument cannot be InheritPriority");
648  return;
649  }
650  Q_D(QThread);
651  QMutexLocker locker(&d->mutex);
652  if (!d->running) {
653  qWarning("QThread::setPriority: Cannot set priority, thread is not running");
654  return;
655  }
656  d->setPriority(priority);
657 }
658 
668 {
669  Q_D(const QThread);
670  QMutexLocker locker(&d->mutex);
671 
672  // mask off the high bits that are used for flags
673  return Priority(d->priority & 0xffff);
674 }
675 
806 int QThread::loopLevel() const
807 {
808  Q_D(const QThread);
809  return d->data->eventLoops.size();
810 }
811 
812 #else // QT_CONFIG(thread)
813 
815  : QObject(*(new QThreadPrivate), parent)
816 {
817  Q_D(QThread);
818  d->data->thread.storeRelaxed(this);
819 }
820 
822 {
823 
824 }
825 
827 {
828 
829 }
830 
832 {
833  return 0;
834 }
835 
836 void QThread::start(Priority priority)
837 {
838  Q_D(QThread);
840  d->running = true;
841 }
842 
844 {
845 
846 }
847 
849 {
850 
851 }
852 
853 void QThread::exit(int returnCode)
854 {
855  Q_D(QThread);
856  d->data->quitNow = true;
857  for (int i = 0; i < d->data->eventLoops.size(); ++i) {
858  QEventLoop *eventLoop = d->data->eventLoops.at(i);
859  eventLoop->exit(returnCode);
860  }
861 }
862 
864 {
866  return false;
867 }
868 
870 {
871  return QObject::event(event);
872 }
873 
874 Qt::HANDLE QThread::currentThreadIdImpl() noexcept
875 {
876  return Qt::HANDLE(currentThread());
877 }
878 
880 {
882 }
883 
885 {
886  return 1;
887 }
888 
890 {
891 
892 }
893 
895 {
896  return false;
897 }
898 
899 bool QThread::isRunning() const
900 {
901  Q_D(const QThread);
902  return d->running;
903 }
904 
905 // No threads: so we can just use static variables
906 static QThreadData *data = nullptr;
907 
908 QThreadData *QThreadData::current(bool createIfNecessary)
909 {
910  if (!data && createIfNecessary) {
911  data = new QThreadData;
912  data->thread = new QAdoptedThread(data);
913  data->threadId.storeRelaxed(Qt::HANDLE(data->thread.loadAcquire()));
914  data->deref();
915  data->isAdopted = true;
916  if (!QCoreApplicationPrivate::theMainThread.loadAcquire())
918  }
919  return data;
920 }
921 
923 {
924  delete data;
925  data = 0;
926 }
927 
932  : QObject(dd, parent)
933 {
934  Q_D(QThread);
935  // fprintf(stderr, "QThreadData %p taken from private data for thread %p\n", d->data, this);
936  d->data->thread.storeRelaxed(this);
937 }
938 
940 {
941 }
942 
944 {
945  data->thread.storeRelease(nullptr); // prevent QThreadData from deleting the QThreadPrivate (again).
946  delete data;
947 }
948 
950 {
952 }
953 
955 {
956  return 0;
957 }
958 
959 #endif // QT_CONFIG(thread)
960 
968 {
969  Q_D(const QThread);
970  return d->data->eventDispatcher.loadRelaxed();
971 }
972 
986 {
987  Q_D(QThread);
988  if (d->data->hasEventDispatcher()) {
989  qWarning("QThread::setEventDispatcher: An event dispatcher has already been created for this thread");
990  } else {
992  if (eventDispatcher->thread() == this) // was the move successful?
993  d->data->eventDispatcher = eventDispatcher;
994  else
995  qWarning("QThread::setEventDispatcher: Could not move event dispatcher to target thread");
996  }
997 }
998 
1007 #if QT_CONFIG(thread)
1008 
1013 {
1014  if (event->type() == QEvent::Quit) {
1015  quit();
1016  return true;
1017  } else {
1018  return QObject::event(event);
1019  }
1020 }
1021 
1036 {
1037  if (this == QCoreApplicationPrivate::theMainThread.loadAcquire()) {
1038  qWarning("QThread::requestInterruption has no effect on the main thread");
1039  return;
1040  }
1041  Q_D(QThread);
1042  QMutexLocker locker(&d->mutex);
1043  if (!d->running || d->finished || d->isInFinish)
1044  return;
1045  d->interruptionRequested.store(true, std::memory_order_relaxed);
1046 }
1047 
1075 {
1076  Q_D(const QThread);
1077  // fast path: check that the flag is not set:
1078  if (!d->interruptionRequested.load(std::memory_order_relaxed))
1079  return false;
1080  // slow path: if the flag is set, take into account run status:
1081  QMutexLocker locker(&d->mutex);
1082  return d->running && !d->finished && !d->isInFinish;
1083 }
1084 
1107 #if QT_CONFIG(cxx11_future)
1108 class QThreadCreateThread : public QThread
1109 {
1110 public:
1111  explicit QThreadCreateThread(std::future<void> &&future)
1112  : m_future(std::move(future))
1113  {
1114  }
1115 
1116  ~QThreadCreateThread()
1117  {
1119  quit();
1120  wait();
1121  }
1122 
1123 private:
1124  void run() override
1125  {
1126  m_future.get();
1127  }
1128 
1129  std::future<void> m_future;
1130 };
1131 
1132 QThread *QThread::createThreadImpl(std::future<void> &&future)
1133 {
1134  return new QThreadCreateThread(std::move(future));
1135 }
1136 #endif // QT_CONFIG(cxx11_future)
1137 
1146 QDaemonThread::QDaemonThread(QObject *parent)
1147  : QThread(parent)
1148 {
1149  // QThread::started() is emitted from the thread we start
1150  connect(this, &QThread::started,
1151  [](){ QThreadData::current()->requiresCoreApplication = false; });
1152 }
1153 
1154 QDaemonThread::~QDaemonThread()
1155 {
1156 }
1157 
1158 #endif // QT_CONFIG(thread)
1159 
1161 
1162 #include "moc_qthread.cpp"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
QAdoptedThread(QThreadData *data=nullptr)
Definition: qthread.cpp:135
bool ref() noexcept
Definition: qbasicatomic.h:101
bool deref() noexcept
Definition: qbasicatomic.h:102
T loadRelaxed() const noexcept
Definition: qbasicatomic.h:90
Type loadAcquire() const noexcept
Definition: qbasicatomic.h:233
void storeRelease(Type newValue) noexcept
Definition: qbasicatomic.h:234
static QBasicAtomicPointer< QThread > theMainThread
The QDeadlineTimer class marks a deadline in the future.
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
@ Quit
Definition: qcoreevent.h:92
The QEventLoop class provides a means of entering and leaving an event loop.
Definition: qeventloop.h:50
int exec(ProcessEventsFlags flags=AllEvents)
Definition: qeventloop.cpp:162
void exit(int returnCode=0)
Definition: qeventloop.cpp:269
qsizetype size() const noexcept
Definition: qlist.h:414
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes.
Definition: qmutex.h:317
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
void moveToThread(QThread *thread)
Definition: qobject.cpp:1572
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Definition: qobject.cpp:2772
virtual bool event(QEvent *event)
Definition: qobject.cpp:1329
QThread * thread() const
Definition: qobject.cpp:1527
Definition: qthread_p.h:76
QObject * receiver
Definition: qthread_p.h:78
QEvent * event
Definition: qthread_p.h:79
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
Definition: qthread.cpp:908
QAtomicPointer< QAbstractEventDispatcher > eventDispatcher
Definition: qthread_p.h:298
bool requiresCoreApplication
Definition: qthread_p.h:305
void deref()
Definition: qthread.cpp:116
QThreadData(int initialRefCount=1)
Definition: qthread.cpp:60
static void clearCurrentThreadData()
Definition: qthread.cpp:922
~QThreadData()
Definition: qthread.cpp:68
QPostEventList postEventList
Definition: qthread_p.h:295
void ref()
Definition: qthread.cpp:108
QAtomicPointer< QThread > thread
Definition: qthread_p.h:296
QAbstractEventDispatcher * createEventDispatcher()
Definition: qthread.cpp:124
void terminate()
Definition: qthread.cpp:843
bool isInterruptionRequested() const
void start(Priority=InheritPriority)
Definition: qthread.cpp:836
QAbstractEventDispatcher * eventDispatcher() const
Definition: qthread.cpp:967
bool isRunning() const
Definition: qthread.cpp:899
static int idealThreadCount() noexcept
Definition: qthread.cpp:884
bool event(QEvent *event) override
Definition: qthread.cpp:869
~QThread()
Definition: qthread.cpp:821
virtual void run()
Definition: qthread.cpp:826
bool isFinished() const
Definition: qthread.cpp:894
static QThread * currentThread()
Definition: qthread.cpp:879
Priority
Definition: qthread.h:76
@ InheritPriority
Definition: qthread.h:87
static void yieldCurrentThread()
Definition: qthread.cpp:889
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition: qthread.cpp:863
QThread(QObject *parent=nullptr)
Definition: qthread.cpp:814
uint stackSize() const
Definition: qthread.cpp:954
Priority priority() const
void finished(QPrivateSignal)
int exec()
Definition: qthread.cpp:831
void setPriority(Priority priority)
void requestInterruption()
void setStackSize(uint stackSize)
Definition: qthread.cpp:949
void quit()
Definition: qthread.cpp:848
int loopLevel() const
void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
Definition: qthread.cpp:985
friend class QThreadData
Definition: qthread.h:154
void started(QPrivateSignal)
void exit(int retcode=0)
Definition: qthread.cpp:853
static QAbstractEventDispatcher * createEventDispatcher(QThreadData *data)
QThreadPrivate(QThreadData *d=nullptr)
Definition: qthread.cpp:939
QThreadData * data
Definition: qthread_p.h:222
#define true
Definition: ftrandom.c:51
void * HANDLE
Definition: qnamespace.h:1561
Definition: qfloat16.h:381
void
Definition: png.h:1080
unsigned int uint
Definition: qglobal.h:334
#define qWarning
Definition: qlogging.h:179
#define qFatal
Definition: qlogging.h:181
GLuint64 GLenum void * handle
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
struct _cl_event * event
Definition: qopenglext.h:2998
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
#define Q_ASSERT_X(cond, x, msg)
Definition: qrandom.cpp:85
Q_UNUSED(salary)
[21]
QFuture< void > future
[5]
QDeadlineTimer deadline(30s)
QObject::connect nullptr
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent