From 288326eaf8819f9c3bf978bd11af8ea0ce3ca4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 16 May 2023 17:57:12 +0200 Subject: [PATCH] QWaitCondition/win: Enable actually waiting longer than u32::max This is done, in part, by swapping the dependency between the wait() overloads. Furthermore, since QDeadlineTimer is 64-bit and the Win32 API is 32-bit we have to wait more than once to actually wait until the deadline is reached. The unsigned int overload has no documented concept of waiting 'forever'. Though, internally we turn u32::max into 'forever'. Change-Id: I47d719c0c29bcd6fa0c0043d168a456f2c05774e Reviewed-by: Thiago Macieira --- src/corelib/thread/qwaitcondition_win.cpp | 50 ++++++++++++++--------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index c176241f47..ba53309e1b 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -43,7 +43,7 @@ public: EventQueue freeQueue; QWaitConditionEvent *pre(); - bool wait(QWaitConditionEvent *wce, unsigned long time); + bool wait(QWaitConditionEvent *wce, QDeadlineTimer deadline); void post(QWaitConditionEvent *wce, bool ret); }; @@ -68,19 +68,25 @@ QWaitConditionEvent *QWaitConditionPrivate::pre() return wce; } -bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, unsigned long time) +bool QWaitConditionPrivate::wait(QWaitConditionEvent *wce, QDeadlineTimer deadline) { // wait for the event - bool ret = false; - switch (WaitForSingleObjectEx(wce->event, time, FALSE)) { - default: - break; + while (true) { + const DWORD timeout = deadline.isForever() + ? INFINITE + : DWORD(std::min(deadline.remainingTime(), qint64(INFINITE - 1))); - case WAIT_OBJECT_0: - ret = true; - break; + switch (WaitForSingleObjectEx(wce->event, timeout, FALSE)) { + case WAIT_OBJECT_0: + return true; + case WAIT_TIMEOUT: + if (deadline.hasExpired()) + return false; + break; + default: + return false; + } } - return ret; } void QWaitConditionPrivate::post(QWaitConditionEvent *wce, bool ret) @@ -123,6 +129,13 @@ QWaitCondition::~QWaitCondition() } bool QWaitCondition::wait(QMutex *mutex, unsigned long time) +{ + if (time == std::numeric_limits::max()) + return wait(mutex, QDeadlineTimer(QDeadlineTimer::Forever)); + return wait(mutex, QDeadlineTimer(time)); +} + +bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline) { if (!mutex) return false; @@ -130,7 +143,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) QWaitConditionEvent *wce = d->pre(); mutex->unlock(); - bool returnValue = d->wait(wce, time); + bool returnValue = d->wait(wce, deadline); mutex->lock(); d->post(wce, returnValue); @@ -138,12 +151,14 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) return returnValue; } -bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline) +bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) { - return wait(mutex, deadline.remainingTime()); + if (time == std::numeric_limits::max()) + return wait(readWriteLock, QDeadlineTimer(QDeadlineTimer::Forever)); + return wait(readWriteLock, QDeadlineTimer(time)); } -bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) +bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline) { using namespace QReadWriteLockStates; @@ -160,7 +175,7 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) QWaitConditionEvent *wce = d->pre(); readWriteLock->unlock(); - bool returnValue = d->wait(wce, time); + bool returnValue = d->wait(wce, deadline); if (previousState == LockedForWrite) readWriteLock->lockForWrite(); @@ -171,11 +186,6 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) return returnValue; } -bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline) -{ - return wait(readWriteLock, deadline.remainingTime()); -} - void QWaitCondition::wakeOne() { // wake up the first waiting thread in the queue