MEL
Microthread & Execution library
NaiveInlineExecutor.h
1 #pragma once
2 /*
3  * SPDX-FileCopyrightText: 2022 Daniel Barrientos <danivillamanin@gmail.com>
4  *
5  * SPDX-License-Identifier: MIT
6  */
7 #include <execution/Executor.h>
8 
9 #include <mpl/TypeTraits.h>
10 namespace mel
11 {
12  namespace execution
13  {
14 
22  {
23  public:
26  template <class TRet,class TArg,class F> void launch( F&& f,TArg&& arg,ExFuture<NaiveInlineExecutionAgent,TRet> output) const noexcept
27  {
28  static_assert( std::is_invocable<F,TArg>::value, "NaiveExecutor::next bad functor signature");
29  if constexpr (std::is_same<std::invoke_result_t<F,TArg>,void>::value )
30  {
31  if constexpr (std::is_nothrow_invocable<F,TArg>::value)
32  {
33  f(std::forward<TArg>(arg));
34  output.setValue();
35  }
36  else
37  {
38  try
39  {
40  f(std::forward<TArg>(arg));
41  output.setValue();
42  }catch(...)
43  {
44  output.setError(std::current_exception());
45  }
46  }
47  }else
48  {
49  if constexpr (std::is_nothrow_invocable<F,TArg>::value)
50  output.setValue(f(std::forward<TArg>(arg)));
51  else
52  {
53  try
54  {
55  output.setValue(f(std::forward<TArg>(arg)));
56  }catch(...)
57  {
58  output.setError(std::current_exception());
59  }
60  }
61  }
62  }
63  template <class TRet,class F> void launch( F&& f,ExFuture<NaiveInlineExecutionAgent,TRet> output) const noexcept
64  {
65  if constexpr (std::is_same<std::invoke_result_t<F>,void>::value )
66  {
67  if constexpr (std::is_nothrow_invocable<F>::value)
68  {
69  f();
70  output.setValue();
71  }
72  else
73  {
74  try
75  {
76  f();
77  output.setValue();
78  }catch(...)
79  {
80  output.setError(std::current_exception());
81  }
82  }
83  }else
84  {
85  if constexpr (std::is_nothrow_invocable<F>::value)
86  output.setValue(f());
87  else
88  {
89  try
90  {
91  output.setValue(f());
92  }catch(...)
93  {
94  output.setError(std::current_exception());
95  }
96  }
97  }
98  }
99  template <class I, class F> ::mel::parallelism::Barrier loop( I&& begin, I&& end, F&& functor, int increment);
100  template <class TArg,class ...FTypes> ::mel::parallelism::Barrier parallel(ExFuture<NaiveInlineExecutionAgent,TArg> fut,std::exception_ptr& excpt, FTypes&&... functions);
101  template <class ReturnTuple,class TArg,class ...FTypes> ::mel::parallelism::Barrier parallel_convert(ExFuture<NaiveInlineExecutionAgent,TArg> fut,std::exception_ptr& excpt,ReturnTuple& result, FTypes&&... functions);
103  };
104  namespace _naive{namespace _private
105  {
106  template <class F,class TArg> void _invokeInline(ExFuture<NaiveInlineExecutionAgent,TArg> fut,std::exception_ptr& except,F&& f)
107  {
108  static_assert( std::is_invocable<F,TArg>::value, "_invokeInline bad functor signature");
109  if constexpr (std::is_nothrow_invocable<F,TArg>::value)
110  {
111  f(fut.getValue().value());
112  }else
113  {
114  try
115  {
116  f(fut.getValue().value());
117  }catch(...)
118  {
119  if ( !except )
120  except = std::current_exception();
121  }
122  }
123  }
124  //void overload
125  template <class F> void _invokeInline(ExFuture<NaiveInlineExecutionAgent,void> fut,std::exception_ptr& except,F&& f)
126  {
127  if constexpr (std::is_nothrow_invocable<F>::value)
128  {
129  f();
130  }else
131  {
132  try
133  {
134  f();
135  }catch(...)
136  {
137  if (!except)
138  except = std::current_exception();
139  }
140  }
141  }
142  template <class TArg,class F,class ...FTypes> void _invokeInline(ExFuture<NaiveInlineExecutionAgent,TArg> fut,std::exception_ptr& except,F&& f, FTypes&&... fs)
143  {
144  _naive::_private::_invokeInline(fut,except,std::forward<F>(f));
145  _naive::_private::_invokeInline(fut,except,std::forward<FTypes>(fs)...);
146  }
147  template <int n,class ResultTuple, class F,class TArg> void _invokeInline_with_result(ExFuture<NaiveInlineExecutionAgent,TArg> fut,std::exception_ptr& except,ResultTuple& output,F&& f)
148  {
149  static_assert( std::is_invocable<F,TArg>::value, "_invokeInline_with_result bad functor signature");
150  if constexpr (std::is_nothrow_invocable<F,TArg>::value)
151  {
152  if constexpr (std::is_same< std::invoke_result_t<F,TArg>,void >::value)
153  f(fut.getValue().value());
154  else
155  std::get<n>(output) = f(fut.getValue().value());
156  }else
157  {
158  try
159  {
160  if constexpr (std::is_same< std::invoke_result_t<F,TArg>,void >::value)
161  f(fut.getValue().value());
162  else
163  std::get<n>(output) = f(fut.getValue().value());
164  }catch(...)
165  {
166  if ( !except )
167  except = std::current_exception();
168  }
169  }
170 
171  }
172  //void overload
173  template <int n,class ResultTuple,class F> void _invokeInline_with_result(ExFuture<NaiveInlineExecutionAgent,void>& fut,std::exception_ptr& except,ResultTuple& output, F&& f)
174  {
175  if constexpr (std::is_nothrow_invocable<F>::value)
176  {
177  if constexpr (std::is_same< std::invoke_result_t<F>,void >::value)
178  f();
179  else
180  std::get<n>(output) = f();
181  }else
182  {
183  try
184  {
185  if constexpr (std::is_same< std::invoke_result_t<F>,void >::value)
186  f();
187  else
188  std::get<n>(output) = f();
189  }catch(...)
190  {
191  if (!except)
192  except = std::current_exception();
193  }
194  }
195  }
196 
197  template <int n,class ResultTuple,class TArg,class F,class ...FTypes> void _invokeInline_with_result(ExFuture<NaiveInlineExecutionAgent,TArg> fut,std::exception_ptr& except,ResultTuple& output,F&& f, FTypes&&... fs)
198  {
199  _naive::_private::_invokeInline_with_result<n>(fut,except,output,std::forward<F>(f));
200  _naive::_private::_invokeInline_with_result<n+1>(fut,except,output,std::forward<FTypes>(fs)...);
201  }
202  }}
214  template <class I, class F> ::mel::parallelism::Barrier Executor<NaiveInlineExecutionAgent>::loop(I&& begin, I&& end, F&& functor, int increment)
215  {
216  //@todo no correcto con no random iterators
217  //@todo falta gestionar error
218  for(auto i = begin; i != end;i+=increment)
219  {
220  functor(i);
221  }
222  return ::mel::parallelism::Barrier((size_t)0);
223  }
224  template <class TArg,class ...FTypes> ::mel::parallelism::Barrier Executor<NaiveInlineExecutionAgent>::parallel( ExFuture<NaiveInlineExecutionAgent,TArg> fut,std::exception_ptr& except,FTypes&&... functions)
225  {
226  _naive::_private::_invokeInline(fut,except,std::forward<FTypes>(functions)...);
227  return ::mel::parallelism::Barrier((size_t)0);
228  }
229  template <class ReturnTuple,class TArg,class ...FTypes> ::mel::parallelism::Barrier Executor<NaiveInlineExecutionAgent>::parallel_convert(ExFuture<NaiveInlineExecutionAgent,TArg> fut,std::exception_ptr& except,ReturnTuple& result, FTypes&&... functions)
230  {
231  _naive::_private::_invokeInline_with_result<0>(fut,except,result,std::forward<FTypes>(functions)...);
232  return ::mel::parallelism::Barrier((size_t)0);
233  }
234 
239  {
240  };
243  }
244 }
Typical Traits for types.
Extension of mel::core::Future to apply to executors.
Definition: ExFuture.h:21
Executor specialization using NaiveInlineExecutionAgent as execution agent.
Definition: NaiveInlineExecutor.h:22
void launch(F &&f, TArg &&arg, ExFuture< NaiveInlineExecutionAgent, TRet > output) const noexcept
Definition: NaiveInlineExecutor.h:26
Definition: Executor.h:26
Multithread barrier.
Definition: Barrier.h:43
ExFuture< ExecutorAgent, std::invoke_result_t< F > > launch(Executor< ExecutorAgent > ex, F &&f)
Launch given functor in given executor.
Definition: Executor.h:65
Executor< NaiveInlineExecutionAgent > NaiveInlineExecutor
alias for Executor<NaiveInlineExecutionAgent>
Definition: NaiveInlineExecutor.h:242
ExFuture< ExecutorAgent, TArg > parallel(ExFuture< ExecutorAgent, TArg > source, FTypes... functions)
Execute given functions in a (possibly, depending on concrete executor) parallel way If an exception ...
Definition: Executor.h:499
ExFuture< ExecutorAgent, TArg > loop(ExFuture< ExecutorAgent, TArg > source, I getIteratorsFunc, F functor, int increment=1)
parallel (possibly, depending on executor capabilities) loop
Definition: Executor.h:290
ExFuture< ExecutorAgent, typename ::mel::execution::_private::GetReturn< TArg, FTypes... >::type > parallel_convert(ExFuture< ExecutorAgent, TArg > source, FTypes... functions)
Same as parallel but returning a tuple with the values for each functor.
Definition: Executor.h:726
Definition: Callback_Impl.h:11
Default traits for any executor.
Definition: Executor.h:46
Definition: NaiveInlineExecutor.h:15