MEL
Microthread & Execution library
Launch.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 #include <preprocessor/utils.h>
9 #include <tuple>
10 namespace mel
11 {
12  namespace execution
13  {
14  namespace flow
15  {
17  template <class TupleType> struct FlowsResult
18  {
19  using type = TupleType;
20  FlowsResult( TupleType&& tt ) : tup( std::move( tt ) ){};
21  TupleType tup;
22  };
24  namespace _private
25  {
26  // helper for invoking flows
27  template <int n, class ResultTuple, class Flow,
28  class ExecutionAgent, class TArg>
29  void _invokeFlow( ExFuture<ExecutionAgent, TArg> fut,
30  std::exception_ptr& except,
31  ResultTuple& output, Flow&& f )
32  {
33  // static_assert( std::is_invocable<F,TArg>::value,
34  // "inlineExecutor::_invokeInline bad signature");
35  if constexpr ( std::is_nothrow_invocable<
36  Flow,
38  {
39  std::get<n>( output ) = f( fut );
40  }
41  else
42  {
43  try
44  {
45  std::get<n>( output ) = f( fut );
46  }
47  catch ( ... )
48  {
49  if ( !except )
50  except = std::current_exception();
51  }
52  }
53  }
54  template <int n, class ResultTuple, class ExecutionAgent,
55  class TArg, class Flow, class... Flows>
56  void _invokeFlow( ExFuture<ExecutionAgent, TArg> fut,
57  std::exception_ptr& except,
58  ResultTuple& output, Flow&& f, Flows&&... fs )
59  {
60  _invokeFlow<n>( fut, except, output,
61  std::forward<Flow>( f ) );
62  _invokeFlow<n + 1>( fut, except, output,
63  std::forward<Flows>( fs )... );
64  }
65  template <class ExecutionAgent, class T, size_t... Is>
66  auto _forwardOnAll( Executor<ExecutionAgent> ex, T&& tup,
67  std::index_sequence<Is...> )
68  {
69  return execution::on_all( ex, std::get<Is>( tup )... );
70  }
71  }; // namespace _private
73 
82  template <class TArg, class ExecutorAgent, class... Flows>
83  FlowsResult<typename ::mel::execution::_private::GetReturn<
84  ExFuture<ExecutorAgent, TArg>, Flows...>::type>
85  launch( ExFuture<ExecutorAgent, TArg> source, Flows... flows )
86  {
87  typedef typename ::mel::execution::_private::GetReturn<
88  ExFuture<ExecutorAgent, TArg>, Flows...>::type ResultTuple;
89  ResultTuple output;
90  std::exception_ptr
91  except; //@todo, uhmm, no es muy importante, porque se
92  // refiere a error en la funcion que lanza el flow..
93  _private::_invokeFlow<0>( source, except, output,
94  std::move( flows )... );
95  return FlowsResult<ResultTuple>( std::move( output ) );
96  }
101  template <class ExecutionAgent, class TupleFlow>
102  auto on_all( Executor<ExecutionAgent> ex, TupleFlow&& f )
103  {
104  // constexpr size_t ts = std::tuple_size<typename
105  // std::remove_reference<TupleFlow>::type>::value; return
106  // _private::_forwardOnAll(ex,f,std::make_index_sequence<ts>{});
107  constexpr size_t ts = std::tuple_size<
108  typename std::remove_reference_t<TupleFlow>::type>::value;
109  return _private::_forwardOnAll(
110  ex, f.tup, std::make_index_sequence<ts>{} );
111  }
112 
113  namespace _private
114  {
115  template <class ExecutionAgent> struct ApplyOnAll
116  {
117  ApplyOnAll( Executor<ExecutionAgent> ex ) : mEx( ex ) {}
119 
120  template <class TupleType>
121  auto operator()( FlowsResult<TupleType>&& fr )
122  {
123  return on_all( mEx, std::move( fr ) );
124  }
125  template <class TupleType>
126  auto operator()( const FlowsResult<TupleType>& fr )
127  {
128  return on_all( mEx, fr );
129  }
130  };
131 
132  template <class... Flows> struct ApplyLaunch
133  {
134  template <class... Fs>
135  ApplyLaunch( Fs&&... fs )
136  : mFuncs( std::forward<Fs>( fs )... )
137  {
138  }
139  std::tuple<Flows...> mFuncs;
140  template <class TArg, class ExecutorAgent>
141  auto operator()( ExFuture<ExecutorAgent, TArg> inputFut )
142  {
143  return launch( inputFut,
144  std::forward<Flows>(
145  std::get<Flows>( mFuncs ) )... );
146  }
147  };
148  } // namespace _private
149 
151  template <class... Flows>
152  _private::ApplyLaunch<Flows...> launch( Flows&&... flows )
153  {
154  return _private::ApplyLaunch<Flows...>(
155  std::forward<Flows>( flows )... );
156  }
157  template <class ExecutionAgent>
159  {
160  return _private::ApplyOnAll<ExecutionAgent>( ex );
161  }
165  template <class TupleType, class U>
166  auto operator|( const FlowsResult<TupleType>& input, U&& u )
167  {
168  return u( input );
169  }
170  template <class TupleType, class U>
171  auto operator|( FlowsResult<TupleType>&& input, U&& u )
172  {
173  return u( std::move( input ) );
174  }
175 
176  } // namespace flow
177  } // namespace execution
178 } // namespace mel
Extension of mel::core::Future to apply to executors.
Definition: ExFuture.h:21
FlowsResult< typename ::mel::execution::_private::GetReturn< ExFuture< ExecutorAgent, TArg >, Flows... >::type > launch(ExFuture< ExecutorAgent, TArg > source, Flows... flows)
Launch given set of flows.
Definition: Launch.h:85
auto operator|(const FlowsResult< TupleType > &input, U &&u)
overload operator | for chaining a FlowsResult
Definition: Launch.h:166
auto on_all(Executor< ExecutionAgent > ex, TupleFlow &&f)
Takes a tuple with the results of execution of some flows and does a execution::on_all.
Definition: Launch.h:102
auto on_all(Executor< ExecutorAgent > ex, FTypes... futs)
return ExFuture which will be executed, in the context of the given executor ex, when all the given E...
Definition: Executor.h:1161
Definition: Callback_Impl.h:11
!brief tuple wrapper for holding result of flows execution
Definition: Launch.h:18