diff --git a/kdevplatform/3rdparty/CMakeLists.txt b/kdevplatform/3rdparty/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(qtpromise) diff --git a/kdevplatform/3rdparty/qtpromise/CMakeLists.txt b/kdevplatform/3rdparty/qtpromise/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/CMakeLists.txt @@ -0,0 +1,7 @@ +set(QTPROMISE_VERSION 0.5.0) + +add_library(QtPromise INTERFACE) + +target_include_directories(QtPromise INTERFACE + $ +) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/.appveyor.yml b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/.appveyor.yml new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/.appveyor.yml @@ -0,0 +1,27 @@ +image: Visual Studio 2015 + +init: + - cmd: call "C:\Program Files (x86)\Microsoft Visual Studio "%VSVER%".0\VC\vcvarsall.bat" %ARCH% + - cmd: qmake --version + +# https://www.appveyor.com/docs/windows-images-software/#qt +environment: + PATH: '%PATH%;%QTDIR%\bin' + matrix: + - QTDIR: C:\Qt\5.6\msvc2013 + VSVER: 12 + ARCH: x86 + - QTDIR: C:\Qt\5.9\msvc2013_64 + VSVER: 12 + ARCH: x64 + - QTDIR: C:\Qt\latest\msvc2015_64 + VSVER: 14 + ARCH: x64 + +build_script: + - cmd: qmake qtpromise.pro + - cmd: nmake + +test_script: + - cmd: nmake check + diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/.gitignore b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/.gitignore new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/.gitignore @@ -0,0 +1,16 @@ +_book +dist +node_modules +*.gcno +*.gcda +*.moc +*.o +*.obj +*.exe +*.user +Makefile* +moc_*.cpp +moc_*.h +coverage.info +package-lock.json +target_wrapper.bat diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/.travis.yml b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/.travis.yml new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/.travis.yml @@ -0,0 +1,37 @@ +sudo: required +dist: trusty +language: cpp +compiler: gcc + +before_install: + - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + - sudo add-apt-repository -y ppa:beineri/opt-qt563-trusty + - sudo apt-get update -qq + +install: + - sudo apt-get install -qq gcc-4.9 g++-4.9 + - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 90 + - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 90 + - sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-4.9 90 + - sudo apt-get install -qq qt56base + - source /opt/qt56/bin/qt56-env.sh + - wget http://archive.ubuntu.com/ubuntu/pool/universe/l/lcov/lcov_1.13.orig.tar.gz + - tar xf lcov_1.13.orig.tar.gz + - cd lcov-1.13/ + - sudo make install + - cd .. + +before_script: + - qmake --version + - lcov --version && gcov --version + - gcc --version && g++ --version + +script: + - qmake qtpromise.pro CONFIG+=coverage + - make -j4 + - make check --quiet + - lcov -capture --directory . --o coverage.info + - lcov -e coverage.info '**/src/**/*' -o coverage.info + +after_success: + - bash <(curl -s https://codecov.io/bash) -f coverage.info diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/LICENSE b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/LICENSE new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/LICENSE @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright (c) 2019 Simon Brunel + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/README.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/README.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/README.md @@ -0,0 +1,21 @@ +Promises/A+ + +# QtPromise + +[![qpm](https://img.shields.io/github/release/simonbrunel/qtpromise.svg?style=flat-square&label=qpm&colorB=4CAF50)](https://www.qpm.io/packages/com.github.simonbrunel.qtpromise/index.html) [![Travis](https://img.shields.io/travis/simonbrunel/qtpromise/master.svg?style=flat-square)](https://travis-ci.org/simonbrunel/qtpromise) [![coverage](https://img.shields.io/codecov/c/github/simonbrunel/qtpromise.svg?style=flat-square)](https://codecov.io/gh/simonbrunel/qtpromise) + +[Promises/A+](https://promisesaplus.com/) implementation for [Qt/C++](https://www.qt.io/). + +Requires [Qt 5.6](https://www.qt.io/download/) (or later) with [C++11 support enabled](https://wiki.qt.io/How_to_use_C++11_in_your_Qt_Projects). + +## Documentation + +* [Getting Started](https://qtpromise.netlify.com/qtpromise/getting-started.html) +* [Qt Concurrent](https://qtpromise.netlify.com/qtpromise/qtconcurrent.html) +* [Qt Signals](https://qtpromise.netlify.com/qtpromise/qtsignals.html) +* [Thread-Safety](https://qtpromise.netlify.com/qtpromise/thread-safety.html) +* [API Reference](https://qtpromise.netlify.com/qtpromise/api-reference.html) + +## License + +QtPromise is available under the [MIT license](LICENSE). diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/.vuepress/config.js b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/.vuepress/config.js new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/.vuepress/config.js @@ -0,0 +1,70 @@ +module.exports = { + title: 'QtPromise', + description: 'Promises/A+ implementation for Qt/C++', + ga: 'UA-113899811-1', + head: [ + ['link', { rel: 'icon', href: `/favicon.png` }], + ], + themeConfig: { + repo: 'simonbrunel/qtpromise', + lastUpdated: 'Last Updated', + editLinks: true, + docsDir: 'docs', + algolia: { + apiKey: '0e6e9cccb8c2c360a5543e28c4e31cb8', + indexName: 'qtpromise' + }, + sidebar: [ + 'qtpromise/getting-started', + 'qtpromise/qtconcurrent', + 'qtpromise/qtsignals', + 'qtpromise/thread-safety', + 'qtpromise/api-reference', + { + title: 'QPromise', + children: [ + 'qtpromise/qpromise/constructor', + 'qtpromise/qpromise/delay', + 'qtpromise/qpromise/each', + 'qtpromise/qpromise/fail', + 'qtpromise/qpromise/filter', + 'qtpromise/qpromise/finally', + 'qtpromise/qpromise/isfulfilled', + 'qtpromise/qpromise/ispending', + 'qtpromise/qpromise/isrejected', + 'qtpromise/qpromise/map', + 'qtpromise/qpromise/reduce', + 'qtpromise/qpromise/tap', + 'qtpromise/qpromise/tapfail', + 'qtpromise/qpromise/then', + 'qtpromise/qpromise/timeout', + 'qtpromise/qpromise/wait', + 'qtpromise/qpromise/reject.md', + 'qtpromise/qpromise/resolve.md' + ] + }, + { + title: 'Helpers', + children: [ + 'qtpromise/helpers/all', + 'qtpromise/helpers/attempt', + 'qtpromise/helpers/connect', + 'qtpromise/helpers/each', + 'qtpromise/helpers/filter', + 'qtpromise/helpers/map', + 'qtpromise/helpers/reduce', + 'qtpromise/helpers/resolve' + ] + }, + { + title: 'Exceptions', + children: [ + 'qtpromise/exceptions/canceled', + 'qtpromise/exceptions/context', + 'qtpromise/exceptions/timeout', + 'qtpromise/exceptions/undefined' + ] + } + ] + } +} diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/.vuepress/override.styl b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/.vuepress/override.styl new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/.vuepress/override.styl @@ -0,0 +1,2 @@ +$accentColor = #23b223 +$textColor = #404244 diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/.vuepress/public/favicon.ico b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/.vuepress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..50cb9fdf100f945d43c889557ef3548bc3223231 GIT binary patch literal 34494 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 YCgTbjSIf9Y#?Esf{wL$Gz>^IB2d&oyHUIzs literal 0 Hc$@h{aDuzLI|L5|cirIb4uO~NRlTY=Rd?>c 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/A+ + +# QtPromise +[Promises/A+](https://promisesaplus.com/) implementation for [Qt/C++](https://www.qt.io/). + +Requires [Qt 5.6](https://www.qt.io/download/) (or later) with [C++11 support enabled](https://wiki.qt.io/How_to_use_C++11_in_your_Qt_Projects). + +## License +QtPromise is available under the [MIT license](https://github.com/simonbrunel/qtpromise/blob/master/LICENSE). diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/api-reference.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/api-reference.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/api-reference.md @@ -0,0 +1,49 @@ +# API Reference + +## Functions + +* [`QPromise::QPromise`](qpromise/constructor.md) +* [`QPromise::delay`](qpromise/delay.md) +* [`QPromise::each`](qpromise/each.md) +* [`QPromise::fail`](qpromise/fail.md) +* [`QPromise::filter`](qpromise/filter.md) +* [`QPromise::finally`](qpromise/finally.md) +* [`QPromise::isFulfilled`](qpromise/isfulfilled.md) +* [`QPromise::isPending`](qpromise/ispending.md) +* [`QPromise::isRejected`](qpromise/isrejected.md) +* [`QPromise::map`](qpromise/map.md) +* [`QPromise::reduce`](qpromise/reduce.md) +* [`QPromise::tap`](qpromise/tap.md) +* [`QPromise::tapFail`](qpromise/tapfail.md) +* [`QPromise::then`](qpromise/then.md) +* [`QPromise::timeout`](qpromise/timeout.md) +* [`QPromise::wait`](qpromise/wait.md) + +## Static Functions + +* [`[static] QPromise::reject`](qpromise/reject.md) +* [`[static] QPromise::resolve`](qpromise/resolve.md) + +## Helpers + +* [`QtPromise::all`](helpers/all.md) +* [`QtPromise::attempt`](helpers/attempt.md) +* [`QtPromise::connect`](helpers/connect.md) +* [`QtPromise::each`](helpers/each.md) +* [`QtPromise::filter`](helpers/filter.md) +* [`QtPromise::map`](helpers/map.md) +* [`QtPromise::reduce`](helpers/reduce.md) +* [`QtPromise::resolve`](helpers/resolve.md) + +## Exceptions + +* [`QPromiseCanceledException`](exceptions/canceled.md) +* [`QPromiseContextException`](exceptions/context.md) +* [`QPromiseTimeoutException`](exceptions/timeout.md) +* [`QPromiseUndefinedException`](exceptions/undefined.md) + +## Deprecations + +* `[static] QPromise::all`: use [`QtPromise::all`](helpers/all.md) instead (since 0.5.0) +* `QtPromise::qPromise`: use [`QtPromise::resolve`](helpers/resolve.md) instead (since 0.5.0) +* `QtPromise::qPromiseAll`: use [`QtPromise::all`](helpers/all.md) instead (since 0.5.0) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/canceled.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/canceled.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/canceled.md @@ -0,0 +1,20 @@ +--- +title: QPromiseCanceledException +--- + +# QPromiseCanceledException + +*Since: 0.1.0* + +This exception is thrown for promise created from a [`QFuture`](../qtconcurrent.md) which has been canceled (e.g. using [`QFuture::cancel()`](http://doc.qt.io/qt-5/qfuture.html#cancel)), for example: + +```cpp +auto output = QtPromise::resolve(future) + .fail([](const QPromiseCanceledException&) { + // `future` has been canceled! + }); +``` + +::: tip NOTE +QtPromise doesn't support promise cancelation (yet?) +::: diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/context.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/context.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/context.md @@ -0,0 +1,17 @@ +--- +title: QPromiseContextException +--- + +# QPromiseContextException + +*Since: 0.5.0* + +When a promise is created using [`QtPromise::connect()`](../helpers/connect.md), this exception is thrown when the `sender` object is destroyed, for example: + +```cpp +auto promise = QtPromise::connect(sender, &Object::finished, &Object::error); + +promise.fail([](const QPromiseContextException&) { + // 'sender' has been destroyed. +}) +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/timeout.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/timeout.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/timeout.md @@ -0,0 +1,17 @@ +--- +title: QPromiseTimeoutException +--- + +# QPromiseTimeoutException + +*Since: 0.2.0* + +This is the default exception thrown when reaching the time limit when using the [`QPromise::timeout()`](../qpromise/timeout.md) method, for example: + +```cpp +QPromise input = {...} +auto output = input.timeout(2000) + .fail([](const QPromiseTimeoutException& e) { + // operation timed out after 2s! + }); +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/undefined.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/undefined.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/exceptions/undefined.md @@ -0,0 +1,25 @@ +--- +title: QPromiseUndefinedException +--- + +# QPromiseUndefinedException + +*Since: 0.5.0* + +This exception is thrown when rejecting a promise with no explicit reason, for example: + +```cpp +QPromise promise([](const QPromiseResolve& resolve, const QPromiseReject& reject) { + async_method([=](bool success, int result) { + if (success) { + resolve(result); + } else { + reject(); + } + }); +}); + +promise.fail([](const QPromiseUndefinedException&) { + // promise rejected without reason! +}) +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/getting-started.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/getting-started.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/getting-started.md @@ -0,0 +1,95 @@ +# Getting Started + +## Installation + +QtPromise is a [header-only](https://en.wikipedia.org/wiki/Header-only) library, simply download the [latest release](https://github.com/simonbrunel/qtpromise/releases/latest) (or [`git submodule`](https://git-scm.com/docs/git-submodule)) and include `qtpromise.pri` from your project `.pro`. + +### qpm + +Alternatively and **only** if your project relies on [qpm](https://www.qpm.io/), you can install QtPromise as follow: + +```bash +qpm install com.github.simonbrunel.qtpromise +``` + +## Usage + +The recommended way to use QtPromise is to include the single module header: + +```cpp +#include +``` + +## Example + +Let's first make the code more readable by using the library namespace: + +```cpp +using namespace QtPromise; +``` + +This `download` function creates a [promise from callbacks](qpromise/constructor.md) which will be resolved when the network request is finished: + +```cpp +QPromise download(const QUrl& url) +{ + return QPromise([&]( + const QPromiseResolve& resolve, + const QPromiseReject& reject) { + + QNetworkReply* reply = manager->get(QNetworkRequest(url)); + QObject::connect(reply, &QNetworkReply::finished, [=]() { + if (reply->error() == QNetworkReply::NoError) { + resolve(reply->readAll()); + } else { + reject(reply->error()); + } + + reply->deleteLater(); + }); + }); +} +``` + +The following method `uncompress` data in a separate thread and returns a [promise from QFuture](qtconcurrent.md): + +```cpp +QPromise uncompress(const QByteArray& data) +{ + return QtPromise::resolve(QtConcurrent::run([](const QByteArray& data) { + Entries entries; + + // {...} uncompress data and parse content. + + if (error) { + throw MalformedException(); + } + + return entries; + }, data)); +} +``` + +It's then easy to chain the whole asynchronous process using promises: +- initiate the promise chain by downloading a specific URL, +- [`then`](qpromise/then.md) *and only if download succeeded*, uncompress received data, +- [`then`](qpromise/then.md) validate and process the uncompressed entries, +- [`finally`](qpromise/finally.md) perform operations whatever the process succeeded or failed, +- and handle specific errors using [`fail`](qpromise/fail.md). + +```cpp +download(url).then(&uncompress).then([](const Entries& entries) { + if (entries.isEmpty()) { + throw UpdateException("No entries"); + } + // {...} process entries +}).finally([]() { + // {...} cleanup +}).fail([](QNetworkReply::NetworkError err) { + // {...} handle network error +}).fail([](const UpdateException& err) { + // {...} handle update error +}).fail([]() { + // {...} catch all +}); +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/all.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/all.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/all.md @@ -0,0 +1,33 @@ +--- +title: all +--- + +# QtPromise::all + +*Since: 0.5.0* + +``` +QtPromise::all(Sequence> promises) -> QPromise> +QtPromise::all(Sequence> promises) -> QPromise +``` + +Returns a `QPromise>` (or `QPromise`) 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, i.e., at the respective positions to the original sequence, regardless of completion 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 +QVector > promises{ + download(QUrl("http://a...")), + download(QUrl("http://b...")), + download(QUrl("http://c...")) +}; + +auto output = QtPromise::all(promises); + +// output type: QPromise> +output.then([](const QVector& res) { + // {...} +}); +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/attempt.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/attempt.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/attempt.md @@ -0,0 +1,42 @@ +--- +title: attempt +--- + +# QtPromise::attempt + +*Since: 0.4.0* + +```cpp +QtPromise::attempt(Functor functor, Args...) -> QPromise + +// With: +// - Functor: Function(Args...) -> R | QPromise +``` + +Calls `functor` immediately and returns a promise fulfilled with the value returned by `functor`. Any synchronous exceptions will be turned into rejections on the returned promise. This is a convenient method that can be used instead of handling both synchronous and asynchronous exception flows. + +The type `R` of the `output` promise depends on the type returned by the `functor` function. If `functor` returns a promise (or `QFuture`), the `output` promise is delayed and will be resolved by the returned promise. + +```cpp +QPromise download(const QUrl& url); + +QPromise process(const QUrl& url) +{ + return QtPromise::attempt([&]() { + if (!url.isValid()) { + throw InvalidUrlException(); + } + + return download(url); + } +} + +auto output = process(url); + +// 'output' type: QPromise +output.then([](const QByteArray& res) { + // {...} +}).fail([](const InvalidUrlException& err) { + // {...} +}); +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/connect.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/connect.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/connect.md @@ -0,0 +1,48 @@ +--- +title: connect +--- + +# QtPromise::connect + +*Since: 0.5.0* + +```cpp +(1) QtPromise::connect(QObject* sender, Signal(T) resolver) -> QPromise +(2) QtPromise::connect(QObject* sender, Signal(T) resolver, Signal(R) rejecter) -> QPromise +(3) QtPromise::connect(QObject* sender, Signal(T) resolver, QObject* sender2, Signal(R) rejecter) -> QPromise +``` + +Creates a `QPromise` that will be fulfilled with the `resolver` signal's first argument, or a `QPromise` if `resolver` doesn't provide any argument. + +The second `(2)` and third `(3)` variants of this method will reject the `output` promise when the `rejecter` signal is emitted. The rejection reason is the value of the `rejecter` signal's first argument or [`QPromiseUndefinedException`](../exceptions/undefined) if `rejected` doesn't provide any argument. + +Additionally, the `output` promise will be automatically rejected with [`QPromiseContextException`](../exceptions/context.md) if `sender` is destroyed before the promise is resolved (that doesn't apply to `sender2`). + +```cpp +class Sender : public QObject +{ +Q_SIGNALS: + void finished(const QByteArray&); + void error(ErrorCode); +}; + +auto sender = new Sender(); +auto output = QtPromise::connect(sender, &Sender::finished, &Sender::error); + +// 'output' resolves as soon as one of the following events happens: +// - the 'sender' object is destroyed, the promise is rejected +// - the 'finished' signal is emitted, the promise is fulfilled +// - the 'error' signal is emitted, the promise is rejected + +// 'output' type: QPromise +output.then([](const QByteArray& res) { + // 'res' is the first argument of the 'finished' signal. +}).fail([](ErrorCode err) { + // 'err' is the first argument of the 'error' signal. +}).fail([](const QPromiseContextException& err) { + // the 'sender' object has been destroyed before any of + // the 'finished' or 'error' signals have been emitted. +}); +``` + +See also the [`Qt Signals`](../qtsignals.md) section for more examples. diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/each.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/each.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/each.md @@ -0,0 +1,41 @@ +--- +title: each +--- + +# QtPromise::each + +*Since: 0.4.0* + +```cpp +QtPromise::each(Sequence values, Functor functor) -> QPromise> + +// With: +// - Sequence: STL compatible container (e.g. QVector, etc.) +// - Functor: Function(T value, int index) -> void | QPromise +``` + +Calls the given `functor` on each element in `values` then resolves to the original sequence unmodified. If `functor` throws, `output` is rejected with the new exception. + +If `functor` returns a promise (or `QFuture`), the `output` promise is delayed until all the promises are resolved. If any of the promises fail, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved. + +```cpp +auto output = QtPromise::each(QVector{ + QUrl("http://a..."), + QUrl("http://b..."), + QUrl("http://c...") +}, [](const QUrl& url, ...) { + return QPromise([&](auto resolve, auto reject) { + // process url asynchronously ... + }) +}); + +// `output` resolves as soon as all promises returned by +// `functor` are fulfilled or at least one is rejected. + +// output type: QPromise> +output.then([](const QVector& res) { + // 'res' contains the original values +}); +``` + +See also: [`QPromise::each`](../qpromise/each.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/filter.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/filter.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/filter.md @@ -0,0 +1,46 @@ +--- +title: filter +--- + +# QtPromise::filter + +*Since: 0.4.0* + +```cpp +QtPromise::filter(Sequence values, Filterer filterer) -> QPromise> + +// With: +// - Sequence: STL compatible container (e.g. QVector, etc.) +// - Filterer: Function(T value, int index) -> bool +``` + +Iterates over `values` and [filters the sequence](https://en.wikipedia.org/wiki/Filter_%28higher-order_function%29) to another using the given `filterer` function. If `filterer` returns `true`, a copy of the item is put in the `output` sequence, otherwise, the item will not appear in `output`. If `filterer` throws, `output` is rejected with the new exception. + +If `filterer` returns a promise (or `QFuture`), the `output` promise is delayed until all the promises are resolved. If any of the promises fail, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved. + +```cpp +auto output = QtPromise::filter(QVector{ + QUrl("http://a..."), + QUrl("http://b..."), + QUrl("http://c...") +}, [](const QUrl& url, ...) { + return QPromise([&](auto resolve, auto reject) { + // resolve(true) if 'url' is reachable, else resolve(false) + // {...} + }); +}); + +// 'output' resolves as soon as all promises returned by +// 'filterer' are fulfilled or at least one is rejected. + +// 'output' type: QPromise> +output.then([](const QVector& res) { + // 'res' contains only reachable URLs +}); +``` + +::: tip NOTE +The order of the output sequence values is guarantee to be the same as the original sequence, regardless of completion order of the promises returned by `filterer`. +::: + +See also: [`QPromise::filter`](../qpromise/filter.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/map.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/map.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/map.md @@ -0,0 +1,46 @@ +--- +title: map +--- + +# QtPromise::map + +*Since: 0.4.0* + +```cpp +QtPromise::map(Sequence values, Mapper mapper) -> QPromise> + +// With: +// - Sequence: STL compatible container (e.g. QVector, etc.) +// - Mapper: Function(T value, int index) -> R | QPromise +``` + +Iterates over `values` and [maps the sequence](https://en.wikipedia.org/wiki/Map_%28higher-order_function%29) to another using the given `mapper` function. The type returned by `mapper` determines the type of the `output` promise. If `mapper` throws, `output` is rejected with the new exception. + +If `mapper` returns a promise (or `QFuture`), the `output` promise is delayed until all the promises are resolved. If any of the promises fails, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved. + +```cpp +auto output = QtPromise::map(QVector{ + QUrl("http://a..."), + QUrl("http://b..."), + QUrl("http://c...") +}, [](const QUrl& url, ...) { + return QPromise([&](auto resolve, auto reject) { + // download content at url and resolve + // {...} + }); +}); + +// 'output' resolves as soon as all promises returned by +// 'mapper' are fulfilled or at least one is rejected. + +// 'output' type: QPromise> +output.then([](const QVector& res) { + // {...} +}); +``` + +::: tip NOTE +The order of the output sequence values is guarantee to be the same as the original sequence, regardless of completion order of the promises returned by `mapper`. +::: + +See also: [`QPromise::map`](../qpromise/map.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/reduce.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/reduce.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/reduce.md @@ -0,0 +1,48 @@ +--- +title: reduce +--- + +# QtPromise::reduce + +*Since: 0.5.0* + +```cpp +QPromise::reduce(Sequence> values, Reducer reducer) -> QPromise +QPromise::reduce(Sequence> values, Reducer reducer, R|QPromise initialValue) -> QPromise + +// With: +// - Sequence: STL compatible container (e.g. QVector, etc.) +// - Reducer: Function(T|R accumulator, T item, int index) -> R|QPromise +``` + +Iterates over `values` and [reduces the sequence to a single value](https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29) using the given `reducer` function and an optional `initialValue`. The type returned by `reducer` determines the type of the `output` promise. If `reducer` throws, `output` is rejected with the new exception. + +If `reducer` returns a promise (or `QFuture`), then the result of the promise is awaited, before continuing with next iteration. If any promise in the `values` sequence is rejected or a promise returned by the `reducer` function is rejected, `output` immediately rejects with the error of the promise that rejected. + +```cpp +// Concatenate the content of the given files, read asynchronously +auto output = QtPromise::reduce(QList{ + "file:f0.txt", // contains "foo" + "file:f1.txt", // contains "bar" + "file:f2.txt" // contains "42" +}, [](const QString& acc, const QString& cur, int idx) { + return readAsync(cur).then([=](const QString& res) { + return QString("%1;%2:%3").arg(acc).arg(idx).arg(res); + }); +}, QString("index:text")); + +// 'output' resolves as soon as all promises returned by +// 'reducer' are fulfilled or at least one is rejected. + +// 'output' type: QPromise +output.then([](const QString& res) { + // res == "index:text;0:foo;1:bar;2:42" + // {...} +}); +``` + +::: warning IMPORTANT +The first time `reducer` is called, if no `initialValue` is provided, `accumulator` will be equal to the first value in the sequence, and `currentValue` to the second one (thus index will be `1`). +::: + +See also: [`QPromise::reduce`](../qpromise/reduce.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/resolve.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/resolve.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/helpers/resolve.md @@ -0,0 +1,21 @@ +--- +title: resolve +--- + +# QtPromise::resolve + +*Since: 0.5.0* + +``` +QtPromise::resolve(T value) -> QPromise +``` + +Similar to the [`QPromise::resolve`](../qpromise/resolve.md) static method, creates a promise resolved from a given `value` but without the extra typing: + +```cpp +auto promise = QtPromise::resolve(); // QPromise +auto promise = QtPromise::resolve(42); // QPromise +auto promise = QtPromise::resolve(QString("foo")); // QPromise +``` + +This method also allows to convert `QFuture` to `QPromise`, delayed until the `QFuture` is finished ([read more](../qtconcurrent.md#convert)). diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/all.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/all.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/all.md @@ -0,0 +1,34 @@ +--- +title: ::all [static] +--- + +# QPromise::all [static] + +*Since: 0.1.0* + +``` +[static] QPromise::all(Sequence> promises) -> QPromise> +``` + +Returns a `QPromise>` 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, i.e., at the respective positions to the original sequence, regardless of completion 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 +QVector > promises{ + download(QUrl("http://a...")), + download(QUrl("http://b...")), + download(QUrl("http://c...")) +}; + +auto output = QPromise::all(promises); + +// output type: QPromise> +output.then([](const QVector& res) { + // {...} +}); +``` + +See also: [`QtPromise::all`](../helpers/all.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/constructor.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/constructor.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/constructor.md @@ -0,0 +1,67 @@ +--- +title: constructor +--- + +# QPromise::QPromise + +*Since: 0.1.0* + +```cpp +QPromise::QPromise(Function resolver) +``` + +Creates a new promise that will be fulfilled or rejected by the given `resolver` lambda: + +```cpp +QPromise promise([](const QPromiseResolve& resolve, const QPromiseReject& reject) { + async_method([=](bool success, int result) { + if (success) { + resolve(result); + } else { + reject(customException()); + } + }); +}); +``` + +::: tip NOTE +`QPromise` is specialized to not contain any value, meaning that the `resolve` callback takes no argument. +::: + +**C++14** + +```cpp +QPromise promise([](const auto& resolve, const auto& reject) { + // {...} +}); +``` + +**Undefined rejection reason** + +*Since: 0.5.0* + +While not recommended because it makes tracking errors more difficult, it's also possible to reject a promise without explicit reason, in which case, a built-in [`QPromiseUndefinedException`](../exceptions/undefined.md) is thrown: + +```cpp +QPromise promise([](const QPromiseResolve& resolve, const QPromiseReject& reject) { + async_method([=](bool success, int result) { + if (success) { + resolve(result); + } else { + reject(); + } + }); +}); +``` + +```cpp +// The exception can be caught explicitly +promise.fail([](const QPromiseUndefinedException&) { + // { ... } +}) + +// ... or implicitly (since undefined) +promise.fail([]() { + // { ... } +}) +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/delay.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/delay.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/delay.md @@ -0,0 +1,20 @@ +--- +title: .delay +--- + +# QPromise::delay + +*Since: 0.2.0* + +```cpp +QPromise::delay(int msec) -> QPromise +``` + +This method returns a promise that will be fulfilled with the same value as the `input` promise and after at least `msec` milliseconds. If the `input` promise is rejected, the `output` promise is immediately rejected with the same reason. + +```cpp +QPromise input = {...} +auto output = input.delay(2000).then([](int res) { + // called 2 seconds after `input` is fulfilled +}); +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/each.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/each.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/each.md @@ -0,0 +1,56 @@ +--- +title: .each +--- + +# QPromise::each + +*Since: 0.4.0* + +```cpp +QPromise>::each(Functor functor) -> QPromise> + +// With: +// - Sequence: STL compatible container +// - Functor: Function(T value, int index) -> any +``` + +::: warning IMPORTANT +This method only applies to promise with sequence value. +::: + +Calls the given `functor` on each element in the promise value (i.e. `Sequence`), then resolves to the original sequence unmodified. If `functor` throws, `output` is rejected with the new exception. + +```cpp +QPromise> input = {...} + +auto output = input.each([](const QByteArray& value, int index) { + // process value ... +}); + +// output type: QPromise> +output.then([](const QList& res) { + // 'res' contains the original values +}); +``` + +If `functor` returns a promise (or `QFuture`), the `output` promise is delayed until all the promises are resolved. If any of the promises fail, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved. + +```cpp +QPromise> input = {...} + +auto output = input.each([](const QUrl& url, ...) { + return QPromise([&](auto resolve, auto reject) { + // process url asynchronously ... + }) +}); + +// `output` resolves as soon as all promises returned by +// `functor` are fulfilled or at least one is rejected. + +// output type: QPromise> +output.then([](const QList& res) { + // 'res' contains the original values +}); +``` + +See also: [`QtPromise::each`](../helpers/each.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/fail.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/fail.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/fail.md @@ -0,0 +1,25 @@ +--- +title: .fail +--- + +# QPromise::fail + +*Since: 0.1.0* + +```cpp +QPromise::fail(Function onRejected) -> QPromise +``` + +Shorthand to `promise.then(nullptr, onRejected)`, similar to the [`catch` statement](http://en.cppreference.com/w/cpp/language/try_catch): + +```cpp +promise.fail([](const MyException&) { + // {...} +}).fail(const QException&) { + // {...} +}).fail(const std::exception&) { + // {...} +}).fail() { + // {...} catch-all +}); +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/filter.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/filter.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/filter.md @@ -0,0 +1,49 @@ +--- +title: .filter +--- + +# QPromise::filter + +*Since: 0.4.0* + +```cpp +QPromise>::filter(Filter filterer) -> QPromise> + +// With: +// - Sequence: STL compatible container (e.g. QVector, etc.) +// - Filterer: Function(T value, int index) -> bool +``` + +::: warning IMPORTANT +This method only applies to promise with sequence value. +::: + +Iterates over all the promise values (i.e. `Sequence`) and [filters the sequence](https://en.wikipedia.org/wiki/Filter_%28higher-order_function%29) to another using the given `filterer` function. If `filterer` returns `true`, a copy of the item is put in the `output` sequence, otherwise, the item will not appear in `output`. If `filterer` throws, `output` is rejected with the new exception. + +If `filterer` returns a promise (or `QFuture`), the `output` promise is delayed until all the promises are resolved. If any of the promises fail, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved. + +```cpp +QPromise> input = {...} + +auto output = input.filter([](const QUrl& url, ...) { + return url.isValid(); // Keep only valid URLs +}).filter([](const QUrl& url, ...) { + return QPromise([&](auto resolve, auto reject) { + // resolve(true) if `url` is reachable, else resolve(false) + }); +}); + +// 'output' resolves as soon as all promises returned by +// 'filterer' are fulfilled or at least one is rejected. + +// 'output' type: QPromise> +output.then([](const QList& res) { + // 'res' contains only reachable URLs +}); +``` + +::: tip NOTE +The order of the output sequence values is guarantee to be the same as the original sequence, regardless of completion order of the promises returned by `filterer`. +::: + +See also: [`QtPromise::filter`](../helpers/filter.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/finally.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/finally.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/finally.md @@ -0,0 +1,21 @@ +--- +title: .finally +--- + +# QPromise::finally + +*Since: 0.1.0* + +```cpp +QPromise::finally(Function handler) -> QPromise +``` + +This `handler` is **always** called, without any argument and whatever the `input` promise state (fulfilled or rejected). The `output` promise has the same type as the `input` one but also the same value or error. The finally `handler` **can not modify the fulfilled value** (the returned value is ignored), however, if `handler` throws, `output` is rejected with the new exception. + +```cpp +auto output = input.finally([]() { + // {...} +}); +``` + +If `handler` returns a promise (or QFuture), the `output` promise is delayed until the returned promise is resolved and under the same conditions: the delayed value is ignored, the error transmitted to the `output` promise. diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/isfulfilled.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/isfulfilled.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/isfulfilled.md @@ -0,0 +1,13 @@ +--- +title: .isFulfilled +--- + +# QPromise::isFulfilled + +*Since: 0.1.0* + +```cpp +QPromise::isFulfilled() -> bool +``` + +Returns `true` if the promise is fulfilled, otherwise returns `false`. diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/ispending.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/ispending.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/ispending.md @@ -0,0 +1,13 @@ +--- +title: .isPending +--- + +# QPromise::isPending + +*Since: 0.1.0* + +```cpp +QPromise::isPending() -> bool +``` + +Returns `true` if the promise is pending (not fulfilled or rejected), otherwise returns `false`. diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/isrejected.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/isrejected.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/isrejected.md @@ -0,0 +1,14 @@ +--- +title: .isRejected +--- + +# QPromise::isRejected + +*Since: 0.1.0* + +```cpp +QPromise::isRejected() -> bool +``` + +Returns `true` if the promise is rejected, otherwise returns `false`. + diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/map.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/map.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/map.md @@ -0,0 +1,62 @@ +--- +title: .map +--- + +# QPromise::map + +*Since: 0.4.0* + +```cpp +QPromise>::map(Mapper mapper) -> QPromise> + +// With: +// - Sequence: STL compatible container (e.g. QVector, etc.) +// - Mapper: Function(T value, int index) -> R | QPromise +``` + +::: warning IMPORTANT +This method only applies to promise with sequence value. +::: + +Iterates over all the promise values (i.e. `Sequence`) and [maps the sequence](https://en.wikipedia.org/wiki/Map_%28higher-order_function%29) to another using the given `mapper` function. The type returned by `mapper` determines the type of the `output` promise. If `mapper` throws, `output` is rejected with the new exception. + +If `mapper` returns a promise (or `QFuture`), the `output` promise is delayed until all the promises are resolved. If any of the promises fails, `output` immediately rejects with the error of the promise that rejected, whether or not the other promises are resolved. + +```cpp +QPromise> input = {...} + +auto output = input.map([](const QUrl& url, int index) { + return QPromise([&](auto resolve, auto reject) { + // download content at 'url' and resolve + // {...} + }); +}).map([](const QByteArray& value, ...) { + // process the downloaded QByteArray + // {...} + return DownloadResult(value); +}); + +// 'output' resolves as soon as all promises returned by +// 'mapper' are fulfilled or at least one is rejected. + +// 'output' type: QPromise> +output.then([](const QVector& res) { + // {...} +}); +``` + +::: tip NOTE +The order of the output sequence values is guarantee to be the same as the original sequence, regardless of completion order of the promises returned by `mapper`. +::: + +This function is provided for convenience and is similar to: + +```cpp +promise.then([](const Sequence& values) { + return QtPromise::map(values, [](const T& value, int index) { + return // {...} + }); +}); +``` + +See also: [`QtPromise::map`](../helpers/map.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/reduce.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/reduce.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/reduce.md @@ -0,0 +1,58 @@ +--- +title: .reduce +--- + +# QPromise::reduce + +*Since: 0.5.0* + +```cpp +QPromise>::reduce(Reducer reducer) -> QPromise +QPromise>::reduce(Reducer reducer, R|QPromise initialValue) -> QPromise + +// With: +// - Sequence: STL compatible container (e.g. QVector, etc.) +// - Reducer: Function(T|R accumulator, T item, int index) -> R|QPromise +``` + +::: warning IMPORTANT +This method only applies to promise with sequence value. +::: + +Iterates over all the promise values (i.e. `Sequence`) and [reduces the sequence to a single value](https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29) using the given `reducer` function and an optional `initialValue`. The type returned by `reducer` determines the type of the `output` promise. + +See [`QtPromise::reduce`](../helpers/reduce.md) for details, this method is provided for convenience and is similar to: + +```cpp +promise.then([](const T& values) { + return QtPromise::reduce(values, reducer, initialValue); +}) +``` + +For example: + +```cpp +auto input = QtPromise::resolve(QList{ + "file:f0.txt", // contains "foo" + "file:f1.txt", // contains "bar" + "file:f2.txt" // contains "42" +}); + +// Concatenate the content of the given files, read asynchronously +auto output = input.reduce([](const QString& acc, const QString& cur, int idx) { + return readAsync(cur).then([=](const QString& res) { + return QString("%1;%2:%3").arg(acc).arg(idx).arg(res); + }); +}, QString("index:text")); + +// 'output' resolves as soon as all promises returned by +// 'reducer' are fulfilled or at least one is rejected. + +// 'output' type: QPromise +output.then([](const QString& res) { + // res == "index:text;0:foo;1:bar;2:42" + // {...} +}); +``` + +See also: [`QtPromise::reduce`](../helpers/reduce.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/reject.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/reject.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/reject.md @@ -0,0 +1,26 @@ +--- +title: ::reject [static] +--- + +# QPromise::reject [static] + +*Since: 0.1.0* + +```cpp +[static] QPromise::reject(any reason) -> QPromise +``` + +Creates a `QPromise` that is rejected with the given `reason` of *whatever type*: + +```cpp +QPromise compute(const QString& type) +{ + if (type == "foobar") { + return QPromise::reject(QString("Unknown type: %1").arg(type)); + } + + return QPromise([](const QPromiseResolve& resolve) { + // {...} + }); +} +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/resolve.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/resolve.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/resolve.md @@ -0,0 +1,28 @@ +--- +title: ::resolve [static] +--- + +# QPromise::resolve [static] + +*Since: 0.1.0* + +``` +[static] QPromise::resolve(T value) -> QPromise +``` + +Creates a `QPromise` that is fulfilled with the given `value` of type `T`: + +```cpp +QPromise compute(const QString& type) +{ + if (type == "magic") { + return QPromise::resolve(42); + } + + return QPromise([](const QPromiseResolve& resolve) { + // {...} + }); +} +``` + +See also: [`QtPromise::resolve`](../helpers/resolve.md) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/tap.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/tap.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/tap.md @@ -0,0 +1,24 @@ +--- +title: .tap +--- + +# QPromise::tap + +*Since: 0.2.0* + +```cpp +QPromise::tap(Function handler) -> QPromise +``` + +This `handler` allows to observe the value of the `input` promise, without changing the propagated value. The `output` promise will be resolved with the same value as the `input` promise (the `handler` returned value will be ignored). However, if `handler` throws, `output` is rejected with the new exception. Unlike [`finally`](finally.md), this handler is **not** called for rejections. + +```cpp +QPromise input = {...} +auto output = input.tap([](int res) { + log(res); +}).then([](int res) { + // {...} +}); +``` + +If `handler` returns a promise (or QFuture), the `output` promise is delayed until the returned promise is resolved and under the same conditions: the delayed value is ignored, the error transmitted to the `output` promise. diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/tapfail.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/tapfail.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/tapfail.md @@ -0,0 +1,27 @@ +--- +title: .tapFail +--- + +# QPromise::tapFail + +*Since: 0.4.0* + +```cpp +QPromise::tapFail(Function handler) -> QPromise +``` + +This `handler` allows to observe errors of the `input` promise without handling them - similar to [`finally`](finally.md) but **only** called on rejections. The `output` promise has the same type as the `input` one but also the same value or error. However, if `handler` throws, `output` is rejected with the new exception. + +```cpp +QPromise input = {...} +auto output = input.tapFail([](Error err) { + log(err); +}).then([](int res) { + return process(res); +}).fail([](Error err) { + handle(err); + return -1; +}); +``` + +If `handler` returns a promise (or QFuture), the `output` promise is delayed until the returned promise is resolved and under the same conditions: the delayed value is ignored, the error transmitted to the `output` promise. diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/then.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/then.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/then.md @@ -0,0 +1,95 @@ +--- +title: .then +--- + +# QPromise::then + +*Since: 0.1.0* + +```cpp +QPromise::then(Function onFulfilled, Function onRejected) -> QPromise +QPromise::then(Function onFulfilled) -> QPromise +``` + +See [Promises/A+ `.then`](https://promisesaplus.com/#the-then-method) for details. + +```cpp +QPromise input = ... +auto output = input.then([](int res) { + // called with the 'input' result if fulfilled +}, [](const ReasonType& reason) { + // called with the 'input' reason if rejected + // see QPromise::fail for details +}); +``` + +::: tip NOTE +`onRejected` handler is optional, in which case `output` will be rejected with the same reason as `input`. Also note that it's recommended to use the [`fail`](fail.md) shorthand to handle errors. +::: + +The type `` of the `output` promise depends on the return type of the `onFulfilled` handler: + +```cpp +QPromise input = {...} +auto output = input.then([](int res) { + return QString::number(res); // -> QPromise +}); + +// output type: QPromise +output.then([](const QString& res) { + // {...} +}); +``` + +::: tip NOTE +Only `onFulfilled` can change the promise type, `onRejected` **must** return the same type as `onFulfilled`. That also means if `onFulfilled` is `nullptr`, `onRejected` must return the same type as the `input` promise. +::: + +```cpp +QPromise input = ... +auto output = input.then([](int res) { + return res + 4; +}, [](const ReasonType& reason) { + return -1; +}); +``` + +If `onFulfilled` doesn't return any value, the `output` type is `QPromise`: + +```cpp +QPromise input = ... +auto output = input.then([](int res) { + // {...} +}); + +// output type: QPromise +output.then([]() { + // `QPromise` `onFulfilled` handler has no argument +}); +``` + +You can also decide to skip the promise result by omitting the handler argument: + +```cpp +QPromise input = {...} +auto output = input.then([]( /* skip int result */ ) { + // {...} +}); +``` + +The `output` promise can be *rejected* by throwing an exception in either `onFulfilled` or `onRejected`: + +```cpp +QPromise input = {...} +auto output = input.then([](int res) { + if (res == -1) { + throw ReasonType(); + } else { + return res; + } +}); + +// output.isRejected() is true +``` + +If an handler returns a promise (or QFuture), the `output` promise is delayed and will be resolved by the returned promise. diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/timeout.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/timeout.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/timeout.md @@ -0,0 +1,24 @@ +--- +title: .timeout +--- + +# QPromise::timeout + +*Since: 0.2.0* + +```cpp +QPromise::timeout(int msec, any error = QPromiseTimeoutException) -> QPromise +``` + +This method returns a promise that will be resolved with the `input` promise's fulfillment value or rejection reason. However, if the `input` promise is not fulfilled or rejected within `msec` milliseconds, the `output` promise is rejected with `error` as the reason ([`QPromiseTimeoutException`](../exceptions/timeout.md) by default). + +```cpp +QPromise input = {...} +auto output = input.timeout(2000) + .then([](int res) { + // operation succeeded within 2 seconds + }) + .fail([](const QPromiseTimeoutException& e) { + // operation timed out! + }); +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/wait.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/wait.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qpromise/wait.md @@ -0,0 +1,29 @@ +--- +title: .wait +--- + +# QPromise::wait + +*Since: 0.1.0* + +```cpp +QPromise::wait() -> QPromise +``` + +This method holds the execution of the remaining code until the `input` promise is resolved (either fulfilled or rejected), **without** blocking the event loop of the current thread: + +```cpp +int result = -1; + +QPromise input = QtPromise::resolve(QtConcurrent::run([]() { + return 42; +})).tap([&](int res) { + result = res; +}); + +// input.isPending() is true && result is -1 + +input.wait(); + +// input.isPending() is false && result is 42 +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qtconcurrent.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qtconcurrent.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qtconcurrent.md @@ -0,0 +1,66 @@ +# Qt Concurrent + +QtPromise integrates with [QtConcurrent](https://doc.qt.io/qt-5/qtconcurrent-index.html) to make easy chaining QFuture with QPromise. + +## Convert + +Converting `QFuture` to `QPromise` is done using the [`QtPromise::resolve`](helpers/resolve.md) helper: + +```cpp +QFuture future = QtConcurrent::run([]() { + // {...} + return 42; +}); + +QPromise promise = QtPromise::resolve(future); +``` + +or simply: + +```cpp +auto promise = QtPromise::resolve(QtConcurrent::run([]() { + // {...} +})); +``` + +## Chain + +Returning a `QFuture` in [`then`](qpromise/then.md) or [`fail`](qpromise/fail.md) automatically translate to `QPromise`: + +```cpp +QPromise input = ... +auto output = input.then([](int res) { + return QtConcurrent::run([]() { + // {...} + return QString("42"); + }); +}); + +// output type: QPromise +output.then([](const QString& res) { + // {...} +}); +``` + +The `output` promise is resolved when the `QFuture` is [finished](https://doc.qt.io/qt-5/qfuture.html#isFinished). + +## Error + +Exceptions thrown from a QtConcurrent thread reject the associated promise with the exception as the reason. Note that if you throw an exception that is not a subclass of `QException`, the promise will be rejected with [`QUnhandledException`](https://doc.qt.io/qt-5/qunhandledexception.html#details) (this restriction only applies to exceptions thrown from a QtConcurrent thread, [read more](https://doc.qt.io/qt-5/qexception.html#details)). + +```cpp +QPromise promise = ... +promise.then([](int res) { + return QtConcurrent::run([]() { + // {...} + + if (!success) { + throw CustomException(); + } + + return QString("42"); + }); +}).fail(const CustomException& err) { + // {...} +}); +``` diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qtsignals.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qtsignals.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/qtsignals.md @@ -0,0 +1,89 @@ +# Qt Signals + +QtPromise supports creating promises that are resolved or rejected by regular [Qt signals](https://doc.qt.io/qt-5/signalsandslots.html). + +::: warning IMPORTANT +A promise connected to a signal will be resolved (fulfilled or rejected) **only one time**, no matter if the signals are emitted multiple times. Internally, the promise is disconnected from all signals as soon as one signal is emitted. +::: + +## Resolve Signal + +The [`QtPromise::connect()`](helpers/connect.md) helper allows to create a promise resolved from a single signal: + +```cpp +// [signal] Object::finished(const QByteArray&) +auto output = QtPromise::connect(obj, &Object::finished); + +// output type: QPromise +output.then([](const QByteArray& data) { + // {...} +}); +``` + +If the signal doesn't provide any argument, a `QPromise` is returned: + +```cpp +// [signal] Object::done() +auto output = QtPromise::connect(obj, &Object::done); + +// output type: QPromise +output.then([]() { + // {...} +}); +``` + +::: tip NOTE +QtPromise currently only supports single argument signals, which means that only the first argument is used to fulfill or reject the connected promise, other arguments being ignored. +::: + +## Reject Signal + +The [`QtPromise::connect()`](helpers/connect.md) helper also allows to reject the promise from another signal: + +```cpp +// [signal] Object::finished(const QByteArray& data) +// [signal] Object::error(ObjectError error) +auto output = QtPromise::connect(obj, &Object::finished, &Object::error); + +// output type: QPromise +output.then([](const QByteArray& data) { + // {...} +}).fail(const ObjectError& error) { + // {...} +}); +``` + +If the rejection signal doesn't provide any argument, the promise will be rejected +with [`QPromiseUndefinedException`](../exceptions/undefined), for example: + +```cpp +// [signal] Object::finished() +// [signal] Object::error() +auto output = QtPromise::connect(obj, &Object::finished, &Object::error); + +// output type: QPromise +output.then([]() { + // {...} +}).fail(const QPromiseUndefinedException& error) { + // {...} +}); +``` + +A third variant allows to connect the resolve and reject signals from different objects: + +```cpp +// [signal] ObjectA::finished(const QByteArray& data) +// [signal] ObjectB::error(ObjectBError error) +auto output = QtPromise::connect(objA, &ObjectA::finished, objB, &ObjectB::error); + +// output type: QPromise +output.then([](const QByteArray& data) { + // {...} +}).fail(const ObjectBError& error) { + // {...} +}); +``` + +Additionally to the rejection signal, promises created using [`QtPromise::connect()`](helpers/connect.md) are automatically rejected with [`QPromiseContextException`](exceptions/context.md) if the sender is destroyed before fulfilling the promise. + +See [`QtPromise::connect()`](helpers/connect.md) for more details. diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/thread-safety.md b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/thread-safety.md new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/docs/qtpromise/thread-safety.md @@ -0,0 +1,7 @@ +# Thread-Safety + +QPromise is thread-safe and can be copied and accessed across different threads. QPromise relies on [explicitly data sharing](https://doc.qt.io/qt-5/qexplicitlyshareddatapointer.html#details) and thus `auto p2 = p1` represents the same promise: when `p1` resolves, handlers registered on `p1` and `p2` are called, the fulfilled value being shared between both instances. + +::: warning IMPORTANT +While it's safe to access the resolved value from different threads using [`then`](qpromise/then.md), QPromise provides no guarantee about the object being pointed to. Thread-safety and reentrancy rules for that object still apply. +::: diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/include/QtPromise b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/include/QtPromise new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/include/QtPromise @@ -0,0 +1,9 @@ +#ifndef QTPROMISE_MODULE_H +#define QTPROMISE_MODULE_H + +#include "../src/qtpromise/qpromise.h" +#include "../src/qtpromise/qpromiseconnections.h" +#include "../src/qtpromise/qpromisefuture.h" +#include "../src/qtpromise/qpromisehelpers.h" + +#endif // QTPROMISE_MODULE_H diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/package/features/qtpromise.prf b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/package/features/qtpromise.prf new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/package/features/qtpromise.prf @@ -0,0 +1 @@ +include(../../qtpromise.pri) diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/qpm.json b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/qpm.json new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/qpm.json @@ -0,0 +1,18 @@ +{ + "name": "com.github.simonbrunel.qtpromise", + "description": "Promises/A+ implementation for Qt/C++", + "author": { + "name": "Simon Brunel", + "email": "simonbrunel@users.noreply.github.com" + }, + "repository": { + "type": "GITHUB", + "url": "https://github.com/simonbrunel/qtpromise.git" + }, + "version": { + "label": "0.5.0" + }, + "license": "MIT", + "pri_filename": "qtpromise.pri", + "webpage": "https://qtpromise.netlify.com" +} diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/qtpromise.pri b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/qtpromise.pri new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/qtpromise.pri @@ -0,0 +1,3 @@ +INCLUDEPATH += $$PWD/include $$PWD/src +DEPENDPATH += $$PWD/include $$PWD/src +CONFIG += c++11 diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/qtpromise.pro b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/qtpromise.pro new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/qtpromise.pro @@ -0,0 +1,12 @@ +TEMPLATE = subdirs +SUBDIRS = \ + tests + +_qt_creator_ { + SUBDIRS += src +} + +OTHER_FILES = \ + package/features/*.prf \ + include/* \ + qtpromise.pri diff --git a/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/src/qtpromise/qpromise.h b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/src/qtpromise/qpromise.h new file mode 100644 --- /dev/null +++ b/kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/src/qtpromise/qpromise.h @@ -0,0 +1,149 @@ +#ifndef QTPROMISE_QPROMISE_H +#define QTPROMISE_QPROMISE_H + +#include "qpromise_p.h" +#include "qpromiseexceptions.h" +#include "qpromiseglobal.h" +#include "qpromiseresolver.h" + +// Qt +#include + +namespace QtPromise { + +template +class QPromiseBase +{ +public: + using Type = T; + + template ::count == 1, int>::type = 0> + inline QPromiseBase(F resolver); + + template ::count != 1, int>::type = 0> + inline QPromiseBase(F resolver); + + QPromiseBase(const QPromiseBase& other): m_d(other.m_d) {} + QPromiseBase(const QPromise& other): m_d(other.m_d) {} + QPromiseBase(QPromiseBase&& other) Q_DECL_NOEXCEPT { swap(other); } + + virtual ~QPromiseBase() { } + + QPromiseBase& operator=(const QPromiseBase& other) { m_d = other.m_d; return *this;} + QPromiseBase& operator=(QPromiseBase&& other) Q_DECL_NOEXCEPT + { QPromiseBase(std::move(other)).swap(*this); return *this; } + + bool operator==(const QPromiseBase& other) const { return (m_d == other.m_d); } + bool operator!=(const QPromiseBase& other) const { return (m_d != other.m_d); } + + void swap(QPromiseBase& other) Q_DECL_NOEXCEPT { qSwap(m_d, other.m_d); } + + bool isFulfilled() const { return m_d->isFulfilled(); } + bool isRejected() const { return m_d->isRejected(); } + bool isPending() const { return m_d->isPending(); } + + template + inline typename QtPromisePrivate::PromiseHandler::Promise + then(const TFulfilled& fulfilled, const TRejected& rejected) const; + + template + inline typename QtPromisePrivate::PromiseHandler::Promise + then(TFulfilled&& fulfilled) const; + + template + inline typename QtPromisePrivate::PromiseHandler::Promise + fail(TRejected&& rejected) const; + + template + inline QPromise finally(THandler handler) const; + + template + inline QPromise tap(THandler handler) const; + + template + inline QPromise tapFail(THandler handler) const; + + template + inline QPromise timeout(int msec, E&& error = E()) const; + + inline QPromise delay(int msec) const; + inline QPromise wait() const; + +public: // STATIC + template + inline static QPromise reject(E&& error); + +protected: + friend struct QtPromisePrivate::PromiseFulfill>; + friend class QtPromisePrivate::PromiseResolver; + friend struct QtPromisePrivate::PromiseInspect; + + QExplicitlySharedDataPointer> m_d; +}; + +template +class QPromise : public QPromiseBase +{ +public: + template + QPromise(F&& resolver): QPromiseBase(std::forward(resolver)) { } + + template + inline QPromise + each(Functor fn); + + template + inline QPromise + filter(Functor fn); + + template + inline typename QtPromisePrivate::PromiseMapper::PromiseType + map(Functor fn); + + template + inline typename QtPromisePrivate::PromiseDeduce::Type + reduce(Functor fn, Input initial); + + template + inline typename QtPromisePrivate::PromiseDeduce::Type + reduce(Functor fn); + +public: // STATIC + + // DEPRECATED (remove at version 1) + template