QThread: add sleep(std::chrono::nanoseconds) overload

All the other overloads are implemented using the new one.

Windows change relies on the pre-check in the code review making sure it
compiles.

[ChangeLog][QtCore][QThread] Added sleep(std::chrono::nanoseconds)
overload.

Task-number: QTBUG-110059
Change-Id: I9a4f4bf09041788ec9275093b6b8d0386521e286
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Ahmad Samir 2023-02-27 21:36:45 +02:00
parent d7f0677368
commit 0d29a406f7
26 changed files with 120 additions and 91 deletions

View File

@ -751,16 +751,28 @@ QThread::Priority QThread::priority() const
}
/*!
\fn void QThread::sleep(unsigned long secs)
\fn void QThread::sleep(std::chrono::nanoseconds nsecs)
\since 6.6
Forces the current thread to sleep for \a secs seconds.
Forces the current thread to sleep for \a nsecs.
Avoid using this function if you need to wait for a given condition to
change. Instead, connect a slot to the signal that indicates the change or
use an event handler (see \l QObject::event()).
\note This function does not guarantee accuracy. The application may sleep
longer than \a secs under heavy load conditions.
longer than \a nsecs under heavy load conditions.
*/
/*!
\fn void QThread::sleep(unsigned long secs)
Forces the current thread to sleep for \a secs seconds.
This is an overloaded function, equivalent to calling:
\code
QThread::sleep(std::chrono::seconds{secs});
\endcode
\sa msleep(), usleep()
*/
@ -768,11 +780,10 @@ QThread::Priority QThread::priority() const
/*!
\fn void QThread::msleep(unsigned long msecs)
Forces the current thread to sleep for \a msecs milliseconds.
Avoid using this function if you need to wait for a given condition to
change. Instead, connect a slot to the signal that indicates the change or
use an event handler (see \l QObject::event()).
This is an overloaded function, equivalent to calling:
\code
QThread::sleep(std::chrono::milliseconds{msecs});
\endcode
\note This function does not guarantee accuracy. The application may sleep
longer than \a msecs under heavy load conditions. Some OSes might round \a
@ -784,11 +795,10 @@ QThread::Priority QThread::priority() const
/*!
\fn void QThread::usleep(unsigned long usecs)
Forces the current thread to sleep for \a usecs microseconds.
Avoid using this function if you need to wait for a given condition to
change. Instead, connect a slot to the signal that indicates the change or
use an event handler (see \l QObject::event()).
This is an overloaded function, equivalent to calling:
\code
QThread::sleep(std::chrono::microseconds{secs});
\endcode
\note This function does not guarantee accuracy. The application may sleep
longer than \a usecs under heavy load conditions. Some OSes might round \a

View File

@ -92,6 +92,7 @@ public:
static void sleep(unsigned long);
static void msleep(unsigned long);
static void usleep(unsigned long);
static void sleep(std::chrono::nanoseconds nsec);
Q_SIGNALS:
void started(QPrivateSignal);

View File

@ -507,17 +507,22 @@ static void qt_nanosleep(timespec amount)
void QThread::sleep(unsigned long secs)
{
qt_nanosleep(durationToTimespec(std::chrono::seconds{secs}));
sleep(std::chrono::seconds{secs});
}
void QThread::msleep(unsigned long msecs)
{
qt_nanosleep(durationToTimespec(std::chrono::milliseconds{msecs}));
sleep(std::chrono::milliseconds{msecs});
}
void QThread::usleep(unsigned long usecs)
{
qt_nanosleep(durationToTimespec(std::chrono::microseconds{usecs}));
sleep(std::chrono::microseconds{usecs});
}
void QThread::sleep(std::chrono::nanoseconds nsec)
{
qt_nanosleep(durationToTimespec(nsec));
}
#if QT_CONFIG(thread)

View File

@ -368,6 +368,12 @@ void QThread::yieldCurrentThread()
#endif // QT_CONFIG(thread)
void QThread::sleep(std::chrono::nanoseconds nsecs)
{
using namespace std::chrono;
::Sleep(DWORD(duration_cast<milliseconds>(nsecs).count()));
}
void QThread::sleep(unsigned long secs)
{
::Sleep(secs * 1000);

View File

@ -102,7 +102,7 @@ bool QTouchEventSequence::commit(bool processEvents)
{
if (points.isEmpty())
return false;
QThread::msleep(1);
QThread::sleep(std::chrono::milliseconds{1});
bool ret = false;
if (targetWindow)
ret = qt_handleTouchEventv2(targetWindow, device, points.values());

View File

@ -123,7 +123,7 @@ bool QTouchEventWidgetSequence::commit(bool processEvents)
bool ret = false;
if (points.isEmpty())
return ret;
QThread::msleep(1);
QThread::sleep(std::chrono::milliseconds{1});
if (targetWindow) {
ret = qt_handleTouchEventv2(targetWindow, device, points.values());
} else if (targetWidget) {

View File

@ -815,7 +815,7 @@ public:
void run() override {
int iter = 60;
while (--iter && !cancel.loadRelaxed())
QThread::currentThread()->msleep(25);
QThread::currentThread()->sleep(std::chrono::milliseconds{25});
}
};

View File

@ -13,7 +13,7 @@ static bool waitForDoneFileWritten(const QString &filePath, int msecs = 30000)
{
QDeadlineTimer t(msecs);
do {
QThread::msleep(250);
QThread::sleep(std::chrono::milliseconds{250});
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly))
continue;

View File

@ -2363,7 +2363,7 @@ public:
public slots:
void block()
{
QThread::sleep(1);
QThread::sleep(std::chrono::seconds{1});
}
};

View File

@ -355,7 +355,7 @@ void tst_QEventDispatcher::postEventFromThread()
threadPool->start([&]{
int loop = 1000 / 10; // give it a second
while (!done && --loop)
QThread::msleep(10);
QThread::sleep(std::chrono::milliseconds{10});
if (done)
return;
hadToQuit = true;
@ -393,7 +393,7 @@ void tst_QEventDispatcher::postEventFromEventHandler()
threadPool->start([&]{
int loop = 250 / 10; // give it 250ms
while (!done && --loop)
QThread::msleep(10);
QThread::sleep(std::chrono::milliseconds{10});
if (done)
return;
hadToQuit = true;

View File

@ -1959,7 +1959,7 @@ void tst_QFuture::nonGlobalThreadPool()
void run() override
{
const int ms = 100 + (QRandomGenerator::global()->bounded(100) - 100/2);
QThread::msleep(ulong(ms));
QThread::sleep(std::chrono::milliseconds{ms});
reportResult(Answer);
reportFinished();
}
@ -3477,7 +3477,7 @@ void tst_QFuture::runAndTake()
auto rabbit = [](){
// Let's wait a bit to give the test below some time
// to sync up with us with its watcher.
QThread::currentThread()->msleep(100);
QThread::currentThread()->sleep(std::chrono::milliseconds{100});
return UniquePtr(new int(10));
};

View File

@ -9,6 +9,7 @@
#include <private/qfutureinterface_p.h>
using namespace QtConcurrent;
using namespace std::chrono_literals;
#include <QTest>
@ -900,13 +901,13 @@ QT_WARNING_POP
QFuture<int> future = QtConcurrent::mapped(&pool, values, [&](int value) {
++count;
// Sleep, to make sure not all threads will start at once.
QThread::msleep(50);
QThread::sleep(50ms);
return value;
});
watcher.setFuture(future);
// Allow some threads to start before suspending.
QThread::msleep(200);
QThread::sleep(200ms);
watcher.suspend();
watcher.suspend();
@ -921,7 +922,7 @@ QT_WARNING_POP
QCOMPARE(resultReadyAfterPaused, count);
// Make sure no more results are reported before resuming.
QThread::msleep(200);
QThread::sleep(200ms);
QCOMPARE(resultReadyAfterPaused, resultReadySpy.size());
resultReadySpy.clear();

View File

@ -14,6 +14,8 @@
#include <qwaitcondition.h>
#include <private/qvolatile_p.h>
using namespace std::chrono_literals;
class tst_QMutex : public QObject
{
Q_OBJECT
@ -283,7 +285,7 @@ void tst_QMutex::tryLock_non_recursive()
testsTurn.acquire();
normalMutex.lock();
threadsTurn.release();
QThread::msleep(100);
QThread::sleep(100ms);
normalMutex.unlock();
// wait for thread to finish
@ -408,7 +410,7 @@ void tst_QMutex::try_lock_for_non_recursive()
testsTurn.acquire();
normalMutex.lock();
threadsTurn.release();
QThread::msleep(100);
QThread::sleep(100ms);
normalMutex.unlock();
// wait for thread to finish
@ -533,7 +535,7 @@ void tst_QMutex::try_lock_until_non_recursive()
testsTurn.acquire();
normalMutex.lock();
threadsTurn.release();
QThread::msleep(100);
QThread::sleep(100ms);
normalMutex.unlock();
// wait for thread to finish

View File

@ -14,6 +14,8 @@
#include <memory>
#include <chrono>
using namespace std::chrono_literals;
class tst_QPromise : public QObject
{
Q_OBJECT
@ -480,7 +482,7 @@ void tst_QPromise::cancelWhenReassigned()
promise.start();
ThreadWrapper thr([p = std::move(promise)] () mutable {
QThread::msleep(100);
QThread::sleep(100ms);
p = QPromise<int>(); // assign new promise, old must be correctly destroyed
});
@ -537,7 +539,7 @@ void tst_QPromise::finishWhenSwapped()
promise2.start();
ThreadWrapper thr([&promise1, &promise2] () mutable {
QThread::msleep(100);
QThread::sleep(100ms);
promise1.addResult(0);
promise2.addResult(1);
swap(promise1, promise2); // ADL must resolve this
@ -580,7 +582,7 @@ void tst_QPromise::cancelWhenMoved()
// Move promises to local scope to test cancellation behavior
ThreadWrapper thr([p1 = std::move(promise1), p2 = std::move(promise2)] () mutable {
QThread::msleep(100);
QThread::sleep(100ms);
p1 = std::move(p2);
p1.finish(); // this finish is for future #2
});
@ -616,7 +618,7 @@ void tst_QPromise::waitUntilResumed()
while (!f.isSuspended()) { // busy wait until worker thread suspends
QCOMPARE(f.isFinished(), false); // exit condition in case of failure
QThread::msleep(50); // allow another thread to actually carry on
QThread::sleep(50ms); // allow another thread to actually carry on
}
f.resume();
@ -645,7 +647,7 @@ void tst_QPromise::waitUntilCanceled()
while (!f.isSuspended()) { // busy wait until worker thread suspends
QCOMPARE(f.isFinished(), false); // exit condition in case of failure
QThread::msleep(50); // allow another thread to actually carry on
QThread::sleep(50ms); // allow another thread to actually carry on
}
f.cancel();

View File

@ -15,10 +15,6 @@
#ifdef Q_OS_UNIX
#include <unistd.h>
#endif
#if defined(Q_OS_WIN)
# include <qt_windows.h>
# define sleep(X) Sleep(X)
#endif
//on solaris, threads that loop on the release bool variable
//needs to sleep more than 1 usec.
@ -30,6 +26,8 @@
#include <stdio.h>
using namespace std::chrono_literals;
class tst_QReadWriteLock : public QObject
{
Q_OBJECT
@ -472,8 +470,8 @@ class ReadLockLoopThread : public QThread
public:
QReadWriteLock &testRwlock;
int runTime;
int holdTime;
int waitTime;
std::chrono::milliseconds holdTime;
std::chrono::milliseconds waitTime;
bool print;
QElapsedTimer t;
inline ReadLockLoopThread(QReadWriteLock &l, int runTime, int holdTime=0, int waitTime=0, bool print=false)
@ -489,9 +487,9 @@ public:
while (t.elapsed()<runTime) {
testRwlock.lockForRead();
if(print) printf("reading\n");
if (holdTime) msleep(ulong(holdTime));
if (holdTime > 0ms) sleep(holdTime);
testRwlock.unlock();
if (waitTime) msleep(ulong(waitTime));
if (waitTime > 0ms) sleep(waitTime);
}
}
};
@ -508,8 +506,8 @@ class WriteLockLoopThread : public QThread
public:
QReadWriteLock &testRwlock;
int runTime;
int holdTime;
int waitTime;
std::chrono::milliseconds holdTime;
std::chrono::milliseconds waitTime;
bool print;
QElapsedTimer t;
inline WriteLockLoopThread(QReadWriteLock &l, int runTime, int holdTime=0, int waitTime=0, bool print=false)
@ -525,9 +523,9 @@ public:
while (t.elapsed() < runTime) {
testRwlock.lockForWrite();
if (print) printf(".");
if (holdTime) msleep(ulong(holdTime));
if (holdTime > 0ms) sleep(holdTime);
testRwlock.unlock();
if (waitTime) msleep(ulong(waitTime));
if (waitTime > 0ms) sleep(waitTime);
}
}
};
@ -547,7 +545,7 @@ class WriteLockCountThread : public QThread
public:
QReadWriteLock &testRwlock;
int runTime;
int waitTime;
std::chrono::milliseconds waitTime;
int maxval;
QElapsedTimer t;
inline WriteLockCountThread(QReadWriteLock &l, int runTime, int waitTime, int maxval)
@ -568,7 +566,7 @@ public:
QtPrivate::volatilePreIncrement(count);
count=0;
testRwlock.unlock();
msleep(ulong(waitTime));
sleep(waitTime);
}
}
};
@ -585,7 +583,7 @@ class ReadLockCountThread : public QThread
public:
QReadWriteLock &testRwlock;
int runTime;
int waitTime;
std::chrono::milliseconds waitTime;
QElapsedTimer t;
inline ReadLockCountThread(QReadWriteLock &l, int runTime, int waitTime)
:testRwlock(l)
@ -600,7 +598,7 @@ public:
if(count)
qFatal("Non-zero count at Read! (%d)",count );
testRwlock.unlock();
msleep(ulong(waitTime));
sleep(waitTime);
}
}
};
@ -617,7 +615,7 @@ void tst_QReadWriteLock::readLockBlockRelease()
threadDone=false;
ReadLockThread rlt(testLock);
rlt.start();
sleep(1);
QThread::sleep(1s);
testLock.unlock();
rlt.wait();
QVERIFY(threadDone);
@ -634,7 +632,7 @@ void tst_QReadWriteLock::writeLockBlockRelease()
threadDone=false;
WriteLockThread wlt(testLock);
wlt.start();
sleep(1);
QThread::sleep(1s);
testLock.unlock();
wlt.wait();
QVERIFY(threadDone);
@ -653,10 +651,10 @@ void tst_QReadWriteLock::multipleReadersBlockRelease()
ReadLockReleasableThread rlt2(testLock);
rlt1.start();
rlt2.start();
sleep(1);
QThread::sleep(1s);
WriteLockThread wlt(testLock);
wlt.start();
sleep(1);
QThread::sleep(1s);
release.storeRelaxed(true);
wlt.wait();
rlt1.wait();

View File

@ -38,6 +38,8 @@
#include <QtTest/private/qemulationdetector_p.h>
using namespace std::chrono_literals;
class tst_QThread : public QObject
{
Q_OBJECT
@ -245,17 +247,19 @@ public:
elapsed = 0;
QElapsedTimer timer;
timer.start();
std::chrono::nanoseconds dur{0};
switch (sleepType) {
case Second:
sleep(interval);
dur = std::chrono::seconds{interval};
break;
case Millisecond:
msleep(interval);
dur = std::chrono::milliseconds{interval};
break;
case Microsecond:
usleep(interval);
dur = std::chrono::microseconds{interval};
break;
}
sleep(dur);
elapsed = timer.elapsed();
cond.wakeOne();
@ -1603,7 +1607,7 @@ void tst_QThread::createDestruction()
for (;;) {
if (QThread::currentThread()->isInterruptionRequested())
return;
QThread::msleep(1);
QThread::sleep(1ms);
}
};
@ -1722,7 +1726,7 @@ void tst_QThread::threadIdReuse()
bool threadIdReused = false;
for (int i = 0; i < 42; i++) {
QThread::msleep(1);
QThread::sleep(1ms);
Qt::HANDLE threadId2;
bool waitOk = false;

View File

@ -14,6 +14,8 @@
#include <unistd.h>
#endif
using namespace std::chrono_literals;
typedef void (*FunctionPointer)();
class FunctionPointerTask : public QRunnable
@ -391,7 +393,7 @@ void tst_QThreadPool::expiryTimeoutRace() // QTBUG-3786
const int numTasks = 20;
for (int i = 0; i < numTasks; ++i) {
threadPool.start(&task);
QThread::msleep(50); // exactly the same as the expiry timeout
QThread::sleep(50ms); // exactly the same as the expiry timeout
}
QVERIFY(task.semaphore.tryAcquire(numTasks, 10000));
QCOMPARE(task.runCount.loadRelaxed(), numTasks);
@ -1086,7 +1088,7 @@ void tst_QThreadPool::clearWithAutoDelete()
{
public:
MyRunnable() {}
void run() override { QThread::usleep(30); }
void run() override { QThread::sleep(30us); }
};
QThreadPool threadPool;

View File

@ -372,7 +372,7 @@ public:
{ }
static inline void sleep(ulong s)
{ QThread::sleep(s); }
{ QThread::sleep(std::chrono::seconds{s}); }
void run() override
{
@ -404,7 +404,7 @@ public:
{ }
static inline void sleep(ulong s)
{ QThread::sleep(s); }
{ QThread::sleep(std::chrono::seconds{s}); }
void run() override
{

View File

@ -55,7 +55,7 @@ namespace QTest {
{
if (process.state() == QProcess::Running) {
process.terminate();
QThread::msleep(20);
QThread::sleep(std::chrono::milliseconds{20});
if (process.state() == QProcess::Running)
process.kill();
}

View File

@ -1982,7 +1982,7 @@ class StrongThread: public QThread
protected:
void run() override
{
usleep(QRandomGenerator::global()->bounded(2000));
sleep(std::chrono::microseconds{QRandomGenerator::global()->bounded(2000)});
ptr->ref();
ptr.clear();
}
@ -1995,7 +1995,7 @@ class WeakThread: public QThread
protected:
void run() override
{
usleep(QRandomGenerator::global()->bounded(2000));
sleep(std::chrono::microseconds{QRandomGenerator::global()->bounded(2000)});
QSharedPointer<ThreadData> ptr = weak;
if (ptr)
ptr->ref();

View File

@ -8,16 +8,9 @@ Interface::Interface()
{
}
// Export the sleep function
// TODO QT5: remove this class, QThread::msleep is now public
class FriendlySleepyThread : public QThread {
public:
using QThread::msleep;
};
int Interface::sleepMethod(int msec)
{
FriendlySleepyThread::msleep(msec);
QThread::sleep(std::chrono::milliseconds{msec});
return 42;
}

View File

@ -753,7 +753,7 @@ public:
cache.remove(url);
if (QRandomGenerator::global()->bounded(5) == 1)
cache.clear();
sleep(0);
sleep(std::chrono::seconds{0});
}
//qDebug() << "read!" << read << i;
}

View File

@ -468,7 +468,7 @@ public:
protected:
void run() override
{
sleep(2);
sleep(std::chrono::seconds{2});
QTcpSocket socket;
socket.connectToHost(host, port);

View File

@ -84,7 +84,7 @@ void tst_QProgressDialog::autoShow()
// in order to test for the setValue() behavior instead
// See autoShowCtor() for the ctor timer check
dlg.setValue(value);
QThread::msleep(delay);
QThread::sleep(std::chrono::milliseconds{delay});
dlg.setValue(min+1);
QCOMPARE(dlg.isVisible(), expectedAutoShow);
}
@ -93,7 +93,7 @@ void tst_QProgressDialog::autoShowCtor()
{
QProgressDialog dlg;
QVERIFY(!dlg.isVisible());
QThread::msleep(dlg.minimumDuration());
QThread::sleep(std::chrono::milliseconds{dlg.minimumDuration()});
QTRY_VERIFY(dlg.isVisible());
}
@ -181,7 +181,7 @@ void tst_QProgressDialog::QTBUG_31046()
{
QProgressDialog dlg("", "", 50, 60);
dlg.setValue(0);
QThread::msleep(200);
QThread::sleep(std::chrono::milliseconds{200});
dlg.setValue(50);
QCOMPARE(50, dlg.value());
}

View File

@ -270,7 +270,7 @@ bool BaselineProtocol::connect(const QString &testCase, bool *dryrun, const Plat
socket.connectToHost(serverName, ServerPort);
if (!socket.waitForConnected(Timeout)) {
QThread::msleep(3000); // Wait a bit and try again, the server might just be restarting
QThread::sleep(std::chrono::seconds{3}); // Wait a bit and try again, the server might just be restarting
if (!socket.waitForConnected(Timeout)) {
errMsg += QLS("TCP connectToHost failed. Host:") + QLS(serverName) + QLS(" port:") + QString::number(ServerPort);
return false;

View File

@ -9,6 +9,8 @@
//#define USE_SEM_T
using namespace std::chrono_literals;
#if defined(Q_OS_UNIX)
#if !defined(USE_SEM_T)
# include <pthread.h>
@ -228,7 +230,8 @@ void tst_QMutex::contendedNative_data()
class NativeMutexThread : public QThread
{
NativeMutexType *mutex1, *mutex2;
int iterations, msleepDuration;
int iterations;
std::chrono::milliseconds msleepDuration;
bool use2mutexes;
public:
bool done;
@ -246,8 +249,8 @@ public:
NativeMutexLock(mutex1);
if (use2mutexes)
NativeMutexLock(mutex2);
if (msleepDuration >= 0)
msleep(msleepDuration);
if (msleepDuration >= 0ms)
sleep(msleepDuration);
if (use2mutexes)
NativeMutexUnlock(mutex2);
NativeMutexUnlock(mutex1);
@ -298,7 +301,8 @@ void tst_QMutex::contendedNative()
class QMutexThread : public QThread
{
QMutex *mutex1, *mutex2;
int iterations, msleepDuration;
int iterations;
std::chrono::milliseconds msleepDuration;
bool use2mutexes;
public:
bool done;
@ -316,8 +320,8 @@ public:
mutex1->lock();
if (use2mutexes)
mutex2->lock();
if (msleepDuration >= 0)
msleep(msleepDuration);
if (msleepDuration >= 0ms)
sleep(msleepDuration);
if (use2mutexes)
mutex2->unlock();
mutex1->unlock();
@ -363,7 +367,8 @@ void tst_QMutex::contendedQMutex()
class QMutexLockerThread : public QThread
{
QMutex *mutex1, *mutex2;
int iterations, msleepDuration;
int iterations;
std::chrono::milliseconds msleepDuration;
bool use2mutexes;
public:
bool done;
@ -381,8 +386,8 @@ public:
{
QMutexLocker locker1(mutex1);
QMutexLocker locker2(use2mutexes ? mutex2 : 0);
if (msleepDuration >= 0)
msleep(msleepDuration);
if (msleepDuration >= 0ms)
sleep(msleepDuration);
}
QThread::yieldCurrentThread();