1 /**
2 * Copyright 2021 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
22 #include "async/async.h"
23 #include "async/option.h"
24
25 namespace mindspore {
26
27 template <typename F>
28 class Deferred : public std::function<F> {
29 public:
~Deferred()30 virtual ~Deferred() {}
31
32 private:
33 template <typename G>
34 friend class internal::DeferredHelper;
35
36 template <typename T>
37 friend Deferred<void()> Defer(const AID &aid, void (T::*method)());
38
39 template <typename R, typename T>
40 friend Deferred<Future<R>()> Defer(const AID &aid, Future<R> (T::*method)());
41
42 template <typename R, typename T>
43 friend Deferred<Future<R>()> Defer(const AID &aid, R (T::*method)());
44
Deferred(const std::function<F> & f)45 Deferred(const std::function<F> &f) : std::function<F>(f) {}
46 };
47
48 namespace internal {
49
50 template <typename F>
51 class DeferredHelper {
52 public:
DeferredHelper(const AID & id,F && function)53 DeferredHelper(const AID &id, F &&function) : aid(id), f(std::forward<F>(function)) {}
54
DeferredHelper(F && function)55 DeferredHelper(F &&function) : f(std::forward<F>(function)) {}
56
~DeferredHelper()57 ~DeferredHelper() {}
58
59 operator Deferred<void()>() && {
60 if (aid.IsNone()) {
61 return std::function<void()>(std::forward<F>(f));
62 }
63
64 Option<AID> optionAid = aid;
65 F &&function = std::forward<F>(f);
66
67 return std::function<void()>([=]() { Async(optionAid.Get(), function); });
68 }
69
70 operator std::function<void()>() && {
71 if (aid.IsNone()) {
72 return std::function<void()>(std::forward<F>(f));
73 }
74
75 Option<AID> optionAid = aid;
76 F &&function = std::forward<F>(f);
77
78 return std::function<void()>([=]() { Async(optionAid.Get(), function); });
79 }
80
81 template <typename R>
82 operator Deferred<R()>() && {
83 if (aid.IsNone()) {
84 return std::function<R()>(std::forward<F>(f));
85 }
86
87 Option<AID> optionAid = aid;
88 F &&function = std::forward<F>(f);
89
90 return std::function<R()>([=]() { return Async(optionAid.Get(), function); });
91 }
92
93 template <typename R>
94 operator std::function<R()>() && {
95 if (aid.IsNone()) {
96 return std::function<R()>(std::forward<F>(f));
97 }
98
99 Option<AID> optionAid = aid;
100 F &&function = std::forward<F>(f);
101
102 return std::function<R()>([=]() { return Async(optionAid.Get(), function); });
103 }
104
105 template <typename Arg>
106 operator Deferred<void(Arg)>() && {
107 if (aid.IsNone()) {
108 return std::function<void(Arg)>(std::forward<F>(f));
109 }
110
111 Option<AID> optionAid = aid;
112 F &&function = std::forward<F>(f);
113
114 return std::function<void(Arg)>([=](Arg arg) {
115 std::function<void()> handler([=]() { function(arg); });
116 Async(optionAid.Get(), handler);
117 });
118 }
119
120 template <typename Arg>
121 operator std::function<void(Arg)>() && {
122 if (aid.IsNone()) {
123 return std::function<void(Arg)>(std::forward<F>(f));
124 }
125
126 Option<AID> optionAid = aid;
127 F &&function = std::forward<F>(f);
128
129 return std::function<void(Arg)>([=](Arg arg) {
130 std::function<void()> handler([=]() { function(arg); });
131 Async(optionAid.Get(), handler);
132 });
133 }
134
135 template <typename... Args>
136 operator Deferred<void(Args...)>() && {
137 if (aid.IsNone()) {
138 return std::function<void(Args...)>(std::forward<F>(f));
139 }
140
141 Option<AID> optionAid = aid;
142 F &&function = std::forward<F>(f);
143
144 return std::function<void(Args...)>([=](Args... args) {
145 auto tuple = std::make_tuple(std::forward<Args>(args)...);
146 std::function<void()> handler([=]() { Apply(function, tuple); });
147 Async(optionAid.Get(), handler);
148 });
149 }
150
151 template <typename... Args>
152 operator std::function<void(Args...)>() && {
153 if (aid.IsNone()) {
154 return std::function<void(Args...)>(std::forward<F>(f));
155 }
156
157 Option<AID> optionAid = aid;
158 F &&function = std::forward<F>(f);
159
160 return std::function<void(Args...)>([=](Args... args) {
161 auto tuple = std::make_tuple(std::forward<Args>(args)...);
162 std::function<void()> handler([=]() { Apply(function, tuple); });
163 Async(optionAid.Get(), handler);
164 });
165 }
166
167 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename Arg>
168 operator Deferred<R(Arg)>() && {
169 if (aid.IsNone()) {
170 return std::function<R(Arg)>(std::forward<F>(f));
171 }
172
173 Option<AID> optionAid = aid;
174 F &&function = std::forward<F>(f);
175
176 return std::function<R(Arg)>([=](Arg arg) {
177 std::function<R()> handler([=]() { return function(arg); });
178 return Async(optionAid.Get(), handler);
179 });
180 }
181
182 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename Arg>
183 operator std::function<R(Arg)>() && {
184 if (aid.IsNone()) {
185 return std::function<R(Arg)>(std::forward<F>(f));
186 }
187
188 Option<AID> optionAid = aid;
189 F &&function = std::forward<F>(f);
190
191 return std::function<R(Arg)>([=](Arg arg) {
192 std::function<R()> handler([=]() { return function(arg); });
193 return Async(optionAid.Get(), handler);
194 });
195 }
196
197 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename... Args>
198 operator Deferred<R(Args...)>() && {
199 if (aid.IsNone()) {
200 return std::function<R(Args...)>(std::forward<F>(f));
201 }
202
203 Option<AID> optionAid = aid;
204 F &&function = std::forward<F>(f);
205
206 return std::function<R(Args...)>([=](Args... args) {
207 auto tuple = std::make_tuple(std::forward<Args>(args)...);
208 std::function<R()> handler([=]() { return Apply(function, tuple); });
209 return Async(optionAid.Get(), handler);
210 });
211 }
212
213 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0, typename... Args>
214 operator std::function<R(Args...)>() && {
215 if (aid.IsNone()) {
216 return std::function<R(Args...)>(std::forward<F>(f));
217 }
218
219 Option<AID> optionAid = aid;
220 F &&function = std::forward<F>(f);
221
222 return std::function<R(Args...)>([=](Args... args) {
223 auto tuple = std::make_tuple(std::forward<Args>(args)...);
224 std::function<R()> handler([=]() { return Apply(function, tuple); });
225 return Async(optionAid.Get(), handler);
226 });
227 }
228
229 private:
230 template <typename G>
231 friend DeferredHelper<G> Defer(const AID &aid, G &&g);
232
233 Option<AID> aid;
234 F f;
235 };
236
237 } // namespace internal
238
239 template <typename F>
Defer(const AID & aid,F && f)240 internal::DeferredHelper<F> Defer(const AID &aid, F &&f) {
241 return internal::DeferredHelper<F>(aid, std::forward<F>(f));
242 }
243
244 template <typename T>
Defer(const AID & aid,void (T::* method)())245 Deferred<void()> Defer(const AID &aid, void (T::*method)()) {
246 return Deferred<void()>([=]() { Async(aid, method); });
247 }
248
249 template <typename R, typename T>
Defer(const AID & aid,Future<R> (T::* method)())250 Deferred<Future<R>()> Defer(const AID &aid, Future<R> (T::*method)()) {
251 return Deferred<Future<R>()>([=]() { return Async(aid, method); });
252 }
253
254 template <typename R, typename T>
Defer(const AID & aid,R (T::* method)())255 Deferred<Future<R>()> Defer(const AID &aid, R (T::*method)()) {
256 return Deferred<Future<R>()>([=]() { return Async(aid, method); });
257 }
258
259 template <typename T, typename... Args0, typename... Args1>
260 auto Defer(T *t, void (T::*method)(Args0...), Args1 &&... args)
261 -> internal::DeferredHelper<decltype(std::bind(&std::function<void(Args0...)>::operator(),
262 std::function<void(Args0...)>(), std::forward<Args1>(args)...))> {
263 std::function<void(Args0...)> f([=](Args0... args0) {
264 if (t != nullptr) {
265 (t->*method)(args0...);
266 }
267 });
268
269 return std::bind(&std::function<void(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
270 }
271
272 template <typename T, typename... Args0, typename... Args1>
273 auto Defer(std::shared_ptr<T> t, void (T::*method)(Args0...), Args1 &&... args)
274 -> internal::DeferredHelper<decltype(std::bind(&std::function<void(Args0...)>::operator(),
275 std::function<void(Args0...)>(), std::forward<Args1>(args)...))> {
276 std::function<void(Args0...)> f([=](Args0... args0) {
277 if (t != nullptr) {
278 (t.get()->*method)(args0...);
279 }
280 });
281
282 return std::bind(&std::function<void(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
283 }
284
285 template <typename T, typename... Args0, typename... Args1>
286 auto Defer(const AID &aid, void (T::*method)(Args0...), Args1 &&... args)
287 -> internal::DeferredHelper<decltype(std::bind(&std::function<void(Args0...)>::operator(),
288 std::function<void(Args0...)>(), std::forward<Args1>(args)...))> {
289 std::function<void(Args0...)> f([=](Args0... args0) { Async(aid, method, args0...); });
290
291 return std::bind(&std::function<void(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
292 }
293
294 template <typename R, typename T, typename... Args0, typename... Args1>
295 auto Defer(const AID &aid, Future<R> (T::*method)(Args0...), Args1 &&... args)
296 -> internal::DeferredHelper<decltype(std::bind(&std::function<Future<R>(Args0...)>::operator(),
297 std::function<Future<R>(Args0...)>(), std::forward<Args1>(args)...))> {
298 std::function<Future<R>(Args0...)> f([=](Args0... args0) { return Async(aid, method, args0...); });
299
300 return std::bind(&std::function<Future<R>(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
301 }
302
303 template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0,
304 typename std::enable_if<!internal::IsFuture<R>::value, int>::type = 0, typename T, typename... Args0,
305 typename... Args1>
306 auto Defer(const AID &aid, R (T::*method)(Args0...), Args1 &&... args)
307 -> internal::DeferredHelper<decltype(std::bind(&std::function<Future<R>(Args0...)>::operator(),
308 std::function<Future<R>(Args0...)>(), std::forward<Args1>(args)...))> {
309 std::function<Future<R>(Args0...)> f([=](Args0... args0) { return Async(aid, method, args0...); });
310
311 return std::bind(&std::function<Future<R>(Args0...)>::operator(), std::move(f), std::forward<Args1>(args)...);
312 }
313
314 } // namespace mindspore
315
316 #endif
317