diff options
Diffstat (limited to 'src/corelib/thread')
-rw-r--r-- | src/corelib/thread/qbasicatomic.h | 6 | ||||
-rw-r--r-- | src/corelib/thread/qexception.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qfutureinterface.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qmutex.cpp | 6 | ||||
-rw-r--r-- | src/corelib/thread/qmutex_linux.cpp | 4 | ||||
-rw-r--r-- | src/corelib/thread/qorderedmutexlocker_p.h | 2 | ||||
-rw-r--r-- | src/corelib/thread/qreadwritelock.cpp | 10 | ||||
-rw-r--r-- | src/corelib/thread/qresultstore.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qsemaphore.h | 7 | ||||
-rw-r--r-- | src/corelib/thread/qthread.cpp | 36 | ||||
-rw-r--r-- | src/corelib/thread/qthread.h | 8 | ||||
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 28 | ||||
-rw-r--r-- | src/corelib/thread/qthread_win.cpp | 6 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qthreadstorage.cpp | 12 | ||||
-rw-r--r-- | src/corelib/thread/qwaitcondition.h | 39 | ||||
-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 | 6 | ||||
-rw-r--r-- | src/corelib/thread/thread.pri | 1 |
20 files changed, 279 insertions, 87 deletions
diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 9804e60119..c9c95cf6ce 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -47,9 +47,9 @@ # include <QtCore/qatomic_bootstrap.h> // If C++11 atomics are supported, use them! -// Note that constexpr support is sometimes disabled in QNX builds but its -// library has <atomic>. -#elif defined(Q_COMPILER_ATOMICS) && (defined(Q_COMPILER_CONSTEXPR) || defined(Q_OS_QNX)) +// Note that constexpr support is sometimes disabled in QNX or INTEGRITY builds, +// but their libraries have <atomic>. +#elif defined(Q_COMPILER_ATOMICS) && (defined(Q_COMPILER_CONSTEXPR) || defined(Q_OS_QNX) || defined(Q_OS_INTEGRITY)) # include <QtCore/qatomic_cxx11.h> // We only support one fallback: MSVC, because even on version 2015, it lacks full constexpr support diff --git a/src/corelib/thread/qexception.cpp b/src/corelib/thread/qexception.cpp index a3e30d5a7a..f9c63085b7 100644 --- a/src/corelib/thread/qexception.cpp +++ b/src/corelib/thread/qexception.cpp @@ -199,7 +199,7 @@ void ExceptionStore::setException(const QException &e) bool ExceptionStore::hasException() const { - return (exceptionHolder.exception() != 0); + return (exceptionHolder.exception() != nullptr); } ExceptionHolder ExceptionStore::exception() diff --git a/src/corelib/thread/qfutureinterface.cpp b/src/corelib/thread/qfutureinterface.cpp index 6430f38a3b..f1fd40e7b6 100644 --- a/src/corelib/thread/qfutureinterface.cpp +++ b/src/corelib/thread/qfutureinterface.cpp @@ -471,7 +471,7 @@ bool QFutureInterfaceBase::derefT() const QFutureInterfaceBasePrivate::QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState) : refCount(1), m_progressValue(0), m_progressMinimum(0), m_progressMaximum(0), state(initialState), - manualProgress(false), m_expectedResultCount(0), runnable(0), m_pool(0) + manualProgress(false), m_expectedResultCount(0), runnable(nullptr), m_pool(nullptr) { progressTime.invalidate(); } diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 9e52f286ee..f3883278e3 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -70,7 +70,7 @@ class QRecursiveMutexPrivate : public QMutexData { public: QRecursiveMutexPrivate() - : QMutexData(QMutex::Recursive), owner(0), count(0) {} + : QMutexData(QMutex::Recursive), owner(nullptr), count(0) {} // written to by the thread that first owns 'mutex'; // read during attempts to acquire ownership of 'mutex' from any other thread: @@ -186,7 +186,7 @@ public: */ QMutex::QMutex(RecursionMode mode) { - d_ptr.storeRelaxed(mode == Recursive ? new QRecursiveMutexPrivate : 0); + d_ptr.storeRelaxed(mode == Recursive ? new QRecursiveMutexPrivate : nullptr); } /*! @@ -799,7 +799,7 @@ inline void QRecursiveMutexPrivate::unlock() noexcept if (count > 0) { count--; } else { - owner.storeRelaxed(0); + owner.storeRelaxed(nullptr); mutex.QBasicMutex::unlock(); } } diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp index 3270875471..72002838cf 100644 --- a/src/corelib/thread/qmutex_linux.cpp +++ b/src/corelib/thread/qmutex_linux.cpp @@ -106,7 +106,7 @@ static inline QMutexData *dummyFutexValue() } template <bool IsTimed> static inline -bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -1, QElapsedTimer *elapsedTimer = 0) noexcept +bool lockInternal_helper(QBasicAtomicPointer<QMutexData> &d_ptr, int timeout = -1, QElapsedTimer *elapsedTimer = nullptr) noexcept { if (!IsTimed) timeout = -1; @@ -175,7 +175,7 @@ void QBasicMutex::unlockInternal() noexcept Q_UNUSED(d); Q_ASSERT(!isRecursive()); - d_ptr.storeRelease(0); + d_ptr.storeRelease(nullptr); futexWakeOne(d_ptr); } diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index 570c526225..83edfd5879 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -69,7 +69,7 @@ class QOrderedMutexLocker public: QOrderedMutexLocker(QBasicMutex *m1, QBasicMutex *m2) : mtx1((m1 == m2) ? m1 : (std::less<QBasicMutex *>()(m1, m2) ? m1 : m2)), - mtx2((m1 == m2) ? 0 : (std::less<QBasicMutex *>()(m1, m2) ? m2 : m1)), + mtx2((m1 == m2) ? nullptr : (std::less<QBasicMutex *>()(m1, m2) ? m2 : m1)), locked(false) { relock(); diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp index 14654986a0..8c28507d5a 100644 --- a/src/corelib/thread/qreadwritelock.cpp +++ b/src/corelib/thread/qreadwritelock.cpp @@ -227,7 +227,7 @@ bool QReadWriteLock::tryLockForRead(int timeout) return true; while (true) { - if (d == 0) { + if (d == nullptr) { if (!d_ptr.testAndSetAcquire(nullptr, dummyLockedForRead, d)) continue; return true; @@ -341,7 +341,7 @@ bool QReadWriteLock::tryLockForWrite(int timeout) return true; while (true) { - if (d == 0) { + if (d == nullptr) { if (!d_ptr.testAndSetAcquire(d, dummyLockedForWrite, d)) continue; return true; @@ -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); @@ -581,7 +581,7 @@ void QReadWriteLockPrivate::recursiveUnlock() if (self == currentWriter) { if (--writerCount > 0) return; - currentWriter = 0; + currentWriter = nullptr; } else { auto it = currentReaders.find(self); if (it == currentReaders.end()) { diff --git a/src/corelib/thread/qresultstore.cpp b/src/corelib/thread/qresultstore.cpp index 1b3bc20eca..0b82b938e1 100644 --- a/src/corelib/thread/qresultstore.cpp +++ b/src/corelib/thread/qresultstore.cpp @@ -192,7 +192,7 @@ int ResultStoreBase::addResults(int index, const void *results, int vectorSize, ResultItem filteredIn(results, vectorSize); insertResultItem(index, filteredIn); } - ResultItem filteredAway(0, totalCount - vectorSize); + ResultItem filteredAway(nullptr, totalCount - vectorSize); return insertResultItem(index + vectorSize, filteredAway); } } 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.cpp b/src/corelib/thread/qthread.cpp index 880ae9e046..d3bb372b00 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -49,6 +49,8 @@ #include "qthread_p.h" #include "private/qcoreapplication_p.h" +#include <limits> + QT_BEGIN_NAMESPACE /* @@ -57,7 +59,7 @@ QT_BEGIN_NAMESPACE QThreadData::QThreadData(int initialRefCount) : _ref(initialRefCount), loopLevel(0), scopeLevel(0), - eventDispatcher(0), + eventDispatcher(nullptr), quitNow(false), canWait(true), isAdopted(false), requiresCoreApplication(true) { // fprintf(stderr, "QThreadData %p created\n", this); @@ -397,7 +399,7 @@ QThreadPrivate::~QThreadPrivate() QThread *QThread::currentThread() { QThreadData *data = QThreadData::current(); - Q_ASSERT(data != 0); + Q_ASSERT(data != nullptr); return data->thread.loadAcquire(); } @@ -449,7 +451,7 @@ QThread::~QThread() if (d->running && !d->finished && !d->data->isAdopted) qFatal("QThread: Destroyed while thread is still running"); - d->data->thread = 0; + d->data->thread = nullptr; } } @@ -726,7 +728,8 @@ QThread::Priority QThread::priority() const */ /*! - \fn bool QThread::wait(unsigned long time) + \fn bool QThread::wait(QDeadlineTimer deadline) + \since 5.15 Blocks the thread until either of these conditions is met: @@ -735,12 +738,14 @@ QThread::Priority QThread::priority() const execution (i.e. when it returns from \l{run()}). This function will return true if the thread has finished. It also returns true if the thread has not been started yet. - \li \a time milliseconds has elapsed. If \a time is ULONG_MAX (the - default), then the wait will never timeout (the thread must - return from \l{run()}). This function will return false if the - wait timed out. + \li The \a deadline is reached. This function will return false if the + deadline is reached. \endlist + A deadline timer set to \c QDeadlineTimer::Forever (the default) will never + time out: in this case, the function only returns when the thread returns + from \l{run()} or if the thread has not yet started. + This provides similar functionality to the POSIX \c pthread_join() function. @@ -833,9 +838,9 @@ void QThread::exit(int returnCode) } } -bool QThread::wait(unsigned long time) +bool QThread::wait(QDeadlineTimer deadline) { - Q_UNUSED(time); + Q_UNUSED(deadline); return false; } @@ -966,6 +971,17 @@ void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) } } +/*! + \fn bool QThread::wait(unsigned long time) + \overload +*/ +bool QThread::wait(unsigned long time) +{ + if (time == std::numeric_limits<unsigned long>::max()) + return wait(QDeadlineTimer(QDeadlineTimer::Forever)); + return wait(QDeadlineTimer(time)); +} + #if QT_CONFIG(thread) /*! diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index c7a6dc8f1a..2072e22340 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -42,6 +42,7 @@ #define QTHREAD_H #include <QtCore/qobject.h> +#include <QtCore/qdeadlinetimer.h> // For QThread::create. The configure-time test just checks for the availability // of std::future and std::async; for the C++17 codepath we perform some extra @@ -57,8 +58,6 @@ # endif #endif -#include <limits.h> - QT_BEGIN_NAMESPACE @@ -135,8 +134,9 @@ public Q_SLOTS: void quit(); public: - // default argument causes thread to block indefinetely - bool wait(unsigned long time = ULONG_MAX); + bool wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)); + // ### Qt6 inline this function + bool wait(unsigned long time); static void sleep(unsigned long); static void msleep(unsigned long); diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index cb3c0d6bb1..1da68b3130 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -109,7 +109,7 @@ Q_STATIC_ASSERT(sizeof(pthread_t) <= sizeof(Qt::HANDLE)); enum { ThreadPriorityResetFlag = 0x80000000 }; -static thread_local QThreadData *currentThreadData = 0; +static thread_local QThreadData *currentThreadData = nullptr; static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT; static pthread_key_t current_thread_data_key; @@ -144,7 +144,7 @@ static void destroy_current_thread_data(void *p) #if defined(Q_OS_VXWORKS) (void *)1); #else - 0); + nullptr); #endif } @@ -182,8 +182,8 @@ static void set_thread_data(QThreadData *data) static void clear_thread_data() { - currentThreadData = 0; - pthread_setspecific(current_thread_data_key, 0); + currentThreadData = nullptr; + pthread_setspecific(current_thread_data_key, nullptr); } template <typename T> @@ -226,7 +226,7 @@ QThreadData *QThreadData::current(bool createIfNecessary) } QT_CATCH(...) { clear_thread_data(); data->deref(); - data = 0; + data = nullptr; QT_RETHROW; } data->deref(); @@ -294,7 +294,7 @@ static void setCurrentThreadName(const char *name) void *QThreadPrivate::start(void *arg) { #if !defined(Q_OS_ANDROID) - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr); #endif pthread_cleanup_push(QThreadPrivate::finish, arg); @@ -336,7 +336,7 @@ void *QThreadPrivate::start(void *arg) emit thr->started(QThread::QPrivateSignal()); #if !defined(Q_OS_ANDROID) - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, nullptr); pthread_testcancel(); #endif thr->run(); @@ -360,7 +360,7 @@ void *QThreadPrivate::start(void *arg) // thrown. pthread_cleanup_pop(1); - return 0; + return nullptr; } void QThreadPrivate::finish(void *arg) @@ -379,13 +379,13 @@ void QThreadPrivate::finish(void *arg) void *data = &d->data->tls; locker.unlock(); emit thr->finished(QThread::QPrivateSignal()); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QThreadStorageData::finish((void **)data); locker.relock(); QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.loadRelaxed(); if (eventDispatcher) { - d->data->eventDispatcher = 0; + d->data->eventDispatcher = nullptr; locker.unlock(); eventDispatcher->closingDown(); delete eventDispatcher; @@ -751,7 +751,7 @@ void QThread::terminate() #endif } -bool QThread::wait(unsigned long time) +bool QThread::wait(QDeadlineTimer deadline) { Q_D(QThread); QMutexLocker locker(&d->mutex); @@ -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(), deadline)) return false; } return true; @@ -774,14 +774,14 @@ bool QThread::wait(unsigned long time) void QThread::setTerminationEnabled(bool enabled) { QThread *thr = currentThread(); - Q_ASSERT_X(thr != 0, "QThread::setTerminationEnabled()", + Q_ASSERT_X(thr != nullptr, "QThread::setTerminationEnabled()", "Current thread was not started with QThread."); Q_UNUSED(thr) #if defined(Q_OS_ANDROID) Q_UNUSED(enabled); #else - pthread_setcancelstate(enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, NULL); + pthread_setcancelstate(enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, nullptr); if (enabled) pthread_testcancel(); #endif diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index a72df2fc40..3df7080caf 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -610,7 +610,7 @@ void QThread::terminate() QThreadPrivate::finish(this, false); } -bool QThread::wait(unsigned long time) +bool QThread::wait(QDeadlineTimer deadline) { Q_D(QThread); QMutexLocker locker(&d->mutex); @@ -627,9 +627,9 @@ bool QThread::wait(unsigned long time) bool ret = false; #ifndef Q_OS_WINRT - switch (WaitForSingleObject(d->handle, time)) { + switch (WaitForSingleObject(d->handle, deadline.remainingTime())) { #else - switch (WaitForSingleObjectEx(d->handle, time, false)) { + switch (WaitForSingleObjectEx(d->handle, deadline.remainingTime(), false)) { #endif case WAIT_OBJECT_0: ret = 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/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp index fdc484d2d2..464559ffa5 100644 --- a/src/corelib/thread/qthreadstorage.cpp +++ b/src/corelib/thread/qthreadstorage.cpp @@ -116,7 +116,7 @@ void **QThreadStorageData::get() const QThreadData *data = QThreadData::current(); if (!data) { qWarning("QThreadStorage::get: QThreadStorage can only be used with threads started with QThread"); - return 0; + return nullptr; } QVector<void *> &tls = data->tls; if (tls.size() <= id) @@ -128,7 +128,7 @@ void **QThreadStorageData::get() const *v, data->thread.loadRelaxed()); - return *v ? v : 0; + return *v ? v : nullptr; } void **QThreadStorageData::set(void *p) @@ -136,7 +136,7 @@ void **QThreadStorageData::set(void *p) QThreadData *data = QThreadData::current(); if (!data) { qWarning("QThreadStorage::set: QThreadStorage can only be used with threads started with QThread"); - return 0; + return nullptr; } QVector<void *> &tls = data->tls; if (tls.size() <= id) @@ -144,7 +144,7 @@ void **QThreadStorageData::set(void *p) void *&value = tls[id]; // delete any previous data - if (value != 0) { + if (value != nullptr) { DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p", id, value, @@ -156,7 +156,7 @@ void **QThreadStorageData::set(void *p) locker.unlock(); void *q = value; - value = 0; + value = nullptr; if (destructor) destructor(q); @@ -178,7 +178,7 @@ void QThreadStorageData::finish(void **p) while (!tls->isEmpty()) { void *&value = tls->last(); void *q = value; - value = 0; + value = nullptr; int i = tls->size() - 1; tls->resize(i); diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h index 11520e4cfe..079049af25 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 <QtCore/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(); @@ -80,21 +82,28 @@ private: #else class QMutex; +class QReadWriteLock; + class Q_CORE_EXPORT QWaitCondition { public: QWaitCondition() {} ~QWaitCondition() {} - bool wait(QMutex *mutex, unsigned long time = ULONG_MAX) - { - Q_UNUSED(mutex); - Q_UNUSED(time); - return true; - } + bool wait(QMutex *, QDeadlineTimer = QDeadlineTimer(QDeadlineTimer::Forever)) + { return true; } + bool wait(QReadWriteLock *, QDeadlineTimer = QDeadlineTimer(QDeadlineTimer::Forever)) + { return true; } +#if QT_DEPRECATED_SINCE(5, 15) + bool wait(QMutex *, unsigned long) { return true; } + bool wait(QReadWriteLock *, unsigned long) { return true; } +#endif void wakeOne() {} void wakeAll() {} + + void notify_one() { wakeOne(); } + void notify_all() { wakeAll(); } }; #endif // QT_CONFIG(thread) 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..80f9e780e7 100644 --- a/src/corelib/thread/qwaitcondition_unix.cpp +++ b/src/corelib/thread/qwaitcondition_unix.cpp @@ -173,7 +173,7 @@ public: QWaitCondition::QWaitCondition() { d = new QWaitConditionPrivate; - report_error(pthread_mutex_init(&d->mutex, NULL), "QWaitCondition", "mutex init"); + report_error(pthread_mutex_init(&d->mutex, nullptr), "QWaitCondition", "mutex init"); qt_initialize_pthread_cond(&d->cond, "QWaitCondition"); d->waiters = d->wakeups = 0; } @@ -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 += \ |