diff options
Diffstat (limited to 'src/corelib/thread')
-rw-r--r-- | src/corelib/thread/qbasicatomic.h | 12 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.cpp | 7 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.h | 13 | ||||
-rw-r--r-- | src/corelib/thread/qreadwritelock.cpp | 13 | ||||
-rw-r--r-- | src/corelib/thread/qreadwritelock_p.h | 18 | ||||
-rw-r--r-- | src/corelib/thread/qsemaphore.h | 7 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition_p.h | 153 | ||||
-rw-r--r-- | src/corelib/thread/thread.pri | 1 |
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 += \ |