diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-04-12 16:02:56 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-04-12 16:02:56 +0200 |
commit | 7357673a7ee5a0976447d0285e3aa272e8626282 (patch) | |
tree | 667c7f7c8a780c88419f878ed5c381d54a7ed803 /async/src/future.h | |
parent | e85967518b9041e9943ec5f1765c6694bb153840 (diff) | |
parent | 73b8fe58c6fb985898d2bbf431926f0628e2b0a9 (diff) | |
download | sink-7357673a7ee5a0976447d0285e3aa272e8626282.tar.gz sink-7357673a7ee5a0976447d0285e3aa272e8626282.zip |
Merge remote-tracking branch 'origin/develop' into develop
Diffstat (limited to 'async/src/future.h')
-rw-r--r-- | async/src/future.h | 145 |
1 files changed, 60 insertions, 85 deletions
diff --git a/async/src/future.h b/async/src/future.h index cadd96d..ff199ef 100644 --- a/async/src/future.h +++ b/async/src/future.h | |||
@@ -29,28 +29,35 @@ class QEventLoop; | |||
29 | 29 | ||
30 | namespace Async { | 30 | namespace Async { |
31 | 31 | ||
32 | class FutureWatcherBase; | ||
33 | template<typename T> | ||
34 | class FutureWatcher; | ||
35 | |||
32 | namespace Private { | 36 | namespace Private { |
33 | class Execution; | 37 | class Execution; |
34 | class ExecutorBase; | 38 | class ExecutorBase; |
35 | 39 | ||
36 | typedef QSharedPointer<Execution> ExecutionPtr; | 40 | typedef QSharedPointer<Execution> ExecutionPtr; |
37 | 41 | } // namespace Private | |
38 | } | ||
39 | 42 | ||
40 | class FutureBase | 43 | class FutureBase |
41 | { | 44 | { |
42 | friend class Async::Private::Execution; | 45 | friend class Async::Private::Execution; |
46 | friend class FutureWatcherBase; | ||
43 | 47 | ||
44 | public: | 48 | public: |
45 | virtual ~FutureBase(); | 49 | virtual ~FutureBase(); |
46 | 50 | ||
47 | virtual void setFinished() = 0; | 51 | void setFinished(); |
48 | virtual bool isFinished() const = 0; | 52 | bool isFinished() const; |
49 | virtual void setError(int code = 1, const QString &message = QString()) = 0; | 53 | void setError(int code = 1, const QString &message = QString()); |
54 | int errorCode() const; | ||
55 | QString errorMessage() const; | ||
50 | 56 | ||
51 | protected: | 57 | void setProgress(qreal progress); |
52 | virtual void releaseExecution() = 0; | 58 | void setProgress(int processed, int total); |
53 | 59 | ||
60 | protected: | ||
54 | class PrivateBase : public QSharedData | 61 | class PrivateBase : public QSharedData |
55 | { | 62 | { |
56 | public: | 63 | public: |
@@ -59,12 +66,24 @@ protected: | |||
59 | 66 | ||
60 | void releaseExecution(); | 67 | void releaseExecution(); |
61 | 68 | ||
69 | bool finished; | ||
70 | int errorCode; | ||
71 | QString errorMessage; | ||
72 | |||
73 | QVector<QPointer<FutureWatcherBase>> watchers; | ||
62 | private: | 74 | private: |
63 | QWeakPointer<Async::Private::Execution> mExecution; | 75 | QWeakPointer<Async::Private::Execution> mExecution; |
64 | }; | 76 | }; |
65 | 77 | ||
66 | FutureBase(); | 78 | FutureBase(); |
79 | FutureBase(FutureBase::PrivateBase *dd); | ||
67 | FutureBase(const FutureBase &other); | 80 | FutureBase(const FutureBase &other); |
81 | |||
82 | void addWatcher(Async::FutureWatcherBase *watcher); | ||
83 | void releaseExecution(); | ||
84 | |||
85 | protected: | ||
86 | QExplicitlySharedDataPointer<PrivateBase> d; | ||
68 | }; | 87 | }; |
69 | 88 | ||
70 | template<typename T> | 89 | template<typename T> |
@@ -79,42 +98,7 @@ class FutureGeneric : public FutureBase | |||
79 | friend class FutureWatcher<T>; | 98 | friend class FutureWatcher<T>; |
80 | 99 | ||
81 | public: | 100 | public: |
82 | void setFinished() | 101 | void waitForFinished() const |
83 | { | ||
84 | if (d->finished) { | ||
85 | return; | ||
86 | } | ||
87 | d->finished = true; | ||
88 | for (auto watcher : d->watchers) { | ||
89 | if (watcher) { | ||
90 | watcher->futureReadyCallback(); | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | bool isFinished() const | ||
96 | { | ||
97 | return d->finished; | ||
98 | } | ||
99 | |||
100 | void setError(int errorCode, const QString &message) | ||
101 | { | ||
102 | d->errorCode = errorCode; | ||
103 | d->errorMessage = message; | ||
104 | setFinished(); | ||
105 | } | ||
106 | |||
107 | int errorCode() const | ||
108 | { | ||
109 | return d->errorCode; | ||
110 | } | ||
111 | |||
112 | QString errorMessage() const | ||
113 | { | ||
114 | return d->errorMessage; | ||
115 | } | ||
116 | |||
117 | void waitForFinished() | ||
118 | { | 102 | { |
119 | if (isFinished()) { | 103 | if (isFinished()) { |
120 | return; | 104 | return; |
@@ -123,52 +107,33 @@ public: | |||
123 | QEventLoop eventLoop; | 107 | QEventLoop eventLoop; |
124 | QObject::connect(&watcher, &Async::FutureWatcher<T>::futureReady, | 108 | QObject::connect(&watcher, &Async::FutureWatcher<T>::futureReady, |
125 | &eventLoop, &QEventLoop::quit); | 109 | &eventLoop, &QEventLoop::quit); |
126 | watcher.setFuture(*static_cast<Async::Future<T>*>(this)); | 110 | watcher.setFuture(*static_cast<const Async::Future<T>*>(this)); |
127 | eventLoop.exec(); | 111 | eventLoop.exec(); |
128 | } | 112 | } |
129 | 113 | ||
130 | protected: | 114 | protected: |
131 | FutureGeneric(const Async::Private::ExecutionPtr &execution) | 115 | FutureGeneric(const Async::Private::ExecutionPtr &execution) |
132 | : FutureBase() | 116 | : FutureBase(new Private(execution)) |
133 | , d(new Private(execution)) | ||
134 | {} | 117 | {} |
135 | 118 | ||
136 | FutureGeneric(const FutureGeneric<T> &other) | 119 | FutureGeneric(const FutureGeneric<T> &other) |
137 | : FutureBase(other) | 120 | : FutureBase(other) |
138 | , d(other.d) | ||
139 | {} | 121 | {} |
140 | 122 | ||
123 | protected: | ||
141 | class Private : public FutureBase::PrivateBase | 124 | class Private : public FutureBase::PrivateBase |
142 | { | 125 | { |
143 | public: | 126 | public: |
144 | Private(const Async::Private::ExecutionPtr &execution) | 127 | Private(const Async::Private::ExecutionPtr &execution) |
145 | : FutureBase::PrivateBase(execution) | 128 | : FutureBase::PrivateBase(execution) |
146 | , finished(false) | ||
147 | , errorCode(0) | ||
148 | {} | 129 | {} |
149 | 130 | ||
150 | typename std::conditional<std::is_void<T>::value, int /* dummy */, T>::type | 131 | typename std::conditional<std::is_void<T>::value, int /* dummy */, T>::type |
151 | value; | 132 | value; |
152 | |||
153 | QVector<QPointer<FutureWatcher<T>>> watchers; | ||
154 | bool finished; | ||
155 | int errorCode; | ||
156 | QString errorMessage; | ||
157 | }; | 133 | }; |
158 | |||
159 | QExplicitlySharedDataPointer<Private> d; | ||
160 | |||
161 | void releaseExecution() | ||
162 | { | ||
163 | d->releaseExecution(); | ||
164 | } | ||
165 | |||
166 | void addWatcher(FutureWatcher<T> *watcher) | ||
167 | { | ||
168 | d->watchers.append(QPointer<FutureWatcher<T>>(watcher)); | ||
169 | } | ||
170 | }; | 134 | }; |
171 | 135 | ||
136 | |||
172 | template<typename T> | 137 | template<typename T> |
173 | class Future : public FutureGeneric<T> | 138 | class Future : public FutureGeneric<T> |
174 | { | 139 | { |
@@ -188,12 +153,12 @@ public: | |||
188 | 153 | ||
189 | void setValue(const T &value) | 154 | void setValue(const T &value) |
190 | { | 155 | { |
191 | this->d->value = value; | 156 | static_cast<typename FutureGeneric<T>::Private*>(this->d.data())->value = value; |
192 | } | 157 | } |
193 | 158 | ||
194 | T value() const | 159 | T value() const |
195 | { | 160 | { |
196 | return this->d->value; | 161 | return static_cast<typename FutureGeneric<T>::Private*>(this->d.data())->value; |
197 | } | 162 | } |
198 | 163 | ||
199 | protected: | 164 | protected: |
@@ -208,9 +173,6 @@ class Future<void> : public FutureGeneric<void> | |||
208 | { | 173 | { |
209 | friend class Async::Private::ExecutorBase; | 174 | friend class Async::Private::ExecutorBase; |
210 | 175 | ||
211 | template<typename T_> | ||
212 | friend class Async::FutureWatcher; | ||
213 | |||
214 | public: | 176 | public: |
215 | Future() | 177 | Future() |
216 | : FutureGeneric<void>(Async::Private::ExecutionPtr()) | 178 | : FutureGeneric<void>(Async::Private::ExecutionPtr()) |
@@ -227,16 +189,38 @@ protected: | |||
227 | }; | 189 | }; |
228 | 190 | ||
229 | 191 | ||
192 | |||
193 | |||
194 | |||
230 | class FutureWatcherBase : public QObject | 195 | class FutureWatcherBase : public QObject |
231 | { | 196 | { |
232 | Q_OBJECT | 197 | Q_OBJECT |
233 | 198 | ||
199 | friend class FutureBase; | ||
200 | |||
201 | Q_SIGNALS: | ||
202 | void futureReady(); | ||
203 | void futureProgress(qreal progress); | ||
204 | |||
234 | protected: | 205 | protected: |
235 | FutureWatcherBase(QObject *parent = nullptr); | 206 | FutureWatcherBase(QObject *parent = nullptr); |
236 | virtual ~FutureWatcherBase(); | 207 | virtual ~FutureWatcherBase(); |
237 | 208 | ||
238 | Q_SIGNALS: | 209 | void futureReadyCallback(); |
239 | void futureReady(); | 210 | void futureProgressCallback(qreal progress); |
211 | |||
212 | void setFutureImpl(const Async::FutureBase &future); | ||
213 | |||
214 | protected: | ||
215 | class Private { | ||
216 | public: | ||
217 | Async::FutureBase future; | ||
218 | }; | ||
219 | |||
220 | Private * const d; | ||
221 | |||
222 | private: | ||
223 | Q_DISABLE_COPY(FutureWatcherBase); | ||
240 | }; | 224 | }; |
241 | 225 | ||
242 | template<typename T> | 226 | template<typename T> |
@@ -254,25 +238,16 @@ public: | |||
254 | 238 | ||
255 | void setFuture(const Async::Future<T> &future) | 239 | void setFuture(const Async::Future<T> &future) |
256 | { | 240 | { |
257 | mFuture = future; | 241 | setFutureImpl(*static_cast<const Async::FutureBase*>(&future)); |
258 | mFuture.addWatcher(this); | ||
259 | if (future.isFinished()) { | ||
260 | futureReadyCallback(); | ||
261 | } | ||
262 | } | 242 | } |
263 | 243 | ||
264 | Async::Future<T> future() const | 244 | Async::Future<T> future() const |
265 | { | 245 | { |
266 | return mFuture; | 246 | return *static_cast<Async::Future<T>*>(&d->future); |
267 | } | 247 | } |
268 | 248 | ||
269 | private: | 249 | private: |
270 | void futureReadyCallback() | 250 | Q_DISABLE_COPY(FutureWatcher<T>); |
271 | { | ||
272 | Q_EMIT futureReady(); | ||
273 | } | ||
274 | |||
275 | Async::Future<T> mFuture; | ||
276 | }; | 251 | }; |
277 | 252 | ||
278 | } // namespace Async | 253 | } // namespace Async |