MEL
Microthread & Execution library
While.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 
11 namespace mel
12 {
13  namespace execution
14  {
15  namespace flow
16  {
17  namespace _private
18  {
19  template <class Flow, class Predicate, class ExecutorAgent,
20  class TArg, class FlowResult>
21  class WhileImpl
22  : public std::enable_shared_from_this<WhileImpl<
23  Flow, Predicate, ExecutorAgent, TArg, FlowResult>>
24  {
26 
27  public:
28  template <class F, class P>
29  static std::shared_ptr<WhileImpl<
30  Flow, Predicate, ExecutorAgent, TArg, FlowResult>>
31  create( F&& f, P&& p, SourceType source, FlowResult result )
32  {
33  auto ptr = new WhileImpl<Flow, Predicate, ExecutorAgent,
34  TArg, FlowResult>(
35  std::forward<F>( f ), std::forward<P>( p ), source,
36  result );
37  return std::shared_ptr<WhileImpl<
38  Flow, Predicate, ExecutorAgent, TArg, FlowResult>>(
39  ptr );
40  // return
41  // std::make_shared<WhileImpl<Flow,Predicate,ExecutorAgent,TArg,FlowResult>>(std::forward<F>(f),std::forward<P>(p),source);
42  }
43  void execute()
44  {
45  auto fut = mFlow( mSource );
46  auto _this =
47  WhileImpl<Flow, Predicate, ExecutorAgent, TArg,
48  FlowResult>::shared_from_this();
49  fut.subscribeCallback( [_this, fut]( auto v )
50  { _this->_callback( fut ); } );
51  }
52  // ~WhileImpl() //para depurar, quitarlo
53  // {
54  // mel::text::debug("WhileImpl destructor");
55  // }
56  private:
57  // typename RemovePointerRef<Flow>::type mFlow;
58  // typename RemovePointerRef<Predicate>::type mPred;
59  Flow mFlow;
60  Predicate mPred;
61  SourceType mSource;
62  FlowResult mResult;
63 
64  template <class F, class P>
65  WhileImpl( F&& f, P&& p, SourceType s, FlowResult r )
66  : mFlow( std::forward<F>( f ) ),
67  mPred( std::forward<P>( p ) ), mSource( s ),
68  mResult( r )
69  {
70  }
71  void _callback( FlowResult res )
72  {
73  typename FlowResult::ValueType& val = res.getValue();
74  if ( val.isValid() )
75  {
76  if constexpr ( std::is_same<
77  typename FlowResult::ValueType::
78  ReturnType,
79  void>::value )
80  {
81  if ( mPred() )
82  execute();
83  else
84  mResult.assign( res );
85  }
86  else
87  {
88  if ( mPred( val.value() ) )
89  execute();
90  else
91  mResult.assign( res );
92  }
93  }
94  else
95  mResult.setError(
96  std::move( res.getValue().error() ) );
97  }
98  };
99 
100  }; // namespace _private
101 
114  template <class ExecutorAgent, class TArg, class Flow,
115  class Predicate>
116  auto doWhile( ExFuture<ExecutorAgent, TArg> source, Flow flow,
117  Predicate p )
118  {
119  static_assert(
120  std::is_invocable<Flow,
122  "execution::doWhile bad flow signature" );
123  typedef
124  typename ExFuture<ExecutorAgent, TArg>::ValueType ValueType;
125  typedef std::invoke_result_t<Flow,
127  TRet;
128  TRet result( source.agent );
129  source.subscribeCallback(
130  // need to bind de source future to not get lost and input
131  // pointing to unknown place
132 
133  [source, flow = std::move( flow ), p = std::move( p ),
134  result]( ValueType& input ) mutable
135  {
136  if ( input.isValid() )
137  {
138  auto _while = _private::WhileImpl<
139  Flow, Predicate, ExecutorAgent, TArg,
140  TRet>::create( std::move( flow ),
141  std::move( p ), source, result );
142  _while->execute();
143  }
144  else
145  {
146  launch(
147  source.agent,
148  [result, err = std::move(
149  input.error() )]() mutable noexcept
150  { result.setError( std::move( err ) ); } );
151  }
152  } );
153  return result;
154  }
155  namespace _private
156  {
157  template <class Flow, class Predicate> struct ApplyWhile
158  {
159  template <class F, class P>
160  ApplyWhile( F&& flow, P&& p )
161  : mFlow( std::forward<F>( flow ) ),
162  mPred( std::forward<P>( p ) )
163  {
164  }
165  // ~ApplyWhile() //PARA DEPURACION
166  // {
167  // mel::text::info("Destructor ApplyWhile");
168  // }
169  Flow mFlow;
170  Predicate mPred;
171  template <class TArg, class ExecutorAgent>
172  auto operator()( ExFuture<ExecutorAgent, TArg> inputFut )
173  {
174  return doWhile( inputFut, std::forward<Flow>( mFlow ),
175  std::forward<Predicate>( mPred ) );
176  }
177  };
178  } // namespace _private
179 
181  template <class Flow, class Predicate>
183  Predicate&& pred )
184  {
186  std::forward<Flow>( flow ),
187  std::forward<Predicate>( pred ) );
188  }
189  } // namespace flow
190  } // namespace execution
191 } // namespace mel
int subscribeCallback(F &&f) const
Subscribe callback to be executed when future is ready (valid or error)
Definition: Future.h:681
const _private::FutureData< T >::ValueType & getValue() const
Get the Value object.
Definition: Future.h:613
Executor< ExecutorAgent > agent
execution agent associated with this instance
Definition: ExFuture.h:54
auto doWhile(ExFuture< ExecutorAgent, TArg > source, Flow flow, Predicate p)
do...while a flow
Definition: While.h:116
Definition: Callback_Impl.h:11