diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-01-31 19:01:10 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-01-31 19:38:57 +0100 |
commit | a910706986aa8e83e070d23525c02649d80c05c3 (patch) | |
tree | d31cf91bdfbaf47ed750a744000327f0f8d45f2a /common/resultprovider.h | |
parent | 546d86aae7cd0b9766f3a0ea73f3777334d55814 (diff) | |
download | sink-a910706986aa8e83e070d23525c02649d80c05c3.tar.gz sink-a910706986aa8e83e070d23525c02649d80c05c3.zip |
Don't call into the model after the model has been destroyed.
Diffstat (limited to 'common/resultprovider.h')
-rw-r--r-- | common/resultprovider.h | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/common/resultprovider.h b/common/resultprovider.h index cda4dac..86138db 100644 --- a/common/resultprovider.h +++ b/common/resultprovider.h | |||
@@ -22,6 +22,8 @@ | |||
22 | 22 | ||
23 | #include <functional> | 23 | #include <functional> |
24 | #include <memory> | 24 | #include <memory> |
25 | #include <QMutexLocker> | ||
26 | #include <QPointer> | ||
25 | 27 | ||
26 | namespace Sink { | 28 | namespace Sink { |
27 | 29 | ||
@@ -82,21 +84,21 @@ public: | |||
82 | void add(const T &value) | 84 | void add(const T &value) |
83 | { | 85 | { |
84 | if (auto strongRef = mResultEmitter.toStrongRef()) { | 86 | if (auto strongRef = mResultEmitter.toStrongRef()) { |
85 | strongRef->addHandler(value); | 87 | strongRef->add(value); |
86 | } | 88 | } |
87 | } | 89 | } |
88 | 90 | ||
89 | void modify(const T &value) | 91 | void modify(const T &value) |
90 | { | 92 | { |
91 | if (auto strongRef = mResultEmitter.toStrongRef()) { | 93 | if (auto strongRef = mResultEmitter.toStrongRef()) { |
92 | strongRef->modifyHandler(value); | 94 | strongRef->modify(value); |
93 | } | 95 | } |
94 | } | 96 | } |
95 | 97 | ||
96 | void remove(const T &value) | 98 | void remove(const T &value) |
97 | { | 99 | { |
98 | if (auto strongRef = mResultEmitter.toStrongRef()) { | 100 | if (auto strongRef = mResultEmitter.toStrongRef()) { |
99 | strongRef->removeHandler(value); | 101 | strongRef->remove(value); |
100 | } | 102 | } |
101 | } | 103 | } |
102 | 104 | ||
@@ -194,6 +196,15 @@ public: | |||
194 | 196 | ||
195 | virtual ~ResultEmitter() | 197 | virtual ~ResultEmitter() |
196 | { | 198 | { |
199 | //Try locking in case we're in the middle of an execution in another thread | ||
200 | QMutexLocker locker{&mMutex}; | ||
201 | } | ||
202 | |||
203 | virtual void waitForMethodExecutionEnd() | ||
204 | { | ||
205 | //If we're in the middle of a method execution, this will block until the method is done. | ||
206 | QMutexLocker locker{&mMutex}; | ||
207 | mDone = true; | ||
197 | } | 208 | } |
198 | 209 | ||
199 | void onAdded(const std::function<void(const DomainType &)> &handler) | 210 | void onAdded(const std::function<void(const DomainType &)> &handler) |
@@ -226,38 +237,55 @@ public: | |||
226 | clearHandler = handler; | 237 | clearHandler = handler; |
227 | } | 238 | } |
228 | 239 | ||
240 | bool guardOk() | ||
241 | { | ||
242 | return !mDone; | ||
243 | } | ||
244 | |||
229 | void add(const DomainType &value) | 245 | void add(const DomainType &value) |
230 | { | 246 | { |
231 | addHandler(value); | 247 | QMutexLocker locker{&mMutex}; |
248 | if (guardOk()) { | ||
249 | addHandler(value); | ||
250 | } | ||
232 | } | 251 | } |
233 | 252 | ||
234 | void modify(const DomainType &value) | 253 | void modify(const DomainType &value) |
235 | { | 254 | { |
236 | modifyHandler(value); | 255 | QMutexLocker locker{&mMutex}; |
256 | if (guardOk()) { | ||
257 | modifyHandler(value); | ||
258 | } | ||
237 | } | 259 | } |
238 | 260 | ||
239 | void remove(const DomainType &value) | 261 | void remove(const DomainType &value) |
240 | { | 262 | { |
241 | removeHandler(value); | 263 | QMutexLocker locker{&mMutex}; |
264 | if (guardOk()) { | ||
265 | removeHandler(value); | ||
266 | } | ||
242 | } | 267 | } |
243 | 268 | ||
244 | void initialResultSetComplete(const DomainType &parent, bool replayedAll) | 269 | void initialResultSetComplete(const DomainType &parent, bool replayedAll) |
245 | { | 270 | { |
246 | if (initialResultSetCompleteHandler) { | 271 | QMutexLocker locker{&mMutex}; |
272 | if (initialResultSetCompleteHandler && guardOk()) { | ||
247 | initialResultSetCompleteHandler(parent, replayedAll); | 273 | initialResultSetCompleteHandler(parent, replayedAll); |
248 | } | 274 | } |
249 | } | 275 | } |
250 | 276 | ||
251 | void complete() | 277 | void complete() |
252 | { | 278 | { |
253 | if (completeHandler) { | 279 | QMutexLocker locker{&mMutex}; |
280 | if (completeHandler && guardOk()) { | ||
254 | completeHandler(); | 281 | completeHandler(); |
255 | } | 282 | } |
256 | } | 283 | } |
257 | 284 | ||
258 | void clear() | 285 | void clear() |
259 | { | 286 | { |
260 | if (clearHandler) { | 287 | QMutexLocker locker{&mMutex}; |
288 | if (clearHandler && guardOk()) { | ||
261 | clearHandler(); | 289 | clearHandler(); |
262 | } | 290 | } |
263 | } | 291 | } |
@@ -285,6 +313,8 @@ private: | |||
285 | std::function<void(void)> clearHandler; | 313 | std::function<void(void)> clearHandler; |
286 | 314 | ||
287 | std::function<void(const DomainType &parent)> mFetcher; | 315 | std::function<void(const DomainType &parent)> mFetcher; |
316 | QMutex mMutex; | ||
317 | bool mDone = false; | ||
288 | }; | 318 | }; |
289 | 319 | ||
290 | template <class DomainType> | 320 | template <class DomainType> |
@@ -293,6 +323,18 @@ class AggregatingResultEmitter : public ResultEmitter<DomainType> | |||
293 | public: | 323 | public: |
294 | typedef QSharedPointer<AggregatingResultEmitter<DomainType>> Ptr; | 324 | typedef QSharedPointer<AggregatingResultEmitter<DomainType>> Ptr; |
295 | 325 | ||
326 | ~AggregatingResultEmitter() | ||
327 | { | ||
328 | } | ||
329 | |||
330 | virtual void waitForMethodExecutionEnd() Q_DECL_OVERRIDE | ||
331 | { | ||
332 | for (const auto &emitter : mEmitter) { | ||
333 | emitter->waitForMethodExecutionEnd(); | ||
334 | } | ||
335 | ResultEmitter<DomainType>::waitForMethodExecutionEnd(); | ||
336 | } | ||
337 | |||
296 | void addEmitter(const typename ResultEmitter<DomainType>::Ptr &emitter) | 338 | void addEmitter(const typename ResultEmitter<DomainType>::Ptr &emitter) |
297 | { | 339 | { |
298 | Q_ASSERT(emitter); | 340 | Q_ASSERT(emitter); |