diff options
Diffstat (limited to 'src/corelib/thread')
-rw-r--r-- | src/corelib/thread/qreadwritelock.cpp | 4 | ||||
-rw-r--r-- | src/corelib/thread/qsemaphore.h | 7 | ||||
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition.h | 20 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition.qdoc | 34 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition_p.h | 153 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition_unix.cpp | 4 | ||||
-rw-r--r-- | src/corelib/thread/thread.pri | 1 |
9 files changed, 198 insertions, 29 deletions
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp index 14654986a0..c8463de402 100644 --- a/src/corelib/thread/qreadwritelock.cpp +++ b/src/corelib/thread/qreadwritelock.cpp @@ -477,7 +477,7 @@ bool QReadWriteLockPrivate::lockForRead(int timeout) if (elapsed > timeout) return false; waitingReaders++; - readerCond.wait(&mutex, timeout - elapsed); + readerCond.wait(&mutex, QDeadlineTimer(timeout - elapsed)); } else { waitingReaders++; readerCond.wait(&mutex); @@ -511,7 +511,7 @@ bool QReadWriteLockPrivate::lockForWrite(int timeout) return false; } waitingWriters++; - writerCond.wait(&mutex, timeout - elapsed); + writerCond.wait(&mutex, QDeadlineTimer(timeout - elapsed)); } else { waitingWriters++; writerCond.wait(&mutex); 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/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index cb3c0d6bb1..b19922753a 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -765,7 +765,7 @@ bool QThread::wait(unsigned long time) return true; while (d->running) { - if (!d->thread_done.wait(locker.mutex(), time)) + if (!d->thread_done.wait(locker.mutex(), QDeadlineTimer(time))) return false; } return true; diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index 4d2389f699..5f23a78c8a 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -136,7 +136,7 @@ void QThreadPoolThread::run() manager->waitingThreads.enqueue(this); registerThreadInactive(); // wait for work, exiting after the expiry timeout is reached - runnableReady.wait(locker.mutex(), manager->expiryTimeout); + runnableReady.wait(locker.mutex(), QDeadlineTimer(manager->expiryTimeout)); ++manager->activeThreads; if (manager->waitingThreads.removeOne(this)) expired = true; diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h index 11520e4cfe..86e2141f84 100644 --- a/src/corelib/thread/qwaitcondition.h +++ b/src/corelib/thread/qwaitcondition.h @@ -40,15 +40,12 @@ #ifndef QWAITCONDITION_H #define QWAITCONDITION_H -#include <QtCore/qglobal.h> - -#include <limits.h> +#include <QDeadlineTimer> QT_BEGIN_NAMESPACE #if QT_CONFIG(thread) -class QDeadlineTimer; class QWaitConditionPrivate; class QMutex; class QReadWriteLock; @@ -59,11 +56,16 @@ public: QWaitCondition(); ~QWaitCondition(); - // ### Qt 6: remove unsigned long overloads - bool wait(QMutex *lockedMutex, unsigned long time = ULONG_MAX); - bool wait(QMutex *lockedMutex, QDeadlineTimer deadline); - bool wait(QReadWriteLock *lockedReadWriteLock, unsigned long time = ULONG_MAX); - bool wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline); + bool wait(QMutex *lockedMutex, + QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)); + bool wait(QReadWriteLock *lockedReadWriteLock, + QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)); +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_VERSION_X_5_15("Use wait(QMutex *lockedMutex, QDeadlineTimer deadline) instead") + bool wait(QMutex *lockedMutex, unsigned long time); + QT_DEPRECATED_VERSION_X_5_15("Use wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline) instead") + bool wait(QReadWriteLock *lockedReadWriteLock, unsigned long time); +#endif void wakeOne(); void wakeAll(); diff --git a/src/corelib/thread/qwaitcondition.qdoc b/src/corelib/thread/qwaitcondition.qdoc index eebc28f059..9da6f6f25c 100644 --- a/src/corelib/thread/qwaitcondition.qdoc +++ b/src/corelib/thread/qwaitcondition.qdoc @@ -119,10 +119,22 @@ \sa wakeOne() */ +#if QT_DEPRECATED_SINCE(5, 15) /*! \fn bool QWaitCondition::wait(QMutex *lockedMutex, unsigned long time) + \obsolete use wait(QMutex *lockedMutex, QDeadlineTimer deadline) instead +*/ +/*! + \fn bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, unsigned long time) + \obsolete use wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline) instead +*/ +#endif - Releases the \a lockedMutex and waits on the wait condition. The +/*! + \fn bool QWaitCondition::wait(QMutex *lockedMutex, QDeadlineTimer deadline) + \since 5.12 + + Releases the \a lockedMutex and waits on the wait condition. The \a lockedMutex must be initially locked by the calling thread. If \a lockedMutex is not in a locked state, the behavior is undefined. If \a lockedMutex is a recursive mutex, this function @@ -132,10 +144,10 @@ \list \li Another thread signals it using wakeOne() or wakeAll(). This function will return true in this case. - \li \a time milliseconds has elapsed. If \a time is \c ULONG_MAX - (the default), then the wait will never timeout (the event - must be signalled). This function will return false if the - wait timed out. + \li the deadline given by \a deadline is reached. If \a deadline is + \c QDeadlineTimer::Forever (the default), then the wait will never + timeout (the event must be signalled). This function will return + false if the wait timed out. \endlist The \a lockedMutex will be returned to the same locked state. This @@ -146,8 +158,8 @@ */ /*! - \fn bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, unsigned long time) - \since 4.4 + \fn bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline) + \since 5.12 Releases the \a lockedReadWriteLock and waits on the wait condition. The \a lockedReadWriteLock must be initially locked by the @@ -160,10 +172,10 @@ \list \li Another thread signals it using wakeOne() or wakeAll(). This function will return true in this case. - \li \a time milliseconds has elapsed. If \a time is \c ULONG_MAX - (the default), then the wait will never timeout (the event - must be signalled). This function will return false if the - wait timed out. + \li the deadline given by \a deadline is reached. If \a deadline is + \c QDeadlineTimer::Forever (the default), then the wait will never + timeout (the event must be signalled). This function will return + false if the wait timed out. \endlist The \a lockedReadWriteLock will be returned to the same locked 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/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp index dd7475cec5..a8dfb9999c 100644 --- a/src/corelib/thread/qwaitcondition_unix.cpp +++ b/src/corelib/thread/qwaitcondition_unix.cpp @@ -202,12 +202,14 @@ void QWaitCondition::wakeAll() report_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeAll()", "mutex unlock"); } +#if QT_DEPRECATED_SINCE(5, 15) bool QWaitCondition::wait(QMutex *mutex, unsigned long time) { if (time == std::numeric_limits<unsigned long>::max()) return wait(mutex, QDeadlineTimer(QDeadlineTimer::Forever)); return wait(mutex, QDeadlineTimer(time)); } +#endif bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline) { @@ -229,12 +231,14 @@ bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline) return returnValue; } +#if QT_DEPRECATED_SINCE(5, 15) bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) { if (time == std::numeric_limits<unsigned long>::max()) return wait(readWriteLock, QDeadlineTimer(QDeadlineTimer::Forever)); return wait(readWriteLock, QDeadlineTimer(time)); } +#endif bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline) { 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 += \ |