summaryrefslogtreecommitdiffstats
path: root/async
diff options
context:
space:
mode:
Diffstat (limited to 'async')
-rw-r--r--async/autotests/asynctest.cpp50
-rw-r--r--async/src/async.h44
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
46void AsyncTest::testSyncPromises() 47void 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
71void AsyncTest::testAsyncPromises() 73void 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
115void 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
112QTEST_MAIN(AsyncTest); 138QTEST_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>
80class ThenExecutor: public Executor 80class 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
87public: 83public:
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
143template<typename Out, typename In>
144class ReduceExecutor : public Executor
145{
146public:
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
165private:
166 std::function<void(const In &, Async::Future<Out> &)> mFunc;
167};
168
144class JobBase 169class 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:
212template<typename Out, typename ... In> 237template<typename Out, typename ... In>
213Async::Job<Out, In ...> Async::start(ThenTask<Out, In ...> func) 238Async::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