QLockFile: tryLock(): use chrono first
I.e. tryLock(chrono::milliseconds) shouldn't call the int overload as that truncates the timeout (milliseconds is typically int64_t). Add a note to the tryLock(millisecons) docs that passing milliseconds::max() will make it wait forever to obtain the lock. Task-number: QTBUG-110059 Change-Id: Ib48d9b1b117ce816348625331543d6ba8a788973 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
425e635ecd
commit
5cea5fc80b
@ -216,7 +216,7 @@ bool QLockFile::isLocked() const
|
||||
*/
|
||||
bool QLockFile::lock()
|
||||
{
|
||||
return tryLock(-1);
|
||||
return tryLock(std::chrono::milliseconds::max());
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -241,10 +241,42 @@ bool QLockFile::lock()
|
||||
*/
|
||||
bool QLockFile::tryLock(int timeout)
|
||||
{
|
||||
return tryLock(std::chrono::milliseconds{ timeout });
|
||||
}
|
||||
|
||||
/*! \fn bool QLockFile::tryLock(std::chrono::milliseconds timeout)
|
||||
\overload
|
||||
\since 6.2
|
||||
|
||||
Attempts to create the lock file. This function returns \c true if the
|
||||
lock was obtained; otherwise it returns \c false. If another process (or
|
||||
another thread) has created the lock file already, this function will
|
||||
wait for at most \a timeout for the lock file to become available.
|
||||
|
||||
If the lock was obtained, it must be released with unlock()
|
||||
before another process (or thread) can successfully lock it.
|
||||
|
||||
Calling this function multiple times on the same lock from the same
|
||||
thread without unlocking first is not allowed, this function will
|
||||
\e always return false when attempting to lock the file recursively.
|
||||
|
||||
\sa lock(), unlock()
|
||||
*/
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
|
||||
bool QLockFile::tryLock(std::chrono::milliseconds timeout)
|
||||
#else
|
||||
bool QLockFile::tryLock_impl(std::chrono::milliseconds timeout)
|
||||
#endif
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
using Msec = std::chrono::milliseconds;
|
||||
|
||||
Q_D(QLockFile);
|
||||
QDeadlineTimer timer(qMax(timeout, -1)); // QDT only takes -1 as "forever"
|
||||
int sleepTime = 100;
|
||||
forever {
|
||||
|
||||
QDeadlineTimer timer(timeout < 0ms ? Msec::max() : timeout);
|
||||
|
||||
Msec sleepTime = 100ms;
|
||||
while (true) {
|
||||
d->lockError = d->tryLock_sys();
|
||||
switch (d->lockError) {
|
||||
case NoError:
|
||||
@ -268,39 +300,21 @@ bool QLockFile::tryLock(int timeout)
|
||||
break;
|
||||
}
|
||||
|
||||
int remainingTime = timer.remainingTime();
|
||||
if (remainingTime == 0)
|
||||
auto remainingTime = std::chrono::duration_cast<Msec>(timer.remainingTimeAsDuration());
|
||||
if (remainingTime == 0ms)
|
||||
return false;
|
||||
else if (uint(sleepTime) > uint(remainingTime))
|
||||
|
||||
if (sleepTime > remainingTime)
|
||||
sleepTime = remainingTime;
|
||||
|
||||
QThread::msleep(sleepTime);
|
||||
if (sleepTime < 5 * 1000)
|
||||
QThread::sleep(sleepTime);
|
||||
if (sleepTime < 5s)
|
||||
sleepTime *= 2;
|
||||
}
|
||||
// not reached
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! \fn bool QLockFile::tryLock(std::chrono::milliseconds timeout)
|
||||
\overload
|
||||
\since 6.2
|
||||
|
||||
Attempts to create the lock file. This function returns \c true if the
|
||||
lock was obtained; otherwise it returns \c false. If another process (or
|
||||
another thread) has created the lock file already, this function will
|
||||
wait for at most \a timeout for the lock file to become available.
|
||||
|
||||
If the lock was obtained, it must be released with unlock()
|
||||
before another process (or thread) can successfully lock it.
|
||||
|
||||
Calling this function multiple times on the same lock from the same
|
||||
thread without unlocking first is not allowed, this function will
|
||||
\e always return false when attempting to lock the file recursively.
|
||||
|
||||
\sa lock(), unlock()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QLockFile::unlock()
|
||||
Releases the lock, by deleting the lock file.
|
||||
|
@ -22,13 +22,20 @@ public:
|
||||
QString fileName() const;
|
||||
|
||||
bool lock();
|
||||
bool tryLock(int timeout = 0);
|
||||
bool tryLock(int timeout);
|
||||
void unlock();
|
||||
|
||||
void setStaleLockTime(int);
|
||||
int staleLockTime() const;
|
||||
|
||||
bool tryLock(std::chrono::milliseconds timeout) { return tryLock(int(timeout.count())); }
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
|
||||
bool tryLock(std::chrono::milliseconds timeout = std::chrono::milliseconds::zero());
|
||||
#else
|
||||
bool tryLock(std::chrono::milliseconds timeout = std::chrono::milliseconds::zero())
|
||||
{
|
||||
return tryLock_impl(timeout);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setStaleLockTime(std::chrono::milliseconds value) { setStaleLockTime(int(value.count())); }
|
||||
|
||||
@ -55,6 +62,10 @@ protected:
|
||||
private:
|
||||
Q_DECLARE_PRIVATE(QLockFile)
|
||||
Q_DISABLE_COPY(QLockFile)
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
|
||||
bool tryLock_impl(std::chrono::milliseconds timeout);
|
||||
#endif
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
#include <private/qlockfile_p.h> // for getLockFileHandle()
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class tst_QLockFile : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -96,7 +98,7 @@ void tst_QLockFile::lockUnlock()
|
||||
QVERIFY(lockFile.getLockInfo(&pid, &hostname, &appname));
|
||||
QCOMPARE(pid, QCoreApplication::applicationPid());
|
||||
QCOMPARE(appname, qAppName());
|
||||
QVERIFY(!lockFile.tryLock(200));
|
||||
QVERIFY(!lockFile.tryLock(200ms));
|
||||
QCOMPARE(int(lockFile.error()), int(QLockFile::LockFailedError));
|
||||
|
||||
// Unlock deletes the lock file
|
||||
@ -341,8 +343,8 @@ void tst_QLockFile::staleLongLockFromBusyProcess()
|
||||
QTRY_VERIFY(QFile::exists(fileName));
|
||||
|
||||
QLockFile secondLock(fileName);
|
||||
secondLock.setStaleLockTime(0);
|
||||
QVERIFY(!secondLock.tryLock(100)); // never stale
|
||||
secondLock.setStaleLockTime(0ms);
|
||||
QVERIFY(!secondLock.tryLock(100ms)); // never stale
|
||||
QCOMPARE(int(secondLock.error()), int(QLockFile::LockFailedError));
|
||||
qint64 pid;
|
||||
QTRY_VERIFY(secondLock.getLockInfo(&pid, NULL, NULL));
|
||||
@ -510,8 +512,8 @@ void tst_QLockFile::corruptedLockFile()
|
||||
}
|
||||
|
||||
QLockFile secondLock(fileName);
|
||||
secondLock.setStaleLockTime(100);
|
||||
QVERIFY(secondLock.tryLock(10000));
|
||||
secondLock.setStaleLockTime(100ms);
|
||||
QVERIFY(secondLock.tryLock(10s));
|
||||
QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
|
||||
}
|
||||
|
||||
@ -564,7 +566,7 @@ void tst_QLockFile::hostnameChange()
|
||||
{
|
||||
// we should fail to lock
|
||||
QLockFile lock2(lockFile);
|
||||
QVERIFY(!lock2.tryLock(1000));
|
||||
QVERIFY(!lock2.tryLock(1s));
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,7 +593,7 @@ void tst_QLockFile::differentMachines()
|
||||
{
|
||||
// we should fail to lock
|
||||
QLockFile lock2(lockFile);
|
||||
QVERIFY(!lock2.tryLock(1000));
|
||||
QVERIFY(!lock2.tryLock(1s));
|
||||
}
|
||||
}
|
||||
|
||||
@ -620,7 +622,7 @@ void tst_QLockFile::reboot()
|
||||
f.close();
|
||||
|
||||
// we should succeed in locking
|
||||
QVERIFY(lock1.tryLock(0));
|
||||
QVERIFY(lock1.tryLock(0ms));
|
||||
}
|
||||
|
||||
bool tst_QLockFile::overwritePidInLockFile(const QString &filePath, qint64 pid)
|
||||
|
Loading…
x
Reference in New Issue
Block a user