Differential D18758 Diff 58398 kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/src/qtpromise/qpromise.inl
Changeset View
Changeset View
Standalone View
Standalone View
kdevplatform/3rdparty/qtpromise/qtpromise-0.5.0/src/qtpromise/qpromise.inl
- This file was added.
1 | #include "qpromise.h" | ||||
---|---|---|---|---|---|
2 | #include "qpromisehelpers.h" | ||||
3 | | ||||
4 | // Qt | ||||
5 | #include <QCoreApplication> | ||||
6 | #include <QSharedPointer> | ||||
7 | #include <QTimer> | ||||
8 | | ||||
9 | namespace QtPromise { | ||||
10 | | ||||
11 | template <typename T> | ||||
12 | template <typename F, typename std::enable_if<QtPromisePrivate::ArgsOf<F>::count == 1, int>::type> | ||||
13 | inline QPromiseBase<T>::QPromiseBase(F callback) | ||||
14 | : m_d(new QtPromisePrivate::PromiseData<T>()) | ||||
15 | { | ||||
16 | QtPromisePrivate::PromiseResolver<T> resolver(*this); | ||||
17 | | ||||
18 | try { | ||||
19 | callback(QPromiseResolve<T>(resolver)); | ||||
20 | } catch (...) { | ||||
21 | resolver.reject(std::current_exception()); | ||||
22 | } | ||||
23 | } | ||||
24 | | ||||
25 | template <typename T> | ||||
26 | template <typename F, typename std::enable_if<QtPromisePrivate::ArgsOf<F>::count != 1, int>::type> | ||||
27 | inline QPromiseBase<T>::QPromiseBase(F callback) | ||||
28 | : m_d(new QtPromisePrivate::PromiseData<T>()) | ||||
29 | { | ||||
30 | QtPromisePrivate::PromiseResolver<T> resolver(*this); | ||||
31 | | ||||
32 | try { | ||||
33 | callback(QPromiseResolve<T>(resolver), QPromiseReject<T>(resolver)); | ||||
34 | } catch (...) { | ||||
35 | resolver.reject(std::current_exception()); | ||||
36 | } | ||||
37 | } | ||||
38 | | ||||
39 | template <typename T> | ||||
40 | template <typename TFulfilled, typename TRejected> | ||||
41 | inline typename QtPromisePrivate::PromiseHandler<T, TFulfilled>::Promise | ||||
42 | QPromiseBase<T>::then(const TFulfilled& fulfilled, const TRejected& rejected) const | ||||
43 | { | ||||
44 | using namespace QtPromisePrivate; | ||||
45 | using PromiseType = typename PromiseHandler<T, TFulfilled>::Promise; | ||||
46 | | ||||
47 | PromiseType next([&]( | ||||
48 | const QPromiseResolve<typename PromiseType::Type>& resolve, | ||||
49 | const QPromiseReject<typename PromiseType::Type>& reject) { | ||||
50 | m_d->addHandler(PromiseHandler<T, TFulfilled>::create(fulfilled, resolve, reject)); | ||||
51 | m_d->addCatcher(PromiseCatcher<T, TRejected>::create(rejected, resolve, reject)); | ||||
52 | }); | ||||
53 | | ||||
54 | if (!m_d->isPending()) { | ||||
55 | m_d->dispatch(); | ||||
56 | } | ||||
57 | | ||||
58 | return next; | ||||
59 | } | ||||
60 | | ||||
61 | template <typename T> | ||||
62 | template <typename TFulfilled> | ||||
63 | inline typename QtPromisePrivate::PromiseHandler<T, TFulfilled>::Promise | ||||
64 | QPromiseBase<T>::then(TFulfilled&& fulfilled) const | ||||
65 | { | ||||
66 | return then(std::forward<TFulfilled>(fulfilled), nullptr); | ||||
67 | } | ||||
68 | | ||||
69 | template <typename T> | ||||
70 | template <typename TRejected> | ||||
71 | inline typename QtPromisePrivate::PromiseHandler<T, std::nullptr_t>::Promise | ||||
72 | QPromiseBase<T>::fail(TRejected&& rejected) const | ||||
73 | { | ||||
74 | return then(nullptr, std::forward<TRejected>(rejected)); | ||||
75 | } | ||||
76 | | ||||
77 | template <typename T> | ||||
78 | template <typename THandler> | ||||
79 | inline QPromise<T> QPromiseBase<T>::finally(THandler handler) const | ||||
80 | { | ||||
81 | QPromise<T> p = *this; | ||||
82 | return p.then(handler, handler).then([=]() { | ||||
83 | return p; | ||||
84 | }); | ||||
85 | } | ||||
86 | | ||||
87 | template <typename T> | ||||
88 | template <typename THandler> | ||||
89 | inline QPromise<T> QPromiseBase<T>::tap(THandler handler) const | ||||
90 | { | ||||
91 | QPromise<T> p = *this; | ||||
92 | return p.then(handler).then([=]() { | ||||
93 | return p; | ||||
94 | }); | ||||
95 | } | ||||
96 | | ||||
97 | template <typename T> | ||||
98 | template <typename THandler> | ||||
99 | inline QPromise<T> QPromiseBase<T>::tapFail(THandler handler) const | ||||
100 | { | ||||
101 | QPromise<T> p = *this; | ||||
102 | return p.then([](){}, handler).then([=]() { | ||||
103 | return p; | ||||
104 | }); | ||||
105 | } | ||||
106 | | ||||
107 | template <typename T> | ||||
108 | template <typename E> | ||||
109 | inline QPromise<T> QPromiseBase<T>::timeout(int msec, E&& error) const | ||||
110 | { | ||||
111 | QPromise<T> p = *this; | ||||
112 | return QPromise<T>([&]( | ||||
113 | const QPromiseResolve<T>& resolve, | ||||
114 | const QPromiseReject<T>& reject) { | ||||
115 | | ||||
116 | QTimer::singleShot(msec, [=]() { | ||||
117 | // we don't need to verify the current promise state, reject() | ||||
118 | // takes care of checking if the promise is already resolved, | ||||
119 | // and thus will ignore this rejection. | ||||
120 | reject(std::move(error)); | ||||
121 | }); | ||||
122 | | ||||
123 | QtPromisePrivate::PromiseFulfill<QPromise<T>>::call(p, resolve, reject); | ||||
124 | }); | ||||
125 | } | ||||
126 | | ||||
127 | template <typename T> | ||||
128 | inline QPromise<T> QPromiseBase<T>::delay(int msec) const | ||||
129 | { | ||||
130 | return tap([=]() { | ||||
131 | return QPromise<void>([&](const QPromiseResolve<void>& resolve) { | ||||
132 | QTimer::singleShot(msec, resolve); | ||||
133 | }); | ||||
134 | }); | ||||
135 | } | ||||
136 | | ||||
137 | template <typename T> | ||||
138 | inline QPromise<T> QPromiseBase<T>::wait() const | ||||
139 | { | ||||
140 | // @TODO wait timeout + global timeout | ||||
141 | while (m_d->isPending()) { | ||||
142 | QCoreApplication::processEvents(QEventLoop::AllEvents); | ||||
143 | QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); | ||||
144 | } | ||||
145 | | ||||
146 | return *this; | ||||
147 | } | ||||
148 | | ||||
149 | template <typename T> | ||||
150 | template <typename E> | ||||
151 | inline QPromise<T> QPromiseBase<T>::reject(E&& error) | ||||
152 | { | ||||
153 | return QPromise<T>([&](const QPromiseResolve<T>&, const QPromiseReject<T>& reject) { | ||||
154 | reject(std::forward<E>(error)); | ||||
155 | }); | ||||
156 | } | ||||
157 | | ||||
158 | template <typename T> | ||||
159 | template <typename Functor> | ||||
160 | inline QPromise<T> QPromise<T>::each(Functor fn) | ||||
161 | { | ||||
162 | return this->tap([=](const T& values) { | ||||
163 | int i = 0; | ||||
164 | | ||||
165 | std::vector<QPromise<void>> promises; | ||||
166 | for (const auto& v : values) { | ||||
167 | promises.push_back( | ||||
168 | QtPromise::attempt(fn, v, i) | ||||
169 | .then([]() { | ||||
170 | // Cast to void in case fn returns a non promise value. | ||||
171 | // TODO remove when implicit cast is implemented. | ||||
172 | })); | ||||
173 | | ||||
174 | i++; | ||||
175 | } | ||||
176 | | ||||
177 | return QtPromise::all(promises); | ||||
178 | }); | ||||
179 | } | ||||
180 | | ||||
181 | template <typename T> | ||||
182 | template <typename Functor> | ||||
183 | inline QPromise<T> QPromise<T>::filter(Functor fn) | ||||
184 | { | ||||
185 | return this->then([=](const T& values) { | ||||
186 | return QtPromise::filter(values, fn); | ||||
187 | }); | ||||
188 | } | ||||
189 | | ||||
190 | template <typename T> | ||||
191 | template <typename Functor> | ||||
192 | inline typename QtPromisePrivate::PromiseMapper<T, Functor>::PromiseType | ||||
193 | QPromise<T>::map(Functor fn) | ||||
194 | { | ||||
195 | return this->then([=](const T& values) { | ||||
196 | return QtPromise::map(values, fn); | ||||
197 | }); | ||||
198 | } | ||||
199 | | ||||
200 | template <typename T> | ||||
201 | template <typename Functor, typename Input> | ||||
202 | inline typename QtPromisePrivate::PromiseDeduce<Input>::Type | ||||
203 | QPromise<T>::reduce(Functor fn, Input initial) | ||||
204 | { | ||||
205 | return this->then([=](const T& values) { | ||||
206 | return QtPromise::reduce(values, fn, initial); | ||||
207 | }); | ||||
208 | } | ||||
209 | | ||||
210 | template <typename T> | ||||
211 | template <typename Functor, typename U> | ||||
212 | inline typename QtPromisePrivate::PromiseDeduce<typename U::value_type>::Type | ||||
213 | QPromise<T>::reduce(Functor fn) | ||||
214 | { | ||||
215 | return this->then([=](const T& values) { | ||||
216 | return QtPromise::reduce(values, fn); | ||||
217 | }); | ||||
218 | } | ||||
219 | | ||||
220 | template <typename T> | ||||
221 | template <template <typename, typename...> class Sequence, typename ...Args> | ||||
222 | inline QPromise<QVector<T>> QPromise<T>::all(const Sequence<QPromise<T>, Args...>& promises) | ||||
223 | { | ||||
224 | return QtPromise::all(promises); | ||||
225 | } | ||||
226 | | ||||
227 | template <typename T> | ||||
228 | inline QPromise<T> QPromise<T>::resolve(const T& value) | ||||
229 | { | ||||
230 | return QPromise<T>([&](const QPromiseResolve<T>& resolve) { | ||||
231 | resolve(value); | ||||
232 | }); | ||||
233 | } | ||||
234 | | ||||
235 | template <typename T> | ||||
236 | inline QPromise<T> QPromise<T>::resolve(T&& value) | ||||
237 | { | ||||
238 | return QPromise<T>([&](const QPromiseResolve<T>& resolve) { | ||||
239 | resolve(std::forward<T>(value)); | ||||
240 | }); | ||||
241 | } | ||||
242 | | ||||
243 | template <template <typename, typename...> class Sequence, typename ...Args> | ||||
244 | inline QPromise<void> QPromise<void>::all(const Sequence<QPromise<void>, Args...>& promises) | ||||
245 | { | ||||
246 | return QtPromise::all(promises); | ||||
247 | } | ||||
248 | | ||||
249 | inline QPromise<void> QPromise<void>::resolve() | ||||
250 | { | ||||
251 | return QtPromise::resolve(); | ||||
252 | } | ||||
253 | | ||||
254 | } // namespace QtPromise |