1 /**
2 * Copyright 2021-2022 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_DEFER_H
18 #define MINDSPORE_CORE_MINDRT_INCLUDE_ASYNC_DEFER_H
19
20 #include <functional>
21 #include <memory>
22 #include <utility>
23
24 #include "async/async.h"
25 #include "async/option.h"
26
27 namespace mindspore {
28
29 template <typename F>
30 class Deferred : public std::function<F> {
31 public:
~Deferred()32 virtual ~Deferred() {}
33
34 private:
35 template <typename G>
36 friend class internal::DeferredHelper;
37
38 template <typename T>
39 friend Deferred<void()> Defer(const AID &aid, void (T::*method)());
40
41 template <typename R, typename T>
42 friend Deferred<Future<R>()> Defer(const AID &aid, Future<R> (T::*method)());
43
44 template <typename R, typename T>
45 friend Deferred<Future<R>()> Defer(const AID &aid, R (T::*method)());
46
Deferred(const std::function<F> & f)47 Deferred(const std::function<F> &f) : std::function<F>(f) {}
48 };
49
50 namespace internal {
51
52 template <typename F>
53 class DeferredHelper {
54 public:
DeferredHelper(const AID & id,F && function)55 DeferredHelper(const AID &id, F &&function) : aid(id), f(std::forward<F>(function)) {}
56
DeferredHelper(F && function)57 DeferredHelper(F &&function) : f(std::forward<F>(function)) {}
58
~DeferredHelper()59 ~DeferredHelper() {}
60
61 operator Deferred<void()>() && {
62 if (aid.IsNone()) {
63 return std::function<void()>(std::forward<F>(f));
64 }
65
66 Option<AID> optionAid = aid;
67 F &&function = std::forward<F>(f);
68
69 return std::function<void()>([=]() { Async(optionAid.Get(), function); });
70 }
71
72 operator std::function<void()>() && {
73 if (aid.IsNone()) {
74 return std::function<void()>(std::forward<F>(f));
75 }
76
77 Option<AID> optionAid = aid;
78 F &&function = std::forward<F>(f);
79
80 return std::function<void()>([=]() { Async(optionAid.Get(), function); });
81 }
82
83 template <typename R>
84 operator Deferred<R()>() && {
85 if (aid.IsNone()) {
86 return std::function<R()>(std::forward<F>(f));
87 }
88
89 Option<AID> optionAid = aid;
90 F &&function = std::forward<F>(f);
91
92 return std::function<R()>([=]() { return Async(optionAid.Get(), function); });
93 }
94
95 template <typename R>
96 operator std::function<R()>() && {
97 if (aid.IsNone()) {
98 return std::function<R()>(std::forward<F>(f));
99 }
100
101 Option<AID> optionAid = aid;
102 F &&function = std::forward<F>(f);
103
104 return std::function<R()>([=]() { return Async(optionAid.Get(), function); });
105 }
106
107 template <typename Arg>
108 operator Deferred<void(Arg)>() && {
109 if (aid.IsNone()) {
110 return std::function<void(Arg)>(std::forward<F>(f));
111 }
112
113 Option<AID> optionAid = aid;
114 F &&function = std::forward<F>(f);
115
116 return std::function<void(Arg)>([=](Arg arg) {
117 std::function<void()> handler([=]() { function(arg); });
118 Async(optionAid.Get(), handler);
119 });
120 }
121
122 template <typename Arg>
123 operator std::function<void(Arg)>() && {
124 if (aid.IsNone()) {
125 return std::function<void(Arg)>(std::forward<F>(f));
126 }
127
128 Option<AID> optionAid = aid;
129 F &&function = std::forward<F>(f);
130
131 return std::function<void(Arg)>([=](Arg arg) {
132 std::function<void()> handler([=]() { function(arg); });
133 Async(optionAid.Get(), handler);
134 });
135 }
136
137 template <typename... Args>
138 operator Deferred<void(Args...)>() && {
139 if (aid.IsNone()) {
140 return std::function<void(Args...)>(std::forward<F>(f));
141 }
142
143 Option<AID> optionAid = aid;
144 F &&function = std::forward<F>(f);
145
146 return std::function<void(Args...)>([=](Args... args) {
147 auto tuple = std::make_tuple(std::forward<Args>(args)...);
148 std::function<void()> handler([=]() { Apply(function, tuple); });
149 Async(optionAid.Get(), handler);
150 });
151 }
152
153 template <typename... Args>
154 operator std::function<void(Args...)>() && {
155 if (aid.IsNone()) {
156 return std::function<void(Args...)>(std::forward<F>(f));
157 }
158
159 Option<AID> optionAid = aid;
160 F &&function = std::forward<F>(f);
161
162 return std::function<void(Args...)>([=](Args... args) {
163 auto tuple = std::make_tuple(std::forward<Args>(args)...);
164 std::function<void()> handler([=]() { Apply(function, tuple); });
165 Async(optionAid.Get(), handler);
166 });
167 }
168
169 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename Arg>
170 operator Deferred<R(Arg)>() && {
171 if (aid.IsNone()) {
172 return std::function<R(Arg)>(std::forward<F>(f));
173 }
174
175 Option<AID> optionAid = aid;
176 F &&function = std::forward<F>(f);
177
178 return std::function<R(Arg)>([=](Arg arg) {
179 std::function<R()> handler([=]() { return function(arg); });
180 return Async(optionAid.Get(), handler);
181 });
182 }
183
184 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename Arg>
185 operator std::function<R(Arg)>() && {
186 if (aid.IsNone()) {
187 return std::function<R(Arg)>(std::forward<F>(f));
188 }
189
190 Option<AID> optionAid = aid;
191 F &&function = std::forward<F>(f);
192
193 return std::function<R(Arg)>([=](Arg arg) {
194 std::function<R()> handler([=]() { return function(arg); });
195 return Async(optionAid.Get(), handler);
196 });
197 }
198
199 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename... Args>
200 operator Deferred<R(Args...)>() && {
201 if (aid.IsNone()) {
202 return std::function<R(Args...)>(std::forward<F>(f));
203 }
204
205 Option<AID> optionAid = aid;
206 F &&function = std::forward<F>(f);
207
208 return std::function<R(Args...)>([=](Args... args) {
209 auto tuple = std::make_tuple(std::forward<Args>(args)...);
210 std::function<R()> handler([=]() { return Apply(function, tuple); });
211 return Async(optionAid.Get(), handler);
212 });
213 }
214
215 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename... Args>
216 operator std::function<R(Args...)>() && {
217 if (aid.IsNone()) {
218 return std::function<R(Args...)>(std::forward<F>(f));
219 }
220
221 Option<AID> optionAid = aid;
222 F &&function = std::forward<F>(f);
223
224 return std::function<R(Args...)>([=](Args... args) {
225 auto tuple = std::make_tuple(std::forward<Args>(args)...);
226 std::function<R()> handler([=]() { return Apply(function, tuple); });
227 return Async(optionAid.Get(), handler);
228 });
229 }
230
231 private:
232 template <typename G>
233 friend DeferredHelper<G> Defer(const AID &aid, G &&g);
234
235 Option<AID> aid;
236 F f;
237 };
238
239 } // namespace internal
240
241 template <typename F>
Defer(const AID & aid,F && f)242 internal::DeferredHelper<F> Defer(const AID &aid, F &&f) {
243 return internal::DeferredHelper<F>(aid, std::forward<F>(f));
244 }
245
246 template <typename T>
Defer(const AID & aid,void (T::* method)())247 Deferred<void()> Defer(const AID &aid, void (T::*method)()) {
248 return Deferred<void()>([=]() { Async(aid, method); });
249 }
250
251 template <typename R, typename T>
Defer(const AID & aid,Future<R> (T::* method)())252 Deferred<Future<R>()> Defer(const AID &aid, Future<R> (T::*method)()) {
253 return Deferred<Future<R>()>([=]() { return Async(aid, method); });
254 }
255
256 template <typename R, typename T>
Defer(const AID & aid,R (T::* method)())257 Deferred<Future<R>()> Defer(const AID &aid, R (T::*method)()) {
258 return Deferred<Future<R>()>([=]() { return Async(aid, method); });
259 }
260
261 template <typename T, typename... Args0, typename... Args1>
262 auto Defer(T *t, void (T::*method)(Args0...), Args1 &&... args)
263 -> internal::DeferredHelper<decltype(std::bind(&std::function<void(Args0...)>::operator(),
264 std::function<void(Args0...)>(), std::forward<Args1>(args)...))> {
265 std::function<void(Args0...)> f([=](Args0... args0) {
266 if (t != nullptr) {
267 (t->*method)(args0...);
268 }
269 });
270
271 return std::bind(&std::function<void(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
272 }
273
274 template <typename T, typename... Args0, typename... Args1>
275 auto Defer(std::shared_ptr<T> t, void (T::*method)(Args0...), Args1 &&... args)
276 -> internal::DeferredHelper<decltype(std::bind(&std::function<void(Args0...)>::operator(),
277 std::function<void(Args0...)>(), std::forward<Args1>(args)...))> {
278 std::function<void(Args0...)> f([=](Args0... args0) {
279 if (t != nullptr) {
280 (t.get()->*method)(args0...);
281 }
282 });
283
284 return std::bind(&std::function<void(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
285 }
286
287 template <typename T, typename... Args0, typename... Args1>
288 auto Defer(const AID &aid, void (T::*method)(Args0...), Args1 &&... args)
289 -> internal::DeferredHelper<decltype(std::bind(&std::function<void(Args0...)>::operator(),
290 std::function<void(Args0...)>(), std::forward<Args1>(args)...))> {
291 std::function<void(Args0...)> f([=](Args0... args0) { Async(aid, method, args0...); });
292
293 return std::bind(&std::function<void(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
294 }
295
296 template <typename R, typename T, typename... Args0, typename... Args1>
297 auto Defer(const AID &aid, Future<R> (T::*method)(Args0...), Args1 &&... args)
298 -> internal::DeferredHelper<decltype(std::bind(&std::function<Future<R>(Args0...)>::operator(),
299 std::function<Future<R>(Args0...)>(), std::forward<Args1>(args)...))> {
300 std::function<Future<R>(Args0...)> f([=](Args0... args0) { return Async(aid, method, args0...); });
301
302 return std::bind(&std::function<Future<R>(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
303 }
304
305 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0,
306 typename std::enable_if<!internal::IsFuture<R>::value, int>::type = 0, typename T, typename... Args0,
307 typename... Args1>
308 auto Defer(const AID &aid, R (T::*method)(Args0...), Args1 &&... args)
309 -> internal::DeferredHelper<decltype(std::bind(&std::function<Future<R>(Args0...)>::operator(),
310 std::function<Future<R>(Args0...)>(), std::forward<Args1>(args)...))> {
311 std::function<Future<R>(Args0...)> f([=](Args0... args0) { return Async(aid, method, args0...); });
312
313 return std::bind(&std::function<Future<R>(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
314 }
315
316 } // namespace mindspore
317
318 #endif
319