std::chrono overloads for .timeout() and .delay() (#30)

Add convenience overloads accepting durations from the C++ Standard Library.
This commit is contained in:
Dmitriy Purgin 2020-02-11 22:07:05 +01:00 committed by GitHub
parent 78417b5813
commit 1ad99391a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 209 additions and 1 deletions

View File

@ -20,3 +20,31 @@ auto output = input.delay(2000).then([](int res) {
// called 2 seconds after `input` is fulfilled // called 2 seconds after `input` is fulfilled
}); });
``` ```
---
*Since: 0.6.0*
```cpp
QPromise<T>::delay(std::chrono::milliseconds msec) -> QPromise<T>
```
This is a convenience overload accepting [durations from the C++ Standard Library](https://en.cppreference.com/w/cpp/chrono/duration).
```cpp
QPromise<int> input = {...}
auto output = input.delay(std::chrono::seconds{2}).then([](int res) {
// called 2 seconds after `input` is fulfilled
});
```
C++14 alternative:
```cpp
using namespace std::chrono_literals;
QPromise<int> input = {...}
auto output = input.delay(2s).then([](int res) {
// called 2 seconds after `input` is fulfilled
});
```

View File

@ -25,3 +25,39 @@ auto output = input.timeout(2000)
// operation timed out! // operation timed out!
}); });
``` ```
---
*Since: 0.6.0*
```cpp
QPromise<T>::timeout(std::chrono::milliseconds msec, any error = QPromiseTimeoutException) -> QPromise<T>
```
This is a convenience overload accepting [durations from the C++ Standard Library](https://en.cppreference.com/w/cpp/chrono/duration).
```cpp
QPromise<int> input = {...}
auto output = input.timeout(std::chrono::seconds{2})
.then([](int res) {
// operation succeeded within 2 seconds
})
.fail([](const QPromiseTimeoutException& error) {
// operation timed out!
});
```
C++14 alternative:
```cpp
using namespace std::chrono_literals;
QPromise<int> input = {...}
auto output = input.timeout(2s)
.then([](int res) {
// operation succeeded within 2 seconds
})
.fail([](const QPromiseTimeoutException& error) {
// operation timed out!
});
```

View File

@ -16,6 +16,9 @@
// Qt // Qt
#include <QExplicitlySharedDataPointer> #include <QExplicitlySharedDataPointer>
// C++ Standard Library
#include <chrono>
namespace QtPromise { namespace QtPromise {
template <typename T> template <typename T>
@ -73,7 +76,12 @@ public:
template <typename E = QPromiseTimeoutException> template <typename E = QPromiseTimeoutException>
inline QPromise<T> timeout(int msec, E&& error = E()) const; inline QPromise<T> timeout(int msec, E&& error = E()) const;
template <typename E = QPromiseTimeoutException>
inline QPromise<T> timeout(std::chrono::milliseconds msec, E&& error = E()) const;
inline QPromise<T> delay(int msec) const; inline QPromise<T> delay(int msec) const;
inline QPromise<T> delay(std::chrono::milliseconds msec) const;
inline QPromise<T> wait() const; inline QPromise<T> wait() const;
public: // STATIC public: // STATIC

View File

@ -131,6 +131,13 @@ inline QPromise<T> QPromiseBase<T>::timeout(int msec, E&& error) const
}); });
} }
template <typename T>
template <typename E>
inline QPromise<T> QPromiseBase<T>::timeout(std::chrono::milliseconds msec, E&& error) const
{
return timeout(static_cast<int>(msec.count()), std::forward<E>(error));
}
template <typename T> template <typename T>
inline QPromise<T> QPromiseBase<T>::delay(int msec) const inline QPromise<T> QPromiseBase<T>::delay(int msec) const
{ {
@ -141,6 +148,12 @@ inline QPromise<T> QPromiseBase<T>::delay(int msec) const
}); });
} }
template<typename T>
inline QPromise<T> QPromiseBase<T>::delay(std::chrono::milliseconds msec) const
{
return delay(static_cast<int>(msec.count()));
}
template <typename T> template <typename T>
inline QPromise<T> QPromiseBase<T>::wait() const inline QPromise<T> QPromiseBase<T>::wait() const
{ {

View File

@ -13,6 +13,9 @@
// Qt // Qt
#include <QtTest> #include <QtTest>
// C++ Standard Library
#include <chrono>
using namespace QtPromise; using namespace QtPromise;
class tst_qpromise_delay : public QObject class tst_qpromise_delay : public QObject
@ -22,6 +25,9 @@ class tst_qpromise_delay : public QObject
private Q_SLOTS: private Q_SLOTS:
void fulfilled(); void fulfilled();
void rejected(); void rejected();
void fulfilledStdChrono();
void rejectedStdChrono();
}; };
QTEST_MAIN(tst_qpromise_delay) QTEST_MAIN(tst_qpromise_delay)
@ -63,3 +69,40 @@ void tst_qpromise_delay::rejected()
QCOMPARE(p.isRejected(), true); QCOMPARE(p.isRejected(), true);
QVERIFY(elapsed <= 10); QVERIFY(elapsed <= 10);
} }
void tst_qpromise_delay::fulfilledStdChrono()
{
QElapsedTimer timer;
qint64 elapsed = -1;
timer.start();
auto p = QPromise<int>::resolve(42).delay(std::chrono::seconds{1}).finally([&]() {
elapsed = timer.elapsed();
});
QCOMPARE(waitForValue(p, -1), 42);
QCOMPARE(p.isFulfilled(), true);
// Qt::CoarseTimer (default) Coarse timers try to
// keep accuracy within 5% of the desired interval.
// Require accuracy within 6% for passing the test.
QVERIFY(elapsed >= static_cast<qint64>(1000 * 0.94));
QVERIFY(elapsed <= static_cast<qint64>(1000 * 1.06));
}
void tst_qpromise_delay::rejectedStdChrono()
{
QElapsedTimer timer;
qint64 elapsed = -1;
timer.start();
auto p = QPromise<int>::reject(QString("foo")).delay(std::chrono::seconds{1}).finally([&]() {
elapsed = timer.elapsed();
});
QCOMPARE(waitForError(p, QString()), QString("foo"));
QCOMPARE(p.isRejected(), true);
QVERIFY(elapsed <= 10);
}

