QSemaphore: add <chrono> overload of tryAcquire()

... and C++20 std::counting_semaphore API compatibility.

[ChangeLog][QtCore][QSemaphore] tryAcquire() now optionally takes a
<chrono> duration as timeout, not just int milliseconds.

[ChangeLog][QtCore][QSemaphore] Added try_acquire{,_for,_until}() for
C++20 std::counting_semaphore compatibility.

Change-Id: I34b6b4bf57a54745d4b97349903d090c4995338a
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2021-06-30 07:17:47 +02:00
parent 6f27255cd4
commit 38448b19a1
3 changed files with 91 additions and 1 deletions

View File

@ -485,6 +485,46 @@ bool QSemaphore::tryAcquire(int n, int timeout)
return true;
}
/*!
\fn template <typename Rep, typename Period> QSemaphore::tryAcquire(int n, std::chrono::duration<Rep, Period> timeout)
\overload
\since 6.3
*/
/*!
\fn QSemaphore::try_acquire()
\since 6.3
This function is provided for \c{std::counting_semaphore} compatibility.
It is equivalent to calling \c{tryAcquire(1)}.
\sa tryAcquire(), try_acquire_for(), try_acquire_until()
*/
/*!
\fn template <typename Rep, typename Period> QSemaphore::try_acquire_for(std::chrono::duration<Rep, Period> timeout)
\since 6.3
This function is provided for \c{std::counting_semaphore} compatibility.
It is equivalent to calling \c{tryAcquire(1, timeout)}.
\sa tryAcquire(), try_acquire(), try_acquire_until()
*/
/*!
\fn template <typename Clock, typename Duration> QSemaphore::try_acquire_until(std::chrono::time_point<Clock, Duration> timeout)
\since 6.3
This function is provided for \c{std::counting_semaphore} compatibility.
It is equivalent to calling \c{tryAcquire(1, timeout - Clock::now())},
which means that adjustments to \c{Clock} are ignored while waiting.
\sa tryAcquire(), try_acquire(), try_acquire_for()
*/
/*!
\class QSemaphoreReleaser
\brief The QSemaphoreReleaser class provides exception-safe deferral of a QSemaphore::release() call.

View File

@ -41,6 +41,9 @@
#define QSEMAPHORE_H
#include <QtCore/qglobal.h>
#include <QtCore/qmutex.h> // for convertToMilliseconds()
#include <chrono>
QT_REQUIRE_CONFIG(thread);
@ -57,11 +60,24 @@ public:
void acquire(int n = 1);
bool tryAcquire(int n = 1);
bool tryAcquire(int n, int timeout);
template <typename Rep, typename Period>
bool tryAcquire(int n, std::chrono::duration<Rep, Period> timeout)
{ return tryAcquire(n, QtPrivate::convertToMilliseconds(timeout)); }
void release(int n = 1);
int available() const;
// std::counting_semaphore compatibility:
bool try_acquire() noexcept { return tryAcquire(); }
template <typename Rep, typename Period>
bool try_acquire_for(const std::chrono::duration<Rep, Period> &timeout)
{ return tryAcquire(1, timeout); }
template <typename Clock, typename Duration>
bool try_acquire_until(const std::chrono::time_point<Clock, Duration> &tp)
{
return try_acquire_for(tp - Clock::now());
}
private:
Q_DISABLE_COPY(QSemaphore)

View File

@ -32,6 +32,10 @@
#include <qthread.h>
#include <qsemaphore.h>
#include <chrono>
using namespace std::chrono_literals;
class tst_QSemaphore : public QObject
{
Q_OBJECT
@ -47,6 +51,7 @@ private slots:
void tryAcquireWithTimeoutForever();
void producerConsumer();
void raii();
void stdCompat();
};
static QSemaphore *semaphore = nullptr;
@ -500,7 +505,7 @@ public:
void run() override;
};
static const int Timeout = 60 * 1000; // 1min
static const auto Timeout = 1min;
void Producer::run()
{
@ -599,5 +604,34 @@ void tst_QSemaphore::raii()
QCOMPARE(sem.available(), 49);
}
void tst_QSemaphore::stdCompat()
{
QSemaphore sem(1);
auto now = [] { return std::chrono::steady_clock::now(); };
QVERIFY(sem.try_acquire());
QCOMPARE(sem.available(), 0);
QVERIFY(!sem.try_acquire_for(10ms));
QCOMPARE(sem.available(), 0);
QVERIFY(!sem.try_acquire_until(now() + 10ms));
QCOMPARE(sem.available(), 0);
sem.release(2);
QVERIFY(sem.try_acquire());
QVERIFY(sem.try_acquire_for(5ms));
QCOMPARE(sem.available(), 0);
QVERIFY(!sem.try_acquire_until(now() + 5ms));
QCOMPARE(sem.available(), 0);
sem.release(3);
QVERIFY(sem.try_acquire());
QVERIFY(sem.try_acquire_for(5s));
QVERIFY(sem.try_acquire_until(now() + 5s));
QCOMPARE(sem.available(), 0);
}
QTEST_MAIN(tst_QSemaphore)
#include "tst_qsemaphore.moc"