diff options
Diffstat (limited to 'async')
-rw-r--r-- | async/autotests/asynctest.cpp | 3 | ||||
-rw-r--r-- | async/src/async.h | 111 |
2 files changed, 62 insertions, 52 deletions
diff --git a/async/autotests/asynctest.cpp b/async/autotests/asynctest.cpp index f2a70a4..786ff3c 100644 --- a/async/autotests/asynctest.cpp +++ b/async/autotests/asynctest.cpp | |||
@@ -80,8 +80,9 @@ void AsyncTest::testAsyncPromises() | |||
80 | [&]() { | 80 | [&]() { |
81 | future.setValue(42); | 81 | future.setValue(42); |
82 | future.setFinished(); | 82 | future.setFinished(); |
83 | timer->deleteLater(); | ||
84 | }); | 83 | }); |
84 | QObject::connect(timer, &QTimer::timeout, | ||
85 | timer, &QObject::deleteLater); | ||
85 | timer->setSingleShot(true); | 86 | timer->setSingleShot(true); |
86 | timer->start(200); | 87 | timer->start(200); |
87 | return future; | 88 | return future; |
diff --git a/async/src/async.h b/async/src/async.h index 790dfe9..3fee450 100644 --- a/async/src/async.h +++ b/async/src/async.h | |||
@@ -34,38 +34,51 @@ | |||
34 | 34 | ||
35 | namespace Async { | 35 | namespace Async { |
36 | 36 | ||
37 | class JobBase; | ||
38 | |||
37 | template<typename Out, typename ... In> | 39 | template<typename Out, typename ... In> |
38 | class Job; | 40 | class Job; |
39 | 41 | ||
40 | template<typename Out, typename ... In> | 42 | template<typename Out, typename ... In> |
41 | Job<Out, In ...> start(const std::function<Async::Future<Out>(In ...)> &func); | 43 | Job<Out, In ...> start(const std::function<Async::Future<Out>(In ...)> &func); |
42 | 44 | ||
45 | namespace Private | ||
46 | { | ||
47 | template<typename Out, typename ... In> | ||
48 | Async::Future<Out>* doExec(Job<Out, In ...> *job, const In & ... args); | ||
49 | } | ||
43 | 50 | ||
44 | class JobBase | 51 | class JobBase |
45 | { | 52 | { |
53 | template<typename Out, typename ... In> | ||
54 | friend Async::Future<Out>* Private::doExec(Job<Out, In ...> *job, const In & ... args); | ||
55 | |||
56 | template<typename Out, typename ... In> | ||
57 | friend class Job; | ||
58 | |||
59 | protected: | ||
60 | enum JobType { | ||
61 | Then, | ||
62 | Each | ||
63 | }; | ||
64 | |||
46 | public: | 65 | public: |
47 | JobBase(JobBase *prev = nullptr) | 66 | JobBase(JobType jobType, JobBase *prev = nullptr) |
48 | : mPrev(prev) | 67 | : mPrev(prev) |
49 | , mResult(0) | 68 | , mResult(0) |
69 | , mJobType(jobType) | ||
50 | {} | 70 | {} |
51 | 71 | ||
52 | virtual void exec() = 0; | 72 | virtual void exec() = 0; |
53 | 73 | ||
54 | public: | 74 | protected: |
55 | JobBase *mPrev; | 75 | JobBase *mPrev; |
56 | void *mResult; | 76 | void *mResult; |
57 | }; | ||
58 | 77 | ||
59 | namespace Private { | 78 | JobType mJobType; |
79 | }; | ||
60 | 80 | ||
61 | template<typename Out, typename In> | ||
62 | typename std::enable_if<!std::is_void<In>::value, void>::type | ||
63 | doExec(JobBase *prev, JobBase *jobBase); | ||
64 | 81 | ||
65 | template<typename Out, typename ... In> | ||
66 | typename std::enable_if<sizeof...(In) == 0, void>::type | ||
67 | doExec(JobBase *prev, JobBase *jobBase, int * /* disambiguate */ = 0); | ||
68 | } | ||
69 | 82 | ||
70 | template<typename Out, typename ... In> | 83 | template<typename Out, typename ... In> |
71 | class Job : public JobBase | 84 | class Job : public JobBase |
@@ -76,20 +89,25 @@ class Job : public JobBase | |||
76 | template<typename Out_, typename ... In_, typename F_> | 89 | template<typename Out_, typename ... In_, typename F_> |
77 | friend Job<Out_, In_ ...> start(F_ func); | 90 | friend Job<Out_, In_ ...> start(F_ func); |
78 | 91 | ||
92 | typedef Out OutType; | ||
93 | typedef typename std::tuple_element<0, std::tuple<In ..., void>>::type InType; | ||
94 | |||
79 | public: | 95 | public: |
80 | ~Job() | 96 | ~Job() |
81 | { | 97 | { |
82 | // Can't delete in JobBase, since we don't know the type | ||
83 | // and deleting void* is undefined | ||
84 | delete reinterpret_cast<Async::Future<Out>*>(mResult); | 98 | delete reinterpret_cast<Async::Future<Out>*>(mResult); |
85 | } | 99 | } |
86 | 100 | ||
87 | template<typename Out_, typename ... In_, typename F> | 101 | template<typename Out_, typename ... In_, typename F> |
88 | Job<Out_, In_ ...> then(F func) | 102 | Job<Out_, In_ ...> then(F func) |
89 | { | 103 | { |
90 | Job<Out_, In_ ...> job(this); | 104 | return Job<Out_, In_ ...>::create(func, JobBase::Then, this); |
91 | job.mFunc = func; | 105 | } |
92 | return job; | 106 | |
107 | template<typename Out_, typename ... In_, typename F> | ||
108 | Job<Out_, In_ ...> each(F func) | ||
109 | { | ||
110 | return Job<Out_, In_ ...>::create(func, JobBase::Each, this); | ||
93 | } | 111 | } |
94 | 112 | ||
95 | Async::Future<Out> result() const | 113 | Async::Future<Out> result() const |
@@ -97,16 +115,34 @@ public: | |||
97 | return *reinterpret_cast<Async::Future<Out>*>(mResult); | 115 | return *reinterpret_cast<Async::Future<Out>*>(mResult); |
98 | } | 116 | } |
99 | 117 | ||
100 | |||
101 | void exec() | 118 | void exec() |
102 | { | 119 | { |
103 | Async::Private::doExec<Out, In ...>(mPrev, this); | 120 | Async::Future<InType> *in = nullptr; |
121 | if (mPrev) { | ||
122 | mPrev->exec(); | ||
123 | in = reinterpret_cast<Async::Future<InType>*>(mPrev->mResult); | ||
124 | assert(in->isFinished()); | ||
125 | } | ||
126 | |||
127 | Job<Out, In ...> *job = dynamic_cast<Job<Out, In ...>*>(this); | ||
128 | Async::Future<Out> *out = Private::doExec<Out, In ...>(this, in ? in->value() : In() ...); | ||
129 | out->waitForFinished(); | ||
130 | job->mResult = reinterpret_cast<void*>(out); | ||
104 | } | 131 | } |
105 | 132 | ||
106 | private: | 133 | private: |
107 | Job(JobBase *parent = nullptr) | 134 | Job(JobBase::JobType jobType, JobBase *parent = nullptr) |
108 | : JobBase(parent) | 135 | : JobBase(jobType, parent) |
109 | {} | 136 | { |
137 | } | ||
138 | |||
139 | template<typename F> | ||
140 | static Job<Out, In ... > create(F func, JobBase::JobType jobType, JobBase *parent = nullptr) | ||
141 | { | ||
142 | Job<Out, In ...> job(jobType, parent); | ||
143 | job.mFunc = func; | ||
144 | return job; | ||
145 | } | ||
110 | 146 | ||
111 | public: | 147 | public: |
112 | std::function<Async::Future<Out>(In ...)> mFunc; | 148 | std::function<Async::Future<Out>(In ...)> mFunc; |
@@ -115,44 +151,17 @@ public: | |||
115 | template<typename Out, typename ... In, typename F> | 151 | template<typename Out, typename ... In, typename F> |
116 | Job<Out, In ...> start(F func) | 152 | Job<Out, In ...> start(F func) |
117 | { | 153 | { |
118 | Job<Out, In ...> job; | 154 | return Job<Out, In ...>::create(func, JobBase::Then); |
119 | job.mFunc = std::function<Async::Future<Out>(In ...)>(func); | ||
120 | return job; | ||
121 | } | 155 | } |
122 | 156 | ||
123 | } // namespace Async | 157 | } // namespace Async |
124 | 158 | ||
125 | template<typename Out, typename In> | ||
126 | typename std::enable_if<!std::is_void<In>::value, void>::type | ||
127 | Async::Private::doExec(JobBase *prev, JobBase *jobBase) | ||
128 | { | ||
129 | prev->exec(); | ||
130 | Async::Future<In> *in = reinterpret_cast<Async::Future<In>*>(prev->mResult); | ||
131 | assert(in->isFinished()); | ||
132 | |||
133 | Job<Out, In> *job = dynamic_cast<Job<Out, In>*>(jobBase); | ||
134 | Async::Future<Out> *out = new Async::Future<Out>(job->mFunc(in->value())); | ||
135 | out->waitForFinished(); | ||
136 | job->mResult = reinterpret_cast<void*>(out); | ||
137 | }; | ||
138 | |||
139 | template<typename Out, typename ... In> | 159 | template<typename Out, typename ... In> |
140 | typename std::enable_if<sizeof...(In) == 0, void>::type | 160 | Async::Future<Out>* Async::Private::doExec(Job<Out, In ...> *job, const In & ... args) |
141 | Async::Private::doExec(JobBase *prev, JobBase *jobBase, int * /* disambiguation */ = 0) | ||
142 | { | 161 | { |
143 | if (prev) { | 162 | return new Async::Future<Out>(job->mFunc(args ...)); |
144 | prev->exec(); | ||
145 | Async::Future<void> *in = reinterpret_cast<Async::Future<void>*>(prev->mResult); | ||
146 | assert(in->isFinished()); | ||
147 | } | ||
148 | |||
149 | Job<Out> *job = dynamic_cast<Job<Out>*>(jobBase); | ||
150 | Async::Future<Out> *out = new Async::Future<Out>(job->mFunc()); | ||
151 | out->waitForFinished(); | ||
152 | job->mResult = reinterpret_cast<void*>(out); | ||
153 | }; | 163 | }; |
154 | 164 | ||
155 | |||
156 | #endif // ASYNC_H | 165 | #endif // ASYNC_H |
157 | 166 | ||
158 | 167 | ||