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()
|
bool QLockFile::lock()
|
||||||
{
|
{
|
||||||
return tryLock(-1);
|
return tryLock(std::chrono::milliseconds::max());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -241,10 +241,42 @@ bool QLockFile::lock()
|
|||||||
*/
|
*/
|
||||||
bool QLockFile::tryLock(int timeout)
|
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);
|
Q_D(QLockFile);
|
||||||
QDeadlineTimer timer(qMax(timeout, -1)); // QDT only takes -1 as "forever"
|
|
||||||
int sleepTime = 100;
|
QDeadlineTimer timer(timeout < 0ms ? Msec::max() : timeout);
|
||||||
forever {
|
|
||||||
|
Msec sleepTime = 100ms;
|
||||||
|
while (true) {
|
||||||
d->lockError = d->tryLock_sys();
|
d->lockError = d->tryLock_sys();
|
||||||
switch (d->lockError) {
|
switch (d->lockError) {
|
||||||
case NoError:
|
case NoError:
|
||||||
@ -268,39 +300,21 @@ bool QLockFile::tryLock(int timeout)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int remainingTime = timer.remainingTime();
|
auto remainingTime = std::chrono::duration_cast<Msec>(timer.remainingTimeAsDuration());
|
||||||
if (remainingTime == 0)
|
if (remainingTime == 0ms)
|
||||||
return false;
|
return false;
|
||||||
else if (uint(sleepTime) > uint(remainingTime))
|
|
||||||
|
if (sleepTime > remainingTime)
|
||||||
sleepTime = remainingTime;
|
sleepTime = remainingTime;
|
||||||
|
|
||||||
QThread::msleep(sleepTime);
|
QThread::sleep(sleepTime);
|
||||||
if (sleepTime < 5 * 1000)
|
if (sleepTime < 5s)
|
||||||
sleepTime *= 2;
|
sleepTime *= 2;
|
||||||
}
|
}
|
||||||
// not reached
|
// not reached
|
||||||
return false;
|
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()
|
\fn void QLockFile::unlock()
|
||||||
Releases the lock, by deleting the lock file.
|
Releases the lock, by deleting the lock file.
|
||||||
|
@ -22,13 +22,20 @@ public:
|
|||||||
QString fileName() const;
|
QString fileName() const;
|
||||||
|
|
||||||
bool lock();
|
bool lock();
|
||||||
bool tryLock(int timeout = 0);
|
bool tryLock(int timeout);
|
||||||
void unlock();
|
void unlock();
|
||||||
|
|
||||||
void setStaleLockTime(int);
|
void setStaleLockTime(int);
|
||||||
int staleLockTime() const;
|
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())); }
|
void setStaleLockTime(std::chrono::milliseconds value) { setStaleLockTime(int(value.count())); }
|
||||||
|
|
||||||
@ -55,6 +62,10 @@ protected:
|
|||||||
private:
|
private:
|
||||||
Q_DECLARE_PRIVATE(QLockFile)
|
Q_DECLARE_PRIVATE(QLockFile)
|
||||||
Q_DISABLE_COPY(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
|
QT_END_NAMESPACE
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include <private/qlockfile_p.h> // for getLockFileHandle()
|
#include <private/qlockfile_p.h> // for getLockFileHandle()
|
||||||
|
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
class tst_QLockFile : public QObject
|
class tst_QLockFile : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -96,7 +98,7 @@ void tst_QLockFile::lockUnlock()
|
|||||||
QVERIFY(lockFile.getLockInfo(&pid, &hostname, &appname));
|
QVERIFY(lockFile.getLockInfo(&pid, &hostname, &appname));
|
||||||
QCOMPARE(pid, QCoreApplication::applicationPid());
|
QCOMPARE(pid, QCoreApplication::applicationPid());
|
||||||
QCOMPARE(appname, qAppName());
|
QCOMPARE(appname, qAppName());
|
||||||
QVERIFY(!lockFile.tryLock(200));
|
QVERIFY(!lockFile.tryLock(200ms));
|
||||||
QCOMPARE(int(lockFile.error()), int(QLockFile::LockFailedError));
|
QCOMPARE(int(lockFile.error()), int(QLockFile::LockFailedError));
|
||||||
|
|
||||||
// Unlock deletes the lock file
|
// Unlock deletes the lock file
|
||||||
@ -341,8 +343,8 @@ void tst_QLockFile::staleLongLockFromBusyProcess()
|
|||||||
QTRY_VERIFY(QFile::exists(fileName));
|
QTRY_VERIFY(QFile::exists(fileName));
|
||||||
|
|
||||||
QLockFile secondLock(fileName);
|
QLockFile secondLock(fileName);
|
||||||
secondLock.setStaleLockTime(0);
|
secondLock.setStaleLockTime(0ms);
|
||||||
QVERIFY(!secondLock.tryLock(100)); // never stale
|
QVERIFY(!secondLock.tryLock(100ms)); // never stale
|
||||||
QCOMPARE(int(secondLock.error()), int(QLockFile::LockFailedError));
|
QCOMPARE(int(secondLock.error()), int(QLockFile::LockFailedError));
|
||||||
qint64 pid;
|
qint64 pid;
|
||||||
QTRY_VERIFY(secondLock.getLockInfo(&pid, NULL, NULL));
|
QTRY_VERIFY(secondLock.getLockInfo(&pid, NULL, NULL));
|
||||||
@ -510,8 +512,8 @@ void tst_QLockFile::corruptedLockFile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QLockFile secondLock(fileName);
|
QLockFile secondLock(fileName);
|
||||||
secondLock.setStaleLockTime(100);
|
secondLock.setStaleLockTime(100ms);
|
||||||
QVERIFY(secondLock.tryLock(10000));
|
QVERIFY(secondLock.tryLock(10s));
|
||||||
QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
|
QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,7 +566,7 @@ void tst_QLockFile::hostnameChange()
|
|||||||
{
|
{
|
||||||
// we should fail to lock
|
// we should fail to lock
|
||||||
QLockFile lock2(lockFile);
|
QLockFile lock2(lockFile);
|
||||||
QVERIFY(!lock2.tryLock(1000));
|
QVERIFY(!lock2.tryLock(1s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -591,7 +593,7 @@ void tst_QLockFile::differentMachines()
|
|||||||
{
|
{
|
||||||
// we should fail to lock
|
// we should fail to lock
|
||||||
QLockFile lock2(lockFile);
|
QLockFile lock2(lockFile);
|
||||||
QVERIFY(!lock2.tryLock(1000));
|
QVERIFY(!lock2.tryLock(1s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,7 +622,7 @@ void tst_QLockFile::reboot()
|
|||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
// we should succeed in locking
|
// we should succeed in locking
|
||||||
QVERIFY(lock1.tryLock(0));
|
QVERIFY(lock1.tryLock(0ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tst_QLockFile::overwritePidInLockFile(const QString &filePath, qint64 pid)
|
bool tst_QLockFile::overwritePidInLockFile(const QString &filePath, qint64 pid)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user