View File

@ -13,6 +13,9 @@
// Qt // Qt
#include <QtTest> #include <QtTest>
// C++ Standard Library
#include <chrono>
using namespace QtPromise; using namespace QtPromise;
class tst_qpromise_timeout : public QObject class tst_qpromise_timeout : public QObject
@ -23,6 +26,10 @@ private Q_SLOTS:
void fulfilled(); void fulfilled();
void rejected(); void rejected();
void timeout(); void timeout();
void fulfilledStdChrono();
void rejectedStdChrono();
void timeoutStdChrono();
}; };
QTEST_MAIN(tst_qpromise_timeout) QTEST_MAIN(tst_qpromise_timeout)
@ -100,3 +107,76 @@ void tst_qpromise_timeout::timeout()
QVERIFY(elapsed >= static_cast<qint64>(2000 * 0.94)); QVERIFY(elapsed >= static_cast<qint64>(2000 * 0.94));
QVERIFY(elapsed <= static_cast<qint64>(2000 * 1.06)); QVERIFY(elapsed <= static_cast<qint64>(2000 * 1.06));
} }
void tst_qpromise_timeout::fulfilledStdChrono()
{
QElapsedTimer timer;
qint64 elapsed = -1;
timer.start();
auto p = QPromise<int>([](const QPromiseResolve<int>& resolve) {
QTimer::singleShot(1000, [=]() {
resolve(42);
});
}).timeout(std::chrono::seconds{2}).finally([&]() {
elapsed = timer.elapsed();
});
QCOMPARE(waitForValue(p, -1), 42);
QCOMPARE(p.isFulfilled(), true);
QVERIFY(elapsed < 2000);
}
void tst_qpromise_timeout::rejectedStdChrono()
{
QElapsedTimer timer;
qint64 elapsed = -1;
timer.start();
auto p = QPromise<int>([](const QPromiseResolve<int>&, const QPromiseReject<int>& reject) {
QTimer::singleShot(1000, [=]() {
reject(QString("foo"));
});
}).timeout(std::chrono::seconds{2}).finally([&]() {
elapsed = timer.elapsed();
});
QCOMPARE(waitForError(p, QString()), QString("foo"));
QCOMPARE(p.isRejected(), true);
QVERIFY(elapsed < 2000);
}
void tst_qpromise_timeout::timeoutStdChrono()
{
QElapsedTimer timer;
qint64 elapsed = -1;
bool failed = false;
timer.start();
auto p = QPromise<int>([](const QPromiseResolve<int>& resolve) {
QTimer::singleShot(4000, [=]() {
resolve(42);
});
}).timeout(std::chrono::seconds{2}).finally([&]() {
elapsed = timer.elapsed();
});
p.fail([&](const QPromiseTimeoutException&) {
failed = true;
return -1;
}).wait();
QCOMPARE(waitForValue(p, -1), -1);
QCOMPARE(p.isRejected(), true);
QCOMPARE(failed, true);
// Qt::CoarseTimer (default) Coarse timers try to
// keep accuracy within 5% of the desired interval.
// Require accuracy within 6% for passing the test.
QVERIFY(elapsed >= static_cast<qint64>(2000 * 0.94));
QVERIFY(elapsed <= static_cast<qint64>(2000 * 1.06));
}