summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/thread')
-rw-r--r--src/corelib/thread/qbasicatomic.h12
-rw-r--r--src/corelib/thread/qfutureinterface.cpp7
-rw-r--r--src/corelib/thread/qfutureinterface.h13
-rw-r--r--src/corelib/thread/qreadwritelock.cpp13
-rw-r--r--src/corelib/thread/qreadwritelock_p.h18
-rw-r--r--src/corelib/thread/qsemaphore.h7
-rw-r--r--src/corelib/thread/qwaitcondition_p.h153
-rw-r--r--src/corelib/thread/thread.pri1
8 files changed, 186 insertions, 38 deletions
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h
index dc976819ef..9804e60119 100644
--- a/src/corelib/thread/qbasicatomic.h
+++ b/src/corelib/thread/qbasicatomic.h
@@ -99,8 +99,10 @@ public:
typename Ops::Type _q_value;
// Everything below is either implemented in ../arch/qatomic_XXX.h or (as fallback) in qgenericatomic.h
- T load() const noexcept { return loadRelaxed(); }
- void store(T newValue) noexcept { storeRelaxed(newValue); }
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_VERSION_X_5_14("Use loadRelaxed") T load() const noexcept { return loadRelaxed(); }
+ QT_DEPRECATED_VERSION_X_5_14("Use storeRelaxed") void store(T newValue) noexcept { storeRelaxed(newValue); }
+#endif
T loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); }
void storeRelaxed(T newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); }
@@ -238,8 +240,10 @@ public:
AtomicType _q_value;
- Type load() const noexcept { return loadRelaxed(); }
- void store(Type newValue) noexcept { storeRelaxed(newValue); }
+#if QT_DEPRECATED_SINCE(5, 14)
+ QT_DEPRECATED_VERSION_X_5_14("Use loadRelaxed") Type load() const noexcept { return loadRelaxed(); }
+ QT_DEPRECATED_VERSION_X_5_14("Use storeRelaxed") void store(Type newValue) noexcept { storeRelaxed(newValue); }
+#endif
Type loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); }
void storeRelaxed(Type newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); }
diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp
index 6430f38a3b..1303be10b1 100644
--- a/src/corelib/thread/qfutureinterface.cpp
+++ b/src/corelib/thread/qfutureinterface.cpp
@@ -424,12 +424,7 @@ void QFutureInterfaceBase::setProgressValueAndText(int progressValue,
}
}
-QMutex *QFutureInterfaceBase::mutex() const
-{
- return &d->m_mutex;
-}
-
-QMutex &QFutureInterfaceBase::mutex(int) const
+QMutex &QFutureInterfaceBase::mutex() const
{
return d->m_mutex;
}
diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h
index bcdae24833..43dfd6bac4 100644
--- a/src/corelib/thread/qfutureinterface.h
+++ b/src/corelib/thread/qfutureinterface.h
@@ -119,8 +119,7 @@ public:
void waitForResult(int resultIndex);
void waitForResume();
- QMutex *mutex() const;
- QMutex &mutex(int) const;
+ QMutex &mutex() const;
QtPrivate::ExceptionStore &exceptionStore();
QtPrivate::ResultStoreBase &resultStoreBase();
const QtPrivate::ResultStoreBase &resultStoreBase() const;
@@ -191,7 +190,7 @@ public:
template <typename T>
inline void QFutureInterface<T>::reportResult(const T *result, int index)
{
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
if (this->queryState(Canceled) || this->queryState(Finished)) {
return;
}
@@ -217,7 +216,7 @@ inline void QFutureInterface<T>::reportResult(const T &result, int index)
template <typename T>
inline void QFutureInterface<T>::reportResults(const QVector<T> &_results, int beginIndex, int count)
{
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
if (this->queryState(Canceled) || this->queryState(Finished)) {
return;
}
@@ -245,14 +244,14 @@ inline void QFutureInterface<T>::reportFinished(const T *result)
template <typename T>
inline const T &QFutureInterface<T>::resultReference(int index) const
{
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
return resultStoreBase().resultAt(index).template value<T>();
}
template <typename T>
inline const T *QFutureInterface<T>::resultPointer(int index) const
{
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
return resultStoreBase().resultAt(index).template pointer<T>();
}
@@ -266,7 +265,7 @@ inline QList<T> QFutureInterface<T>::results()
QFutureInterfaceBase::waitForResult(-1);
QList<T> res;
- std::lock_guard<QMutex> locker(mutex(0));
+ std::lock_guard<QMutex> locker{mutex()};
QtPrivate::ResultIteratorBase it = resultStoreBase().begin();
while (it != resultStoreBase().end()) {
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp
index 30e9b95a52..14654986a0 100644
--- a/src/corelib/thread/qreadwritelock.cpp
+++ b/src/corelib/thread/qreadwritelock.cpp
@@ -48,6 +48,7 @@
#include "qreadwritelock_p.h"
#include "qelapsedtimer.h"
#include "private/qfreelist_p.h"
+#include "private/qlocking_p.h"
QT_BEGIN_NAMESPACE
@@ -262,7 +263,7 @@ bool QReadWriteLock::tryLockForRead(int timeout)
if (d->recursive)
return d->recursiveLockForRead(timeout);
- QMutexLocker lock(&d->mutex);
+ auto lock = qt_unique_lock(d->mutex);
if (d != d_ptr.loadRelaxed()) {
// d_ptr has changed: this QReadWriteLock was unlocked before we had
// time to lock d->mutex.
@@ -369,7 +370,7 @@ bool QReadWriteLock::tryLockForWrite(int timeout)
if (d->recursive)
return d->recursiveLockForWrite(timeout);
- QMutexLocker lock(&d->mutex);
+ auto lock = qt_unique_lock(d->mutex);
if (d != d_ptr.loadRelaxed()) {
// The mutex was unlocked before we had time to lock the mutex.
// We are holding to a mutex within a QReadWriteLockPrivate that is already released
@@ -418,7 +419,7 @@ void QReadWriteLock::unlock()
return;
}
- QMutexLocker locker(&d->mutex);
+ const auto lock = qt_scoped_lock(d->mutex);
if (d->writerCount) {
Q_ASSERT(d->writerCount == 1);
Q_ASSERT(d->readerCount == 0);
@@ -536,7 +537,7 @@ void QReadWriteLockPrivate::unlock()
bool QReadWriteLockPrivate::recursiveLockForRead(int timeout)
{
Q_ASSERT(recursive);
- QMutexLocker lock(&mutex);
+ auto lock = qt_unique_lock(mutex);
Qt::HANDLE self = QThread::currentThreadId();
@@ -556,7 +557,7 @@ bool QReadWriteLockPrivate::recursiveLockForRead(int timeout)
bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout)
{
Q_ASSERT(recursive);
- QMutexLocker lock(&mutex);
+ auto lock = qt_unique_lock(mutex);
Qt::HANDLE self = QThread::currentThreadId();
if (currentWriter == self) {
@@ -574,7 +575,7 @@ bool QReadWriteLockPrivate::recursiveLockForWrite(int timeout)
void QReadWriteLockPrivate::recursiveUnlock()
{
Q_ASSERT(recursive);
- QMutexLocker lock(&mutex);
+ auto lock = qt_unique_lock(mutex);
Qt::HANDLE self = QThread::currentThreadId();
if (self == currentWriter) {
diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h
index 31da2401c0..a4d002b7f2 100644
--- a/src/corelib/thread/qreadwritelock_p.h
+++ b/src/corelib/thread/qreadwritelock_p.h
@@ -63,17 +63,16 @@ QT_BEGIN_NAMESPACE
class QReadWriteLockPrivate
{
public:
- QReadWriteLockPrivate(bool isRecursive = false)
- : readerCount(0), writerCount(0), waitingReaders(0), waitingWriters(0),
- recursive(isRecursive), id(0), currentWriter(nullptr) {}
+ explicit QReadWriteLockPrivate(bool isRecursive = false)
+ : recursive(isRecursive) {}
QMutex mutex;
QWaitCondition writerCond;
QWaitCondition readerCond;
- int readerCount;
- int writerCount;
- int waitingReaders;
- int waitingWriters;
+ int readerCount = 0;
+ int writerCount = 0;
+ int waitingReaders = 0;
+ int waitingWriters = 0;
const bool recursive;
//Called with the mutex locked
@@ -82,19 +81,18 @@ public:
void unlock();
//memory management
- int id;
+ int id = 0;
void release();
static QReadWriteLockPrivate *allocate();
// Recusive mutex handling
- Qt::HANDLE currentWriter;
+ Qt::HANDLE currentWriter = {};
QHash<Qt::HANDLE, int> currentReaders;
// called with the mutex unlocked
bool recursiveLockForWrite(int timeout);
bool recursiveLockForRead(int timeout);
void recursiveUnlock();
-
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
index 58c12997ad..b3b9b52052 100644
--- a/src/corelib/thread/qsemaphore.h
+++ b/src/corelib/thread/qsemaphore.h
@@ -80,8 +80,7 @@ public:
explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) noexcept
: m_sem(sem), m_n(n) {}
QSemaphoreReleaser(QSemaphoreReleaser &&other) noexcept
- : m_sem(other.m_sem), m_n(other.m_n)
- { other.m_sem = nullptr; }
+ : m_sem(other.cancel()), m_n(other.m_n) {}
QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) noexcept
{ QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; }
@@ -102,9 +101,7 @@ public:
QSemaphore *cancel() noexcept
{
- QSemaphore *old = m_sem;
- m_sem = nullptr;
- return old;
+ return qExchange(m_sem, nullptr);
}
private:
diff --git a/src/corelib/thread/qwaitcondition_p.h b/src/corelib/thread/qwaitcondition_p.h
new file mode 100644
index 0000000000..5133e52e92
--- /dev/null
+++ b/src/corelib/thread/qwaitcondition_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QWAITCONDITION_P_H
+#define QWAITCONDITION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qmutex.cpp, qmutex_unix.cpp, and qmutex_win.cpp. This header
+// file may change from version to version without notice, or even be
+// removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QWaitCondition>
+#include <QtCore/QMutex>
+#include <QtCore/QDeadlineTimer>
+
+#include <condition_variable>
+#include <mutex>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate
+{
+
+#if defined(Q_OS_INTEGRITY)
+
+class condition_variable;
+
+class mutex : private QMutex
+{
+ friend class QtPrivate::condition_variable;
+public:
+ // all special member functions are ok!
+ // do not expose the (QMutex::Recursive) ctor
+ // don't use 'using QMutex::lock;' etc as those have the wrong noexcept
+
+ void lock() { return QMutex::lock(); }
+ void unlock() { return QMutex::unlock(); }
+ bool try_lock() { return QMutex::tryLock(); }
+};
+
+class condition_variable : private QWaitCondition
+{
+public:
+ // all special member functions are ok!
+
+ void notify_one() { QWaitCondition::wakeOne(); }
+ void notify_all() { QWaitCondition::wakeAll(); }
+
+ void wait(std::unique_lock<QtPrivate::mutex> &lock) { QWaitCondition::wait(lock.mutex()); }
+ template <class Predicate>
+ void wait(std::unique_lock<QtPrivate::mutex> &lock, Predicate p)
+ {
+ while (!p())
+ wait(lock);
+ }
+
+ template <typename Rep, typename Period>
+ std::cv_status wait_for(std::unique_lock<QtPrivate::mutex> &lock,
+ const std::chrono::duration<Rep, Period> &d)
+ {
+ return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{d})
+ ? std::cv_status::no_timeout
+ : std::cv_status::timeout;
+ }
+ template <typename Rep, typename Period, typename Predicate>
+ bool wait_for(std::unique_lock<QtPrivate::mutex> &lock,
+ const std::chrono::duration<Rep, Period> &d, Predicate p)
+ {
+ const auto timer = QDeadlineTimer{d};
+ while (!p()) {
+ if (!QWaitCondition::wait(lock.mutex(), timer))
+ return p();
+ }
+ return true;
+ }
+
+ template <typename Clock, typename Duration>
+ std::cv_status wait_until(std::unique_lock<QtPrivate::mutex> &lock,
+ const std::chrono::time_point<Clock, Duration> &t)
+ {
+ return QWaitCondition::wait(lock.mutex(), QDeadlineTimer{t})
+ ? std::cv_status::no_timeout
+ : std::cv_status::timeout;
+ }
+
+ template <typename Clock, typename Duration, typename Predicate>
+ bool wait_until(std::unique_lock<QtPrivate::mutex> &lock,
+ const std::chrono::time_point<Clock, Duration> &t, Predicate p)
+ {
+ const auto timer = QDeadlineTimer{t};
+ while (!p()) {
+ if (!QWaitCondition::wait(lock.mutex(), timer))
+ return p();
+ }
+ return true;
+ }
+
+};
+
+#else // Integrity
+
+using mutex = std::mutex;
+using condition_variable = std::condition_variable;
+
+#endif // Integrity
+
+} // namespace QtPrivate
+
+QT_END_NAMESPACE
+
+#endif /* QWAITCONDITION_P_H */
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index 9fc9af0e65..25cf68a324 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -6,6 +6,7 @@ HEADERS += \
thread/qrunnable.h \
thread/qthread.h \
thread/qthreadstorage.h \
+ thread/qwaitcondition_p.h \
thread/qwaitcondition.h
SOURCES += \