summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread/qthread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/thread/qthread.cpp')
-rw-r--r--src/corelib/thread/qthread.cpp98
1 files changed, 89 insertions, 9 deletions
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 996a1df9a0..7d908fd4e7 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -78,6 +78,13 @@ QThreadData::~QThreadData()
QThreadData::clearCurrentThreadData();
}
+ // ~QThread() sets thread to nullptr, so if it isn't null here, it's
+ // because we're being run before the main object itself. This can only
+ // happen for QAdoptedThread. Note that both ~QThreadPrivate() and
+ // ~QObjectPrivate() will deref this object again, but that is acceptable
+ // because this destructor is still running (the _ref sub-object has not
+ // been destroyed) and there's no reentrancy. The refcount will become
+ // negative, but that's acceptable.
QThread *t = thread;
thread = 0;
delete t;
@@ -291,7 +298,7 @@ QThreadPrivate::~QThreadPrivate()
\fn int QThread::idealThreadCount()
Returns the ideal number of threads that can be run on the system. This is done querying
- the number of processor cores, both real and logical, in the system. This function returns -1
+ the number of processor cores, both real and logical, in the system. This function returns 1
if the number of processor cores could not be detected.
*/
@@ -837,15 +844,17 @@ bool QThread::event(QEvent *event)
void QThread::requestInterruption()
{
- Q_D(QThread);
- QMutexLocker locker(&d->mutex);
- if (!d->running || d->finished || d->isInFinish)
- return;
if (this == QCoreApplicationPrivate::theMainThread) {
qWarning("QThread::requestInterruption has no effect on the main thread");
return;
}
- d->interruptionRequested = true;
+ Q_D(QThread);
+ // ### Qt 6: use std::atomic_flag, and document that
+ // requestInterruption/isInterruptionRequested do not synchronize with each other
+ QMutexLocker locker(&d->mutex);
+ if (!d->running || d->finished || d->isInFinish)
+ return;
+ d->interruptionRequested.store(true, std::memory_order_relaxed);
}
/*!
@@ -874,11 +883,82 @@ void QThread::requestInterruption()
bool QThread::isInterruptionRequested() const
{
Q_D(const QThread);
- QMutexLocker locker(&d->mutex);
- if (!d->running || d->finished || d->isInFinish)
+ // fast path: check that the flag is not set:
+ if (!d->interruptionRequested.load(std::memory_order_relaxed))
return false;
- return d->interruptionRequested;
+ // slow path: if the flag is set, take into account run status:
+ QMutexLocker locker(&d->mutex);
+ return d->running && !d->finished && !d->isInFinish;
+}
+
+/*!
+ \fn template <typename Function, typename... Args> QThread *QThread::create(Function &&f, Args &&... args)
+ \since 5.10
+
+ Creates a new QThread object that will execute the function \a f with the
+ arguments \a args.
+
+ The new thread is not started -- it must be started by an explicit call
+ to start(). This allows you to connect to its signals, move QObjects
+ to the thread, choose the new thread's priority and so on. The function
+ \a f will be called in the new thread.
+
+ Returns the newly created QThread instance.
+
+ \note the caller acquires ownership of the returned QThread instance.
+
+ \note this function is only available when using C++17.
+
+ \warning do not call start() on the returned QThread instance more than once;
+ doing so will result in undefined behavior.
+
+ \sa start()
+*/
+
+/*!
+ \fn template <typename Function> QThread *QThread::create(Function &&f)
+ \since 5.10
+
+ Creates a new QThread object that will execute the function \a f.
+
+ The new thread is not started -- it must be started by an explicit call
+ to start(). This allows you to connect to its signals, move QObjects
+ to the thread, choose the new thread's priority and so on. The function
+ \a f will be called in the new thread.
+
+ Returns the newly created QThread instance.
+
+ \note the caller acquires ownership of the returned QThread instance.
+
+ \warning do not call start() on the returned QThread instance more than once;
+ doing so will result in undefined behavior.
+
+ \sa start()
+*/
+
+#if QT_CONFIG(cxx11_future)
+class QThreadCreateThread : public QThread
+{
+public:
+ explicit QThreadCreateThread(std::future<void> &&future)
+ : m_future(std::move(future))
+ {
+ }
+
+private:
+ void run() override
+ {
+ m_future.get();
+ }
+
+ std::future<void> m_future;
+};
+
+QThread *QThread::createThreadImpl(std::future<void> &&future)
+{
+ return new QThreadCreateThread(std::move(future));
}
+#endif // QT_CONFIG(cxx11_future)
/*!
\class QDaemonThread