diff options
Diffstat (limited to 'async/src/future.h')
-rw-r--r-- | async/src/future.h | 137 |
1 files changed, 115 insertions, 22 deletions
diff --git a/async/src/future.h b/async/src/future.h index eb3de1e..39e3936 100644 --- a/async/src/future.h +++ b/async/src/future.h | |||
@@ -24,67 +24,160 @@ | |||
24 | 24 | ||
25 | class QEventLoop; | 25 | class QEventLoop; |
26 | 26 | ||
27 | #include <type_traits> | ||
28 | |||
29 | #include <QSharedDataPointer> | ||
30 | #include <QPointer> | ||
31 | #include <QVector> | ||
32 | |||
27 | namespace Async { | 33 | namespace Async { |
28 | 34 | ||
29 | class FutureBase | 35 | class FutureBase |
30 | { | 36 | { |
31 | public: | 37 | public: |
32 | FutureBase(); | ||
33 | FutureBase(const FutureBase &other); | ||
34 | virtual ~FutureBase(); | 38 | virtual ~FutureBase(); |
35 | 39 | ||
36 | void setFinished(); | 40 | virtual void setFinished() = 0; |
37 | bool isFinished() const; | 41 | bool isFinished() const; |
38 | void waitForFinished(); | ||
39 | 42 | ||
40 | protected: | 43 | protected: |
44 | FutureBase(); | ||
45 | FutureBase(const FutureBase &other); | ||
46 | |||
41 | bool mFinished; | 47 | bool mFinished; |
42 | QEventLoop *mWaitLoop; | 48 | QEventLoop *mWaitLoop; |
43 | }; | 49 | }; |
44 | 50 | ||
45 | template<typename T> | 51 | template<typename T> |
46 | class Future : public FutureBase | 52 | class FutureWatcher; |
53 | |||
54 | template<typename T> | ||
55 | class FutureGeneric : public FutureBase | ||
47 | { | 56 | { |
57 | friend class FutureWatcher<T>; | ||
58 | |||
48 | public: | 59 | public: |
49 | Future() | 60 | void setFinished() |
50 | : FutureBase() | 61 | { |
62 | mFinished = true; | ||
63 | for (auto watcher : d->watchers) { | ||
64 | if (watcher) { | ||
65 | watcher->futureReadyCallback(); | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | protected: | ||
71 | FutureGeneric() | ||
72 | : FutureBase() | ||
73 | , d(new Private) | ||
51 | {} | 74 | {} |
52 | 75 | ||
53 | Future(const Future<T> &other) | 76 | FutureGeneric(const FutureGeneric<T> &other) |
54 | : FutureBase(other) | 77 | : FutureBase(other) |
55 | , mValue(other.mValue) | 78 | , d(other.d) |
79 | {} | ||
80 | |||
81 | class Private : public QSharedData | ||
82 | { | ||
83 | public: | ||
84 | typename std::conditional<std::is_void<T>::value, int /* dummy */, T>::type | ||
85 | value; | ||
86 | |||
87 | QVector<QPointer<FutureWatcher<T>>> watchers; | ||
88 | }; | ||
89 | |||
90 | QExplicitlySharedDataPointer<Private> d; | ||
91 | |||
92 | void addWatcher(FutureWatcher<T> *watcher) | ||
93 | { | ||
94 | d->watchers.append(QPointer<FutureWatcher<T>>(watcher)); | ||
95 | } | ||
96 | }; | ||
97 | |||
98 | template<typename T> | ||
99 | class Future : public FutureGeneric<T> | ||
100 | { | ||
101 | public: | ||
102 | Future() | ||
103 | : FutureGeneric<T>() | ||
56 | {} | 104 | {} |
57 | 105 | ||
58 | Future(const T &val) | 106 | Future(const Future<T> &other) |
59 | : FutureBase() | 107 | : FutureGeneric<T>(other) |
60 | , mValue(val) | ||
61 | {} | 108 | {} |
62 | 109 | ||
63 | void setValue(const T &val) | 110 | void setValue(const T &value) |
64 | { | 111 | { |
65 | mValue = val; | 112 | this->d->value = value; |
66 | } | 113 | } |
67 | 114 | ||
68 | T value() const | 115 | T value() const |
69 | { | 116 | { |
70 | return mValue; | 117 | return this->d->value; |
71 | } | 118 | } |
72 | |||
73 | private: | ||
74 | T mValue; | ||
75 | }; | 119 | }; |
76 | 120 | ||
77 | template<> | 121 | template<> |
78 | class Future<void> : public FutureBase | 122 | class Future<void> : public FutureGeneric<void> |
79 | { | 123 | { |
80 | public: | 124 | public: |
81 | Future() | 125 | Future() |
82 | : FutureBase() | 126 | : FutureGeneric<void>() |
83 | {} | 127 | {} |
84 | 128 | ||
85 | Future(const Future<void> &other) | 129 | Future(const Future<void> &other) |
86 | : FutureBase(other) | 130 | : FutureGeneric<void>(other) |
131 | {} | ||
132 | }; | ||
133 | |||
134 | |||
135 | class FutureWatcherBase : public QObject | ||
136 | { | ||
137 | Q_OBJECT | ||
138 | |||
139 | protected: | ||
140 | FutureWatcherBase(QObject *parent = 0); | ||
141 | virtual ~FutureWatcherBase(); | ||
142 | |||
143 | Q_SIGNALS: | ||
144 | void futureReady(); | ||
145 | }; | ||
146 | |||
147 | template<typename T> | ||
148 | class FutureWatcher : public FutureWatcherBase | ||
149 | { | ||
150 | friend class Async::FutureGeneric<T>; | ||
151 | |||
152 | public: | ||
153 | FutureWatcher(QObject *parent = 0) | ||
154 | : FutureWatcherBase(parent) | ||
155 | {} | ||
156 | |||
157 | ~FutureWatcher() | ||
87 | {} | 158 | {} |
159 | |||
160 | void setFuture(const Async::Future<T> &future) | ||
161 | { | ||
162 | mFuture = future; | ||
163 | mFuture.addWatcher(this); | ||
164 | if (future.isFinished()) { | ||
165 | futureReadyCallback(); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | Async::Future<T> future() const | ||
170 | { | ||
171 | return mFuture; | ||
172 | } | ||
173 | |||
174 | private: | ||
175 | void futureReadyCallback() | ||
176 | { | ||
177 | Q_EMIT futureReady(); | ||
178 | } | ||
179 | |||
180 | Async::Future<T> mFuture; | ||
88 | }; | 181 | }; |
89 | 182 | ||
90 | } // namespace Async | 183 | } // namespace Async |