• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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