summaryrefslogtreecommitdiffstats
path: root/async/src/future.h
diff options
context:
space:
mode:
Diffstat (limited to 'async/src/future.h')
-rw-r--r--async/src/future.h145
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
30namespace Async { 30namespace Async {
31 31
32class FutureWatcherBase;
33template<typename T>
34class FutureWatcher;
35
32namespace Private { 36namespace Private {
33class Execution; 37class Execution;
34class ExecutorBase; 38class ExecutorBase;
35 39
36typedef QSharedPointer<Execution> ExecutionPtr; 40typedef QSharedPointer<Execution> ExecutionPtr;
37 41} // namespace Private
38}
39 42
40class FutureBase 43class FutureBase
41{ 44{
42 friend class Async::Private::Execution; 45 friend class Async::Private::Execution;
46 friend class FutureWatcherBase;
43 47
44public: 48public:
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
51protected: 57 void setProgress(qreal progress);
52 virtual void releaseExecution() = 0; 58 void setProgress(int processed, int total);
53 59
60protected:
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
85protected:
86 QExplicitlySharedDataPointer<PrivateBase> d;
68}; 87};
69 88
70template<typename T> 89template<typename T>
@@ -79,42 +98,7 @@ class FutureGeneric : public FutureBase
79 friend class FutureWatcher<T>; 98 friend class FutureWatcher<T>;
80 99
81public: 100public:
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
130protected: 114protected:
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
123protected:
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
172template<typename T> 137template<typename T>
173class Future : public FutureGeneric<T> 138class 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
199protected: 164protected:
@@ -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
214public: 176public:
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
230class FutureWatcherBase : public QObject 195class FutureWatcherBase : public QObject
231{ 196{
232 Q_OBJECT 197 Q_OBJECT
233 198
199 friend class FutureBase;
200
201Q_SIGNALS:
202 void futureReady();
203 void futureProgress(qreal progress);
204
234protected: 205protected:
235 FutureWatcherBase(QObject *parent = nullptr); 206 FutureWatcherBase(QObject *parent = nullptr);
236 virtual ~FutureWatcherBase(); 207 virtual ~FutureWatcherBase();
237 208
238Q_SIGNALS: 209 void futureReadyCallback();
239 void futureReady(); 210 void futureProgressCallback(qreal progress);
211
212 void setFutureImpl(const Async::FutureBase &future);
213
214protected:
215 class Private {
216 public:
217 Async::FutureBase future;
218 };
219
220 Private * const d;
221
222private:
223 Q_DISABLE_COPY(FutureWatcherBase);
240}; 224};
241 225
242template<typename T> 226template<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
269private: 249private:
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