mirror of
https://github.com/simonbrunel/qtpromise.git
synced 2024-11-22 10:40:08 +08:00
Make QPromise::all accept more container types
Currently, QPromise can't be added dynamically to QVector (::push_* | ::append) because it doesn't expose a default constructor. Until deciding if a default constructor should be added (private/public?), let's make the `QPromise::all` method work with any container types that are STL compatible.
This commit is contained in:
parent
d306423159
commit
c34316243e
@ -385,9 +385,11 @@ QPromise<int> compute(const QString& type)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <a name="qpromise-all"></a> `[static] QPromise<T>::all(QVector<QPromise<T>>) -> QPromise<QVector<T>>`
|
### <a name="qpromise-all"></a> `[static] QPromise<T>::all(Sequence<QPromise<T>>) -> QPromise<QVector<T>>`
|
||||||
Returns a `QPromise<QVector<T>>` that fulfills when **all** `promises` of (the same) type `T` have been fulfilled. The `output` value is a vector containing **all** the values of `promises`, in the same order. If any of the given `promises` fail, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved.
|
Returns a `QPromise<QVector<T>>` that fulfills when **all** `promises` of (the same) type `T` have been fulfilled. The `output` value is a vector containing **all** the values of `promises`, in the same order. If any of the given `promises` fail, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved.
|
||||||
|
|
||||||
|
`Sequence` is any STL compatible container (eg. `QVector`, `QList`, `std::vector`, etc.)
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
QVector<QPromise<QByteArray> > promises{
|
QVector<QPromise<QByteArray> > promises{
|
||||||
download(QUrl("http://a...")),
|
download(QUrl("http://a...")),
|
||||||
@ -417,7 +419,7 @@ auto promise = qPromise(QString("foo")); // QPromise<QString>
|
|||||||
|
|
||||||
This method also allows to convert `QFuture<T>` to `QPromise<T>` delayed until the `QFuture` is finished ([read more](#qtconcurrent-convert)).
|
This method also allows to convert `QFuture<T>` to `QPromise<T>` delayed until the `QFuture` is finished ([read more](#qtconcurrent-convert)).
|
||||||
|
|
||||||
### <a name="helpers-qpromiseall"></a> `qPromiseAll(QVector<QPromise<T> promises) -> QPromise<QVector<T>>`
|
### <a name="helpers-qpromiseall"></a> `qPromiseAll(Sequence<QPromise<T> promises) -> QPromise<QVector<T>>`
|
||||||
This method simply calls the appropriated [`QPromise<T>::all`](#qpromise-all) static method based on the given `QVector` type. In some cases, this method is more convenient than the static one since it avoid some extra typing:
|
This method simply calls the appropriated [`QPromise<T>::all`](#qpromise-all) static method based on the given `QVector` type. In some cases, this method is more convenient than the static one since it avoid some extra typing:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
@ -85,7 +85,9 @@ public:
|
|||||||
QPromise(F&& resolver): QPromiseBase<T>(std::forward<F>(resolver)) { }
|
QPromise(F&& resolver): QPromiseBase<T>(std::forward<F>(resolver)) { }
|
||||||
|
|
||||||
public: // STATIC
|
public: // STATIC
|
||||||
inline static QPromise<QVector<T> > all(const QVector<QPromise<T> >& promises);
|
template <template <typename, typename...> class Sequence = QVector, typename ...Args>
|
||||||
|
inline static QPromise<QVector<T> > all(const Sequence<QPromise<T>, Args...>& promises);
|
||||||
|
|
||||||
inline static QPromise<T> resolve(T&& value);
|
inline static QPromise<T> resolve(T&& value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -100,7 +102,9 @@ public:
|
|||||||
QPromise(F&& resolver): QPromiseBase<void>(std::forward<F>(resolver)) { }
|
QPromise(F&& resolver): QPromiseBase<void>(std::forward<F>(resolver)) { }
|
||||||
|
|
||||||
public: // STATIC
|
public: // STATIC
|
||||||
inline static QPromise<void> all(const QVector<QPromise<void> >& promises);
|
template <template <typename, typename...> class Sequence = QVector, typename ...Args>
|
||||||
|
inline static QPromise<void> all(const Sequence<QPromise<void>, Args...>& promises);
|
||||||
|
|
||||||
inline static QPromise<void> resolve();
|
inline static QPromise<void> resolve();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -210,9 +210,10 @@ inline QPromise<T> QPromiseBase<T>::reject(E&& error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline QPromise<QVector<T> > QPromise<T>::all(const QVector<QPromise<T> >& promises)
|
template <template <typename, typename...> class Sequence, typename ...Args>
|
||||||
|
inline QPromise<QVector<T> > QPromise<T>::all(const Sequence<QPromise<T>, Args...>& promises)
|
||||||
{
|
{
|
||||||
const int count = promises.size();
|
const int count = (int)promises.size();
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
return QPromise<QVector<T> >::resolve({});
|
return QPromise<QVector<T> >::resolve({});
|
||||||
}
|
}
|
||||||
@ -224,8 +225,9 @@ inline QPromise<QVector<T> > QPromise<T>::all(const QVector<QPromise<T> >& promi
|
|||||||
QSharedPointer<int> remaining(new int(count));
|
QSharedPointer<int> remaining(new int(count));
|
||||||
QSharedPointer<QVector<T> > results(new QVector<T>(count));
|
QSharedPointer<QVector<T> > results(new QVector<T>(count));
|
||||||
|
|
||||||
for (int i=0; i<count; ++i) {
|
int i = 0;
|
||||||
promises[i].then([=](const T& res) mutable {
|
for (const auto& promise: promises) {
|
||||||
|
promise.then([=](const T& res) mutable {
|
||||||
(*results)[i] = res;
|
(*results)[i] = res;
|
||||||
if (--(*remaining) == 0) {
|
if (--(*remaining) == 0) {
|
||||||
resolve(*results);
|
resolve(*results);
|
||||||
@ -236,6 +238,8 @@ inline QPromise<QVector<T> > QPromise<T>::all(const QVector<QPromise<T> >& promi
|
|||||||
reject(std::current_exception());
|
reject(std::current_exception());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -248,9 +252,10 @@ inline QPromise<T> QPromise<T>::resolve(T&& value)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QPromise<void> QPromise<void>::all(const QVector<QPromise<void> >& promises)
|
template <template <typename, typename...> class Sequence, typename ...Args>
|
||||||
|
inline QPromise<void> QPromise<void>::all(const Sequence<QPromise<void>, Args...>& promises)
|
||||||
{
|
{
|
||||||
const int count = promises.size();
|
const int count = (int)promises.size();
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
return QPromise<void>::resolve();
|
return QPromise<void>::resolve();
|
||||||
}
|
}
|
||||||
@ -259,7 +264,7 @@ inline QPromise<void> QPromise<void>::all(const QVector<QPromise<void> >& promis
|
|||||||
const QPromiseResolve<void>& resolve,
|
const QPromiseResolve<void>& resolve,
|
||||||
const QPromiseReject<void>& reject) {
|
const QPromiseReject<void>& reject) {
|
||||||
|
|
||||||
QSharedPointer<int> remaining(new int(promises.size()));
|
QSharedPointer<int> remaining(new int(count));
|
||||||
|
|
||||||
for (const auto& promise: promises) {
|
for (const auto& promise: promises) {
|
||||||
promise.then([=]() {
|
promise.then([=]() {
|
||||||
|
@ -26,13 +26,14 @@ static inline QPromise<void> qPromise()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, template <typename, typename...> class Sequence = QVector, typename ...Args>
|
||||||
static inline QPromise<QVector<T> > qPromiseAll(const QVector<QPromise<T> >& promises)
|
static inline QPromise<QVector<T> > qPromiseAll(const Sequence<QPromise<T>, Args...>& promises)
|
||||||
{
|
{
|
||||||
return QPromise<T>::all(promises);
|
return QPromise<T>::all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QPromise<void> qPromiseAll(const QVector<QPromise<void> >& promises)
|
template <template <typename, typename...> class Sequence = QVector, typename ...Args>
|
||||||
|
static inline QPromise<void> qPromiseAll(const Sequence<QPromise<void>, Args...>& promises)
|
||||||
{
|
{
|
||||||
return QPromise<void>::all(promises);
|
return QPromise<void>::all(promises);
|
||||||
}
|
}
|
||||||
|
4
tests/auto/qtpromise/qpromise/all/all.pro
Normal file
4
tests/auto/qtpromise/qpromise/all/all.pro
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
TARGET = tst_qpromise_all
|
||||||
|
SOURCES += $$PWD/tst_all.cpp
|
||||||
|
|
||||||
|
include(../../qtpromise.pri)
|
103
tests/auto/qtpromise/qpromise/all/tst_all.cpp
Normal file
103
tests/auto/qtpromise/qpromise/all/tst_all.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// Tests
|
||||||
|
#include "../../shared/utils.h"
|
||||||
|
|
||||||
|
// QtPromise
|
||||||
|
#include <QtPromise>
|
||||||
|
|
||||||
|
// Qt
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace QtPromise;
|
||||||
|
|
||||||
|
class tst_qpromise_all : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void qList();
|
||||||
|
//void qVector();
|
||||||
|
void stdList();
|
||||||
|
void stdVector();
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_qpromise_all)
|
||||||
|
#include "tst_all.moc"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <class Sequence>
|
||||||
|
struct SequenceTester
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename, typename...> class Sequence, typename ...Args>
|
||||||
|
struct SequenceTester<Sequence<QPromise<int>, Args...> >
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
Sequence<QPromise<int>, Args...> promises{
|
||||||
|
QPromise<int>::resolve(42),
|
||||||
|
QPromise<int>::resolve(43),
|
||||||
|
QPromise<int>::resolve(44)
|
||||||
|
};
|
||||||
|
|
||||||
|
promises.push_back(QPromise<int>::resolve(45));
|
||||||
|
promises.insert(++promises.begin(), QPromise<int>::resolve(46));
|
||||||
|
promises.pop_back();
|
||||||
|
|
||||||
|
auto p = QPromise<int>::all(promises);
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QVector<int> > >::value));
|
||||||
|
QCOMPARE(waitForValue(p, QVector<int>()), QVector<int>({42, 46, 43, 44}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename, typename...> class Sequence, typename ...Args>
|
||||||
|
struct SequenceTester<Sequence<QPromise<void>, Args...> >
|
||||||
|
{
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
Sequence<QPromise<void>, Args...> promises{
|
||||||
|
QPromise<void>::resolve(),
|
||||||
|
QPromise<void>::resolve(),
|
||||||
|
QPromise<void>::resolve()
|
||||||
|
};
|
||||||
|
|
||||||
|
promises.push_back(QPromise<void>::resolve());
|
||||||
|
promises.insert(++promises.begin(), QPromise<void>::resolve());
|
||||||
|
promises.pop_back();
|
||||||
|
|
||||||
|
auto p = QPromise<void>::all(promises);
|
||||||
|
|
||||||
|
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<void> >::value));
|
||||||
|
QCOMPARE(waitForValue(p, -1, 42), 42);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void tst_qpromise_all::qList()
|
||||||
|
{
|
||||||
|
SequenceTester<QList<QPromise<int> > >::exec();
|
||||||
|
SequenceTester<QList<QPromise<void> > >::exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
// QVector::push_back/append isn't supported since it requires a default
|
||||||
|
// constructor (see https://github.com/simonbrunel/qtpromise/issues/3)
|
||||||
|
//void tst_qpromise_all::qVector()
|
||||||
|
//{
|
||||||
|
// SequenceTester<QVector<QPromise<int> > >::exec();
|
||||||
|
// SequenceTester<QVector<QPromise<void> > >::exec();
|
||||||
|
//}
|
||||||
|
|
||||||
|
void tst_qpromise_all::stdList()
|
||||||
|
{
|
||||||
|
SequenceTester<std::list<QPromise<int> > >::exec();
|
||||||
|
SequenceTester<std::list<QPromise<void> > >::exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_qpromise_all::stdVector()
|
||||||
|
{
|
||||||
|
SequenceTester<std::vector<QPromise<int> > >::exec();
|
||||||
|
SequenceTester<std::vector<QPromise<void> > >::exec();
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
|
all \
|
||||||
construct \
|
construct \
|
||||||
delay \
|
delay \
|
||||||
fail \
|
fail \
|
||||||
|
Loading…
Reference in New Issue
Block a user