summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--async/src/future.cpp92
-rw-r--r--async/src/future.h136
2 files changed, 135 insertions, 93 deletions
diff --git a/async/src/future.cpp b/async/src/future.cpp
index 50a326a..970060b 100644
--- a/async/src/future.cpp
+++ b/async/src/future.cpp
@@ -20,11 +20,41 @@
20 20
21using namespace Async; 21using namespace Async;
22 22
23FutureBase::PrivateBase::PrivateBase(const Private::ExecutionPtr &execution)
24 : finished(false)
25 , errorCode(0)
26 , mExecution(execution)
27{
28}
29
30FutureBase::PrivateBase::~PrivateBase()
31{
32 Private::ExecutionPtr executionPtr = mExecution.toStrongRef();
33 if (executionPtr) {
34 executionPtr->releaseFuture();
35 releaseExecution();
36 }
37}
38
39void FutureBase::PrivateBase::releaseExecution()
40{
41 mExecution.clear();
42}
43
44
45
23FutureBase::FutureBase() 46FutureBase::FutureBase()
47 : d(nullptr)
48{
49}
50
51FutureBase::FutureBase(FutureBase::PrivateBase *dd)
52 : d(dd)
24{ 53{
25} 54}
26 55
27FutureBase::FutureBase(const Async::FutureBase &other) 56FutureBase::FutureBase(const Async::FutureBase &other)
57 : d(other.d)
28{ 58{
29} 59}
30 60
@@ -32,35 +62,77 @@ FutureBase::~FutureBase()
32{ 62{
33} 63}
34 64
35FutureBase::PrivateBase::PrivateBase(const Private::ExecutionPtr &execution) 65void FutureBase::releaseExecution()
36 : mExecution(execution)
37{ 66{
67 d->releaseExecution();
38} 68}
39 69
40FutureBase::PrivateBase::~PrivateBase() 70void FutureBase::setFinished()
41{ 71{
42 Private::ExecutionPtr executionPtr = mExecution.toStrongRef(); 72 if (isFinished()) {
43 if (executionPtr) { 73 return;
44 executionPtr->releaseFuture(); 74 }
45 releaseExecution(); 75 d->finished = true;
76 for (auto watcher : d->watchers) {
77 if (watcher) {
78 watcher->futureReadyCallback();
79 }
46 } 80 }
47} 81}
48 82
49void FutureBase::PrivateBase::releaseExecution() 83bool FutureBase::isFinished() const
50{ 84{
51 mExecution.clear(); 85 return d->finished;
86}
87
88void FutureBase::setError(int code, const QString &message)
89{
90 d->errorCode = code;
91 d->errorMessage = message;
92 setFinished();
93}
94
95int FutureBase::errorCode() const
96{
97 return d->errorCode;
98}
99
100QString FutureBase::errorMessage() const
101{
102 return d->errorMessage;
52} 103}
53 104
54 105
106void FutureBase::addWatcher(FutureWatcherBase* watcher)
107{
108 d->watchers.append(QPointer<FutureWatcherBase>(watcher));
109}
110
111
112
113
55 114
56FutureWatcherBase::FutureWatcherBase(QObject *parent) 115FutureWatcherBase::FutureWatcherBase(QObject *parent)
57 : QObject(parent) 116 : QObject(parent)
117 , d(new FutureWatcherBase::Private)
58{ 118{
59} 119}
60 120
61FutureWatcherBase::~FutureWatcherBase() 121FutureWatcherBase::~FutureWatcherBase()
62{ 122{
123 delete d;
63} 124}
64 125
126void FutureWatcherBase::futureReadyCallback()
127{
128 Q_EMIT futureReady();
129}
65 130
66#include "future.moc" 131void FutureWatcherBase::setFutureImpl(const FutureBase &future)
132{
133 d->future = future;
134 d->future.addWatcher(this);
135 if (future.isFinished()) {
136 futureReadyCallback();
137 }
138}
diff --git a/async/src/future.h b/async/src/future.h
index cadd96d..bc18f00 100644
--- a/async/src/future.h
+++ b/async/src/future.h
@@ -29,28 +29,32 @@ 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: 57protected:
52 virtual void releaseExecution() = 0;
53
54 class PrivateBase : public QSharedData 58 class PrivateBase : public QSharedData
55 { 59 {
56 public: 60 public:
@@ -59,12 +63,24 @@ protected:
59 63
60 void releaseExecution(); 64 void releaseExecution();
61 65
66 bool finished;
67 int errorCode;
68 QString errorMessage;
69
70 QVector<QPointer<FutureWatcherBase>> watchers;
62 private: 71 private:
63 QWeakPointer<Async::Private::Execution> mExecution; 72 QWeakPointer<Async::Private::Execution> mExecution;
64 }; 73 };
65 74
66 FutureBase(); 75 FutureBase();
76 FutureBase(FutureBase::PrivateBase *dd);
67 FutureBase(const FutureBase &other); 77 FutureBase(const FutureBase &other);
78
79 void addWatcher(Async::FutureWatcherBase *watcher);
80 void releaseExecution();
81
82protected:
83 QExplicitlySharedDataPointer<PrivateBase> d;
68}; 84};
69 85
70template<typename T> 86template<typename T>
@@ -79,41 +95,6 @@ class FutureGeneric : public FutureBase
79 friend class FutureWatcher<T>; 95 friend class FutureWatcher<T>;
80 96
81public: 97public:
82 void setFinished()
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() 98 void waitForFinished()
118 { 99 {
119 if (isFinished()) { 100 if (isFinished()) {
@@ -129,46 +110,27 @@ public:
129 110
130protected: 111protected:
131 FutureGeneric(const Async::Private::ExecutionPtr &execution) 112 FutureGeneric(const Async::Private::ExecutionPtr &execution)
132 : FutureBase() 113 : FutureBase(new Private(execution))
133 , d(new Private(execution))
134 {} 114 {}
135 115
136 FutureGeneric(const FutureGeneric<T> &other) 116 FutureGeneric(const FutureGeneric<T> &other)
137 : FutureBase(other) 117 : FutureBase(other)
138 , d(other.d)
139 {} 118 {}
140 119
120protected:
141 class Private : public FutureBase::PrivateBase 121 class Private : public FutureBase::PrivateBase
142 { 122 {
143 public: 123 public:
144 Private(const Async::Private::ExecutionPtr &execution) 124 Private(const Async::Private::ExecutionPtr &execution)
145 : FutureBase::PrivateBase(execution) 125 : FutureBase::PrivateBase(execution)
146 , finished(false)
147 , errorCode(0)
148 {} 126 {}
149 127
150 typename std::conditional<std::is_void<T>::value, int /* dummy */, T>::type 128 typename std::conditional<std::is_void<T>::value, int /* dummy */, T>::type
151 value; 129 value;
152
153 QVector<QPointer<FutureWatcher<T>>> watchers;
154 bool finished;
155 int errorCode;
156 QString errorMessage;
157 }; 130 };
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}; 131};
171 132
133
172template<typename T> 134template<typename T>
173class Future : public FutureGeneric<T> 135class Future : public FutureGeneric<T>
174{ 136{
@@ -188,12 +150,12 @@ public:
188 150
189 void setValue(const T &value) 151 void setValue(const T &value)
190 { 152 {
191 this->d->value = value; 153 static_cast<typename FutureGeneric<T>::Private*>(this->d.data())->value = value;
192 } 154 }
193 155
194 T value() const 156 T value() const
195 { 157 {
196 return this->d->value; 158 return static_cast<typename FutureGeneric<T>::Private*>(this->d.data())->value;
197 } 159 }
198 160
199protected: 161protected:
@@ -208,9 +170,6 @@ class Future<void> : public FutureGeneric<void>
208{ 170{
209 friend class Async::Private::ExecutorBase; 171 friend class Async::Private::ExecutorBase;
210 172
211 template<typename T_>
212 friend class Async::FutureWatcher;
213
214public: 173public:
215 Future() 174 Future()
216 : FutureGeneric<void>(Async::Private::ExecutionPtr()) 175 : FutureGeneric<void>(Async::Private::ExecutionPtr())
@@ -227,16 +186,36 @@ protected:
227}; 186};
228 187
229 188
189
190
191
230class FutureWatcherBase : public QObject 192class FutureWatcherBase : public QObject
231{ 193{
232 Q_OBJECT 194 Q_OBJECT
233 195
196 friend class FutureBase;
197
198Q_SIGNALS:
199 void futureReady();
200
234protected: 201protected:
235 FutureWatcherBase(QObject *parent = nullptr); 202 FutureWatcherBase(QObject *parent = nullptr);
236 virtual ~FutureWatcherBase(); 203 virtual ~FutureWatcherBase();
237 204
238Q_SIGNALS: 205 void futureReadyCallback();
239 void futureReady(); 206
207 void setFutureImpl(const Async::FutureBase &future);
208
209protected:
210 class Private {
211 public:
212 Async::FutureBase future;
213 };
214
215 Private * const d;
216
217private:
218 Q_DISABLE_COPY(FutureWatcherBase);
240}; 219};
241 220
242template<typename T> 221template<typename T>
@@ -254,25 +233,16 @@ public:
254 233
255 void setFuture(const Async::Future<T> &future) 234 void setFuture(const Async::Future<T> &future)
256 { 235 {
257 mFuture = future; 236 setFutureImpl(*static_cast<const Async::FutureBase*>(&future));
258 mFuture.addWatcher(this);
259 if (future.isFinished()) {
260 futureReadyCallback();
261 }
262 } 237 }
263 238
264 Async::Future<T> future() const 239 Async::Future<T> future() const
265 { 240 {
266 return mFuture; 241 return *static_cast<Async::Future<T>*>(&d->future);
267 } 242 }
268 243
269private: 244private:
270 void futureReadyCallback() 245 Q_DISABLE_COPY(FutureWatcher<T>);
271 {
272 Q_EMIT futureReady();
273 }
274
275 Async::Future<T> mFuture;
276}; 246};
277 247
278} // namespace Async 248} // namespace Async