diff options
Diffstat (limited to 'async')
-rw-r--r-- | async/autotests/asynctest.cpp | 50 | ||||
-rw-r--r-- | async/src/async.h | 44 |
2 files changed, 72 insertions, 22 deletions
diff --git a/async/autotests/asynctest.cpp b/async/autotests/asynctest.cpp index 403fb83..7aedfc4 100644 --- a/async/autotests/asynctest.cpp +++ b/async/autotests/asynctest.cpp | |||
@@ -41,6 +41,7 @@ private Q_SLOTS: | |||
41 | void testSyncPromises(); | 41 | void testSyncPromises(); |
42 | void testAsyncPromises(); | 42 | void testAsyncPromises(); |
43 | void testSyncEach(); | 43 | void testSyncEach(); |
44 | void testSyncReduce(); | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | void AsyncTest::testSyncPromises() | 47 | void AsyncTest::testSyncPromises() |
@@ -65,27 +66,29 @@ void AsyncTest::testSyncPromises() | |||
65 | job.exec(); | 66 | job.exec(); |
66 | Async::Future<QString> future = job.result(); | 67 | Async::Future<QString> future = job.result(); |
67 | 68 | ||
69 | QVERIFY(future.isFinished()); | ||
68 | QCOMPARE(future.value(), QString::fromLatin1("RESULT IS 42")); | 70 | QCOMPARE(future.value(), QString::fromLatin1("RESULT IS 42")); |
69 | } | 71 | } |
70 | 72 | ||
71 | void AsyncTest::testAsyncPromises() | 73 | void AsyncTest::testAsyncPromises() |
72 | { | 74 | { |
73 | auto job = Async::start<int>( | 75 | auto job = Async::start<int>( |
74 | [](Async::Future<int> &future) { | 76 | [](Async::Future<int> &future) { |
75 | QTimer *timer = new QTimer(); | 77 | QTimer *timer = new QTimer(); |
76 | QObject::connect(timer, &QTimer::timeout, | 78 | QObject::connect(timer, &QTimer::timeout, |
77 | [&]() { | 79 | [&]() { |
78 | future.setValue(42); | 80 | future.setValue(42); |
79 | future.setFinished(); | 81 | future.setFinished(); |
80 | }); | 82 | }); |
81 | QObject::connect(timer, &QTimer::timeout, | 83 | QObject::connect(timer, &QTimer::timeout, |
82 | timer, &QObject::deleteLater); | 84 | timer, &QObject::deleteLater); |
83 | timer->setSingleShot(true); | 85 | timer->setSingleShot(true); |
84 | timer->start(200); | 86 | timer->start(200); |
85 | }); | 87 | }); |
86 | 88 | ||
87 | job.exec(); | 89 | job.exec(); |
88 | Async::Future<int> future = job.result(); | 90 | Async::Future<int> future = job.result(); |
91 | QVERIFY(future.isFinished()); | ||
89 | QCOMPARE(future.value(), 42); | 92 | QCOMPARE(future.value(), 42); |
90 | } | 93 | } |
91 | 94 | ||
@@ -105,9 +108,32 @@ void AsyncTest::testSyncEach() | |||
105 | job.exec(); | 108 | job.exec(); |
106 | Async::Future<QList<int>> future = job.result(); | 109 | Async::Future<QList<int>> future = job.result(); |
107 | const QList<int> expected({ 2, 3, 4, 5 }); | 110 | const QList<int> expected({ 2, 3, 4, 5 }); |
111 | QVERIFY(future.isFinished()); | ||
108 | QCOMPARE(future.value(), expected); | 112 | QCOMPARE(future.value(), expected); |
109 | } | 113 | } |
110 | 114 | ||
115 | void AsyncTest::testSyncReduce() | ||
116 | { | ||
117 | auto job = Async::start<QList<int>>( | ||
118 | [](Async::Future<QList<int>> &future) { | ||
119 | future.setValue(QList<int>{ 1, 2, 3, 4 }); | ||
120 | future.setFinished(); | ||
121 | }) | ||
122 | .reduce<int, QList<int>>( | ||
123 | [](const QList<int> &list, Async::Future<int> &future) { | ||
124 | int sum = 0; | ||
125 | for (int i : list) sum += i; | ||
126 | future.setValue(sum); | ||
127 | future.setFinished(); | ||
128 | }); | ||
129 | |||
130 | job.exec(); | ||
131 | Async::Future<int> future = job.result(); | ||
132 | QVERIFY(future.isFinished()); | ||
133 | QCOMPARE(future.value(), 10); | ||
134 | } | ||
135 | |||
136 | |||
111 | 137 | ||
112 | QTEST_MAIN(AsyncTest); | 138 | QTEST_MAIN(AsyncTest); |
113 | 139 | ||
diff --git a/async/src/async.h b/async/src/async.h index 0f027f5..a976fa2 100644 --- a/async/src/async.h +++ b/async/src/async.h | |||
@@ -80,10 +80,6 @@ template<typename Out, typename ... In> | |||
80 | class ThenExecutor: public Executor | 80 | class ThenExecutor: public Executor |
81 | { | 81 | { |
82 | 82 | ||
83 | typedef Out OutType; | ||
84 | typedef typename std::tuple_element<0, std::tuple<In ..., void>>::type InType; | ||
85 | |||
86 | |||
87 | public: | 83 | public: |
88 | ThenExecutor(ThenTask<Out, In ...> then, Executor *parent = nullptr) | 84 | ThenExecutor(ThenTask<Out, In ...> then, Executor *parent = nullptr) |
89 | : Executor(parent) | 85 | : Executor(parent) |
@@ -93,10 +89,12 @@ public: | |||
93 | 89 | ||
94 | void exec() | 90 | void exec() |
95 | { | 91 | { |
96 | Async::Future<InType> *in = 0; | 92 | typedef typename std::tuple_element<0, std::tuple<In ..., void>>::type PrevOut; |
93 | |||
94 | Async::Future<PrevOut> *in = 0; | ||
97 | if (mPrev) { | 95 | if (mPrev) { |
98 | mPrev->exec(); | 96 | mPrev->exec(); |
99 | in = static_cast<Async::Future<InType>*>(mPrev->result()); | 97 | in = static_cast<Async::Future<PrevOut>*>(mPrev->result()); |
100 | assert(in->isFinished()); | 98 | assert(in->isFinished()); |
101 | } | 99 | } |
102 | 100 | ||
@@ -133,6 +131,7 @@ public: | |||
133 | future.waitForFinished(); | 131 | future.waitForFinished(); |
134 | out->setValue(out->value() + future.value()); | 132 | out->setValue(out->value() + future.value()); |
135 | } | 133 | } |
134 | out->setFinished(); | ||
136 | 135 | ||
137 | mResult = out; | 136 | mResult = out; |
138 | } | 137 | } |
@@ -141,6 +140,32 @@ private: | |||
141 | std::function<void(const In&, Async::Future<Out>&)> mFunc; | 140 | std::function<void(const In&, Async::Future<Out>&)> mFunc; |
142 | }; | 141 | }; |
143 | 142 | ||
143 | template<typename Out, typename In> | ||
144 | class ReduceExecutor : public Executor | ||
145 | { | ||
146 | public: | ||
147 | ReduceExecutor(ReduceTask<Out, In> reduce, Executor *parent = nullptr) | ||
148 | : Executor(parent) | ||
149 | , mFunc(reduce) | ||
150 | { | ||
151 | } | ||
152 | |||
153 | void exec() | ||
154 | { | ||
155 | assert(mPrev); | ||
156 | mPrev->exec(); | ||
157 | Async::Future<In> *in = static_cast<Async::Future<In>*>(mPrev->result()); | ||
158 | |||
159 | auto out = new Async::Future<Out>(); | ||
160 | mFunc(in->value(), *out); | ||
161 | out->waitForFinished(); | ||
162 | mResult = out; | ||
163 | } | ||
164 | |||
165 | private: | ||
166 | std::function<void(const In &, Async::Future<Out> &)> mFunc; | ||
167 | }; | ||
168 | |||
144 | class JobBase | 169 | class JobBase |
145 | { | 170 | { |
146 | template<typename Out, typename ... In> | 171 | template<typename Out, typename ... In> |
@@ -187,8 +212,8 @@ public: | |||
187 | Job<OutOther, InOther> reduce(ReduceTask<OutOther, InOther> func) | 212 | Job<OutOther, InOther> reduce(ReduceTask<OutOther, InOther> func) |
188 | { | 213 | { |
189 | static_assert(Async::detail::isIterable<Out>::value, | 214 | static_assert(Async::detail::isIterable<Out>::value, |
190 | "The result type of 'Reduce' task must be a list or an array."); | 215 | "The 'Result' task can only be connected to a job that returns a list or array"); |
191 | //return Job<Out_, In_>::create(func, new ReduceEx, this); | 216 | return Job<OutOther, InOther>(new ReduceExecutor<OutOther, InOther>(func, mExecutor)); |
192 | } | 217 | } |
193 | 218 | ||
194 | Async::Future<Out> result() const | 219 | Async::Future<Out> result() const |
@@ -212,8 +237,7 @@ private: | |||
212 | template<typename Out, typename ... In> | 237 | template<typename Out, typename ... In> |
213 | Async::Job<Out, In ...> Async::start(ThenTask<Out, In ...> func) | 238 | Async::Job<Out, In ...> Async::start(ThenTask<Out, In ...> func) |
214 | { | 239 | { |
215 | Executor *exec = new ThenExecutor<Out, In ...>(func); | 240 | return Job<Out, In ...>(new ThenExecutor<Out, In ...>(func)); |
216 | return Job<Out, In ...>(exec); | ||
217 | } | 241 | } |
218 | 242 | ||
219 | #endif // ASYNC_H | 243 | #endif // ASYNC_H |