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.h137
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
25class QEventLoop; 25class QEventLoop;
26 26
27#include <type_traits>
28
29#include <QSharedDataPointer>
30#include <QPointer>
31#include <QVector>
32
27namespace Async { 33namespace Async {
28 34
29class FutureBase 35class FutureBase
30{ 36{
31public: 37public:
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
40protected: 43protected:
44 FutureBase();
45 FutureBase(const FutureBase &other);
46
41 bool mFinished; 47 bool mFinished;
42 QEventLoop *mWaitLoop; 48 QEventLoop *mWaitLoop;
43}; 49};
44 50
45template<typename T> 51template<typename T>
46class Future : public FutureBase 52class FutureWatcher;
53
54template<typename T>
55class FutureGeneric : public FutureBase
47{ 56{
57 friend class FutureWatcher<T>;
58
48public: 59public:
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
70protected:
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
98template<typename T>
99class Future : public FutureGeneric<T>
100{
101public:
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
73private:
74 T mValue;
75}; 119};
76 120
77template<> 121template<>
78class Future<void> : public FutureBase 122class Future<void> : public FutureGeneric<void>
79{ 123{
80public: 124public:
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
135class FutureWatcherBase : public QObject
136{
137 Q_OBJECT
138
139protected:
140 FutureWatcherBase(QObject *parent = 0);
141 virtual ~FutureWatcherBase();
142
143Q_SIGNALS:
144 void futureReady();
145};
146
147template<typename T>
148class FutureWatcher : public FutureWatcherBase
149{
150 friend class Async::FutureGeneric<T>;
151
152public:
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
174private:
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