diff options
author | Dan Vrátil <dvratil@redhat.com> | 2015-04-01 21:02:34 +0200 |
---|---|---|
committer | Dan Vrátil <dvratil@redhat.com> | 2015-04-01 21:19:48 +0200 |
commit | b01fadba903056218f2a00c5e62e1dc8df062124 (patch) | |
tree | adca72675973ab5d8253ab14ff94949824d6523e /async/src/future.h | |
parent | 94729eef71570e0b792a9afb95eeab7fd1eec56b (diff) | |
download | sink-b01fadba903056218f2a00c5e62e1dc8df062124.tar.gz sink-b01fadba903056218f2a00c5e62e1dc8df062124.zip |
Async: support (re-)executing single Job multiple times
Storing Future and current Job progress directly in Executors means
that we cannot re-execute finished job, or even execute the same Job
multiple times in parallel. To do so, we need to make Executors stateless
and track the state elsewhere.
This change does that by moving the execution state from Executor to Execution
class. Executors now only describe the tasks to execute, while Execution holds
the current state of execution. New Execution is created every time Job::exec()
is called.
Execution holds reference to it's result (Future) and Executor which created
the Execution. This ensures that Executor is not deleted when Job (which owns
Executors) goes out of scope while the execution is still running. At the same
time Future holds reference to relevant Execution, so that the Execution is
deleted when all copies of Future referring result from the respective Execution
are deleted.
Diffstat (limited to 'async/src/future.h')
-rw-r--r-- | async/src/future.h | 71 |
1 files changed, 63 insertions, 8 deletions
diff --git a/async/src/future.h b/async/src/future.h index b580b5a..cadd96d 100644 --- a/async/src/future.h +++ b/async/src/future.h | |||
@@ -29,8 +29,18 @@ class QEventLoop; | |||
29 | 29 | ||
30 | namespace Async { | 30 | namespace Async { |
31 | 31 | ||
32 | namespace Private { | ||
33 | class Execution; | ||
34 | class ExecutorBase; | ||
35 | |||
36 | typedef QSharedPointer<Execution> ExecutionPtr; | ||
37 | |||
38 | } | ||
39 | |||
32 | class FutureBase | 40 | class FutureBase |
33 | { | 41 | { |
42 | friend class Async::Private::Execution; | ||
43 | |||
34 | public: | 44 | public: |
35 | virtual ~FutureBase(); | 45 | virtual ~FutureBase(); |
36 | 46 | ||
@@ -39,6 +49,20 @@ public: | |||
39 | virtual void setError(int code = 1, const QString &message = QString()) = 0; | 49 | virtual void setError(int code = 1, const QString &message = QString()) = 0; |
40 | 50 | ||
41 | protected: | 51 | protected: |
52 | virtual void releaseExecution() = 0; | ||
53 | |||
54 | class PrivateBase : public QSharedData | ||
55 | { | ||
56 | public: | ||
57 | PrivateBase(const Async::Private::ExecutionPtr &execution); | ||
58 | virtual ~PrivateBase(); | ||
59 | |||
60 | void releaseExecution(); | ||
61 | |||
62 | private: | ||
63 | QWeakPointer<Async::Private::Execution> mExecution; | ||
64 | }; | ||
65 | |||
42 | FutureBase(); | 66 | FutureBase(); |
43 | FutureBase(const FutureBase &other); | 67 | FutureBase(const FutureBase &other); |
44 | }; | 68 | }; |
@@ -104,9 +128,9 @@ public: | |||
104 | } | 128 | } |
105 | 129 | ||
106 | protected: | 130 | protected: |
107 | FutureGeneric() | 131 | FutureGeneric(const Async::Private::ExecutionPtr &execution) |
108 | : FutureBase() | 132 | : FutureBase() |
109 | , d(new Private) | 133 | , d(new Private(execution)) |
110 | {} | 134 | {} |
111 | 135 | ||
112 | FutureGeneric(const FutureGeneric<T> &other) | 136 | FutureGeneric(const FutureGeneric<T> &other) |
@@ -114,10 +138,15 @@ protected: | |||
114 | , d(other.d) | 138 | , d(other.d) |
115 | {} | 139 | {} |
116 | 140 | ||
117 | class Private : public QSharedData | 141 | class Private : public FutureBase::PrivateBase |
118 | { | 142 | { |
119 | public: | 143 | public: |
120 | Private() : QSharedData(), finished(false), errorCode(0) {} | 144 | Private(const Async::Private::ExecutionPtr &execution) |
145 | : FutureBase::PrivateBase(execution) | ||
146 | , finished(false) | ||
147 | , errorCode(0) | ||
148 | {} | ||
149 | |||
121 | typename std::conditional<std::is_void<T>::value, int /* dummy */, T>::type | 150 | typename std::conditional<std::is_void<T>::value, int /* dummy */, T>::type |
122 | value; | 151 | value; |
123 | 152 | ||
@@ -129,6 +158,11 @@ protected: | |||
129 | 158 | ||
130 | QExplicitlySharedDataPointer<Private> d; | 159 | QExplicitlySharedDataPointer<Private> d; |
131 | 160 | ||
161 | void releaseExecution() | ||
162 | { | ||
163 | d->releaseExecution(); | ||
164 | } | ||
165 | |||
132 | void addWatcher(FutureWatcher<T> *watcher) | 166 | void addWatcher(FutureWatcher<T> *watcher) |
133 | { | 167 | { |
134 | d->watchers.append(QPointer<FutureWatcher<T>>(watcher)); | 168 | d->watchers.append(QPointer<FutureWatcher<T>>(watcher)); |
@@ -138,9 +172,14 @@ protected: | |||
138 | template<typename T> | 172 | template<typename T> |
139 | class Future : public FutureGeneric<T> | 173 | class Future : public FutureGeneric<T> |
140 | { | 174 | { |
175 | friend class Async::Private::ExecutorBase; | ||
176 | |||
177 | template<typename T_> | ||
178 | friend class Async::FutureWatcher; | ||
179 | |||
141 | public: | 180 | public: |
142 | Future() | 181 | Future() |
143 | : FutureGeneric<T>() | 182 | : FutureGeneric<T>(Async::Private::ExecutionPtr()) |
144 | {} | 183 | {} |
145 | 184 | ||
146 | Future(const Future<T> &other) | 185 | Future(const Future<T> &other) |
@@ -156,19 +195,35 @@ public: | |||
156 | { | 195 | { |
157 | return this->d->value; | 196 | return this->d->value; |
158 | } | 197 | } |
198 | |||
199 | protected: | ||
200 | Future(const Async::Private::ExecutionPtr &execution) | ||
201 | : FutureGeneric<T>(execution) | ||
202 | {} | ||
203 | |||
159 | }; | 204 | }; |
160 | 205 | ||
161 | template<> | 206 | template<> |
162 | class Future<void> : public FutureGeneric<void> | 207 | class Future<void> : public FutureGeneric<void> |
163 | { | 208 | { |
209 | friend class Async::Private::ExecutorBase; | ||
210 | |||
211 | template<typename T_> | ||
212 | friend class Async::FutureWatcher; | ||
213 | |||
164 | public: | 214 | public: |
165 | Future() | 215 | Future() |
166 | : FutureGeneric<void>() | 216 | : FutureGeneric<void>(Async::Private::ExecutionPtr()) |
167 | {} | 217 | {} |
168 | 218 | ||
169 | Future(const Future<void> &other) | 219 | Future(const Future<void> &other) |
170 | : FutureGeneric<void>(other) | 220 | : FutureGeneric<void>(other) |
171 | {} | 221 | {} |
222 | |||
223 | protected: | ||
224 | Future(const Async::Private::ExecutionPtr &execution) | ||
225 | : FutureGeneric<void>(execution) | ||
226 | {} | ||
172 | }; | 227 | }; |
173 | 228 | ||
174 | 229 | ||
@@ -177,7 +232,7 @@ class FutureWatcherBase : public QObject | |||
177 | Q_OBJECT | 232 | Q_OBJECT |
178 | 233 | ||
179 | protected: | 234 | protected: |
180 | FutureWatcherBase(QObject *parent = 0); | 235 | FutureWatcherBase(QObject *parent = nullptr); |
181 | virtual ~FutureWatcherBase(); | 236 | virtual ~FutureWatcherBase(); |
182 | 237 | ||
183 | Q_SIGNALS: | 238 | Q_SIGNALS: |
@@ -190,7 +245,7 @@ class FutureWatcher : public FutureWatcherBase | |||
190 | friend class Async::FutureGeneric<T>; | 245 | friend class Async::FutureGeneric<T>; |
191 | 246 | ||
192 | public: | 247 | public: |
193 | FutureWatcher(QObject *parent = 0) | 248 | FutureWatcher(QObject *parent = nullptr) |
194 | : FutureWatcherBase(parent) | 249 | : FutureWatcherBase(parent) |
195 | {} | 250 | {} |
196 | 251 | ||