Commit Graph

35 Commits

Author SHA1 Message Date
700098ef7b Reorganize exceptions and add unit tests 2019-03-01 17:41:32 +01:00
a6d883acbd Update LICENSE year and cleanup a few comments 2019-02-18 20:30:41 +01:00
fa5a4192ff Allow undefined rejection reason
While not recommended because it makes tracking errors more difficult, it's now possible to reject a promise without explicit reason, in which case, a built-in `QPromiseUndefinedException` is thrown. This is done in anticipation of handling rejection signals without argument.
2019-01-31 19:03:57 +01:00
051fed5fbc Implement QPromise<Sequence<T>>::each(functor)
Call the given `functor` on each element in the promise value (i.e. `Sequence<T>`), then resolve to the original sequence unmodified. Also provide a static helper to directly filter values (`QtPromise::each(values, functor)`).
2018-09-07 16:50:29 +02:00
f610826ef0 Implement QtPromise::attempt(functor, args...)
Add a new helper that 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.

Also simplify PromiseDispatch which now calls the functor with a variable number of arguments (including none).
2018-05-31 09:02:51 +02:00
4fa7a37750 Implement QPromise<Sequence<T>>::filter(filterer)
Add a new method that iterates over all the promise values (i.e. `Sequence<T>`) and filters the sequence 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`. Also provide a static helper to directly filter values (`QtPromise::filter(values, filterer)`).
2018-05-30 18:52:53 +02:00
69c07855f4 Implement QPromise<Sequence<T>>::map(mapper) (#15)
Iterate over all the promise value (i.e. `Sequence<T>`) and map the sequence to another using the given `mapper` function. Also provide a static helper to directly map values (`QtPromise::map(values, mapper)`).
2018-05-26 11:40:51 +02:00
54d88f16a3 Reorganize helpers unit tests 2018-05-23 21:24:00 +02:00
8da467e9da Relax timing constraints when checking timeout in tst_timeout 2018-05-21 10:12:35 +02:00
26a2110a14 Fix GCC -Wold-style-cast warnings
Explicitly enable -Wold-style-cast and make all warnings into errors in tests (-Werror on GCC, -WX on MSVC).
2018-05-10 11:51:17 +02:00
fa987a5044 Cleanup promise captured in resolve/reject
Make sure that QPromiseResolve and QPromiseReject release their associated promise as soon as one of them is resolved or rejected, ensuring that the promise data is cleaned up once resolved (that fixes cases where one or both of them are captured in a signal/slot connection lambda)
2018-05-10 11:51:17 +02:00
7b0cba5b9d Allow QSharedPointer as rejection reason
Embed the promise fulfillment value and rejection reason in respectively PromiseValue and PromiseError private wrappers, both storing the data in a shared pointer (QPromiseError is now deprecated).
2018-05-10 11:51:14 +02:00
2c8ed6e676 Remove extra space between closing angle brackets
The extra space between template closing angle brackets is not anymore required in C++11 (https://en.wikipedia.org/wiki/C%2B%2B11#Right_angle_bracket)
2018-05-10 09:21:21 +02:00
50bae380be Implement QPromise::tapFail(handler) 2018-03-29 09:08:19 +02:00
313d3882d7 Fix dispatching when app (or thread) terminated
Make sure to **not** notify handlers if the captured thread doesn't exist anymore, which would potentially result in dispatching to the wrong thread (ie. nullptr == current thread). This also applies when the app is shutting down and the even loop is not anymore available. In both cases, we should not trigger any error and skip notifications.
2018-02-24 12:43:52 +01:00
4af2740d80 Enable QPromise<T>::resolve() by reference 2018-02-14 22:36:22 +01:00
c34316243e 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.
2018-02-11 16:26:27 +01:00
d306423159 Add QPromise assignment and equality operators 2018-02-10 18:26:08 +01:00
d3b69f1248 Split QPromise tests per feature in separate .pro 2017-10-26 23:03:16 +02:00
36a0eed12a Move tests under their own qtpromise sub folder 2017-09-19 09:39:13 +02:00
931d5d5b13 Fix MSVC 2013 compilation issues 2017-09-04 11:17:26 +02:00
18324d3f44 Implement QPromise::timeout(msec, error) 2017-09-02 12:23:42 +02:00
b47ca0569e Implement QPromise::delay(msec)
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.
2017-08-24 18:28:44 +02:00
c55fa03e7b Implement QPromise::tap(handler)
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`, this handler is not called for rejections.
2017-08-23 21:06:59 +02:00
25d2bad54f Enhance QPromise::finally implementation
Make sure that the chained value is not copied when `finally` is called for a fulfilled input promise. The value was copied 7 times in the previous version because it was captured in a lambda, which one copied multiple times.
2017-08-23 10:59:44 +02:00
49a1d6a57b Avoid value copy when fulfilled from promise 2017-08-22 21:52:28 +02:00
5e754d1b08 Minor code style cleanup 2017-06-10 10:06:25 +02:00
da3ae12c02 More QPromise<T/void> unit tests 2017-06-10 09:58:22 +02:00
81625e1964 Add multithreading support
Make QPromise thread safe but also ensure that continuation lambdas (then/fail/finally) are called in the thread of the promise instance they are attached to.
2017-06-04 22:22:26 +02:00
9bbef41a50 C++11 optimizations and (basic) benchmark
Make continuation methods const (then/fail/finally) and ensure that the resolved promise value/error is copied only when required, same for user lambdas (dispatching result is now fully handled by the PromiseData).
2017-06-03 10:04:28 +02:00
a8ad3619b9 Setup Travis CI builds and code coverage
Built with Qt 5.4.2/GCC 4.8.4, code coverage with LCOV 1.13 and reported to Codecov.
2017-05-26 14:39:11 +02:00
4919a68959 Enhance QFuture integration and add unit tests
QFuture canceled with `QFuture::cancel()` now rejects attached promises with `QPromiseCanceledException`. In case the future is canceled because an exception (e) has been thrown, the promise is rejected with the same (e) exception (or `QUnhandledException` if not a subclass of `QException`).
2017-05-25 18:00:17 +02:00
596855f579 Move helpers in separate file and add unit tests
Gather helpers in `promisehelpers.h` and add a global include file to make easier integration with the lib (`#include <QtPromise>`).
2017-05-25 09:19:36 +02:00
ce3ed72dd4 Promise creation from callback only (resolver)
Make sure that the promise state can only be changed by the promise producer (and not consumers) by removing the `fulfill` and `reject` methods from the instance members and introducing a new constructor accepting a resolver lambda. That also means that a promise can't anymore be default constructed.

Add the static `QPromise<T>::resolve` and `QPromise<T>::reject` methods to create synchronously fulfilled or rejected promises, and fix the `qPromise` helper to handle deduced promises (e.g. `qPromise(QFuture<int>()) -> QPromise<int>`).
2017-05-20 09:40:42 +02:00
6a642446df Initial implementation 2017-05-14 19:03:01 +02:00