Orocos Real-Time Toolkit  2.8.3
FusedFunctorDataSource.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 FusedFunctorDataSource.hpp
3 
4  FusedFunctorDataSource.hpp - description
5  -------------------
6  begin : Tue September 07 2010
7  copyright : (C) 2010 The SourceWorks
8  email : peter@thesourceworks.com
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 #ifndef ORO_FUSEDFUNCTORDATASOURCE_HPP_
40 #define ORO_FUSEDFUNCTORDATASOURCE_HPP_
41 
42 #include "DataSource.hpp"
43 #include "CreateSequence.hpp"
44 #include "../SendStatus.hpp"
45 #include "BindStorage.hpp"
46 #include "../ExecutionEngine.hpp"
47 #include "../os/oro_allocator.hpp"
48 #include "UnMember.hpp"
49 #include <boost/bind.hpp>
50 #include <boost/type_traits.hpp>
51 #include <boost/function.hpp>
52 #include <boost/function_types/function_type.hpp>
53 #include <boost/fusion/include/invoke.hpp>
54 #include <boost/fusion/include/invoke_procedure.hpp>
55 #include <boost/mpl/bool.hpp>
56 #include <boost/make_shared.hpp>
57 
58 namespace RTT
59 {
60  namespace internal
61  {
62  namespace bf = boost::fusion;
63 
69  template<typename Signature, class Enable=void>
71  : public DataSource<
72  typename remove_cr<typename boost::function_traits<Signature>::result_type>::type >
73  {
74  //BOOST_STATIC_ASSERT( boost::mpl::false_::value );
75  typedef typename boost::function_traits<Signature>::result_type
79  typedef create_sequence<
80  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
82  typedef boost::function<Signature> call_type;
84  boost::function<Signature> ff;
85  DataSourceSequence args;
87  public:
88  typedef boost::intrusive_ptr<FusedFunctorDataSource<Signature> >
90 
91  template<class Func>
93  const DataSourceSequence& s = DataSourceSequence() ) :
94  ff(g), args(s)
95  {
96  }
97 
98  void setArguments(const DataSourceSequence& a1)
99  {
100  args = a1;
101  }
102 
103  value_t value() const
104  {
105  return ret.result();
106  }
107 
108  const_reference_t rvalue() const
109  {
110  return ret.result();
111  }
112 
113  bool evaluate() const {
114  // forward invoke to ret object, which stores return value.
115  // this foo pointer dance is because older compilers don't handle using
116  // &bf::invoke<call_type,arg_type> directly.
117  typedef typename bf::result_of::invoke<call_type,arg_type>::type iret;
118  typedef iret(*IType)(call_type, arg_type const&);
119  IType foo = &bf::invoke<call_type,arg_type>;
120  ret.exec( boost::bind(foo, boost::ref(ff), SequenceFactory::data(args)));
122  return true;
123  }
124 
125  value_t get() const
126  {
128  return ret.result();
129  }
130 
132  {
134  }
136  std::map<
137  const base::DataSourceBase*,
138  base::DataSourceBase*>& alreadyCloned) const
139  {
140  return new FusedFunctorDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
141  }
142  };
143 
144  template<typename Signature>
145  struct FusedFunctorDataSource<Signature, typename boost::enable_if< is_pure_reference<typename boost::function_traits<Signature>::result_type> >::type >
146  : public AssignableDataSource<
147  typename remove_cr<typename boost::function_traits<Signature>::result_type>::type >
148  {
149  //BOOST_STATIC_ASSERT( boost::mpl::false_::value );
150  typedef typename boost::function_traits<Signature>::result_type
155  typedef create_sequence<
156  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
158  typedef boost::function<Signature> call_type;
160  boost::function<Signature> ff;
161  DataSourceSequence args;
163  public:
164  typedef boost::intrusive_ptr<FusedFunctorDataSource<Signature> >
166 
167  template<class Func>
169  const DataSourceSequence& s = DataSourceSequence() ) :
170  ff(g), args(s)
171  {
172  }
173 
174  void setArguments(const DataSourceSequence& a1)
175  {
176  args = a1;
177  }
178 
179  value_t value() const
180  {
181  return ret.result();
182  }
183 
184  const_reference_t rvalue() const
185  {
186  return ret.result();
187  }
188 
189  bool evaluate() const {
190  // forward invoke to ret object, which stores return value.
191  // this foo pointer dance is because older compilers don't handle using
192  // &bf::invoke<call_type,arg_type> directly.
193  typedef typename bf::result_of::invoke<call_type,arg_type>::type iret;
194  typedef iret(*IType)(call_type, arg_type const&);
195  IType foo = &bf::invoke<call_type,arg_type>;
196  ret.exec( boost::bind(foo, boost::ref(ff), SequenceFactory::data(args)));
198  return true;
199  }
200  value_t get() const
201  {
203  return ret.result();
204  }
205 
206  void set( typename AssignableDataSource<value_t>::param_t arg) {
207  // we need to get the new reference before we set the arg.
208  get(); ret.result() = arg;
209  }
210 
211  reference_t set() {
212  get(); return ret.result();
213  }
214 
216  {
218  }
220  std::map<
221  const base::DataSourceBase*,
222  base::DataSourceBase*>& alreadyCloned) const
223  {
224  return new FusedFunctorDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
225  }
226  };
237  template<class Function>
238  base::DataSourceBase* newFunctorDataSource(Function f, const std::vector<base::DataSourceBase::shared_ptr>& args)
239  {
240  typedef typename boost::function_types::function_type<Function>::type Signature;
242  if ( args.size() != boost::function_traits<Signature>::arity )
243  throw wrong_number_of_args_exception(boost::function_traits<Signature>::arity, args.size() );
244  return new FusedFunctorDataSource<Signature>(f, SequenceFactory::sources(args.begin()));
245  }
246 
252  template<typename Signature>
254  : public DataSource<
255  typename remove_cr<typename boost::function_traits<Signature>::result_type>::type >
256  {
257  typedef typename boost::function_traits<Signature>::result_type
261  typedef create_sequence<
262  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
265  DataSourceSequence args;
267  public:
268  typedef boost::intrusive_ptr<FusedMCallDataSource<Signature> >
270 
272  const DataSourceSequence& s = DataSourceSequence() ) :
273  ff(g), args(s)
274  {
275  }
276 
277  void setArguments(const DataSourceSequence& a1)
278  {
279  args = a1;
280  }
281 
282  value_t value() const
283  {
284  return ret.result();
285  }
286 
287  const_reference_t rvalue() const
288  {
289  return ret.result();
290  }
291 
292  bool evaluate() const {
293  // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type.
294  typedef bf::cons<base::OperationCallerBase<Signature>*, typename SequenceFactory::data_type> arg_type;
296  // this foo pointer dance is because older compilers don't handle using
297  // &bf::invoke<call_type,arg_type> directly.
298  typedef typename bf::result_of::invoke<call_type,arg_type>::type iret;
299  typedef iret(*IType)(call_type, arg_type const&);
300  IType foo = &bf::invoke<call_type,arg_type>;
301  // we need to store the ret value ourselves.
302  ret.exec( boost::bind(foo, &base::OperationCallerBase<Signature>::call, arg_type(ff.get(), SequenceFactory::data(args))) );
303  if(ret.isError()) {
304  ff->reportError();
305  ret.checkError();
306  }
308  return true;
309  }
310 
311  value_t get() const
312  {
313  evaluate();
314  return ret.result();
315  }
316 
318  {
320  }
322  std::map<
323  const base::DataSourceBase*,
324  base::DataSourceBase*>& alreadyCloned) const
325  {
326  return new FusedMCallDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
327  }
328  };
329 
334  template<typename Signature>
336  : public DataSource<SendHandle<Signature> >
337  {
339  typedef result_type value_t;
341  typedef create_sequence<
342  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
345  DataSourceSequence args;
346  mutable SendHandle<Signature> sh; // mutable because of get() const
347  public:
348  typedef boost::intrusive_ptr<FusedMSendDataSource<Signature> >
350 
352  const DataSourceSequence& s = DataSourceSequence() ) :
353  ff(g), args(s)
354  {
355  }
356 
357  void setArguments(const DataSourceSequence& a1)
358  {
359  args = a1;
360  }
361 
362  value_t value() const
363  {
364  return sh;
365  }
366 
367  const_reference_t rvalue() const
368  {
369  return sh;
370  }
371 
372  value_t get() const
373  {
374  // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type.
376  return sh;
377  }
378 
380  {
382  }
384  std::map<
385  const base::DataSourceBase*,
386  base::DataSourceBase*>& alreadyCloned) const
387  {
388  return new FusedMSendDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
389  }
390  };
391 
398  template<typename Signature>
400  : public DataSource<SendStatus>
401  {
403  typedef result_type value_t;
405  // push the SendHandle pointer in front.
407  typedef typename boost::function_types::parameter_types<CollectSignature>::type arg_types;
408  typedef typename mpl::push_front<arg_types, SendHandle<Signature>& >::type handle_and_arg_types;
409  typedef create_sequence< handle_and_arg_types
412  DataSourceSequence args;
414  mutable SendStatus ss; // because of get() const
415  public:
416  typedef boost::intrusive_ptr<FusedMCollectDataSource<Signature> >
418 
420  const DataSourceSequence& s, DataSource<bool>::shared_ptr blocking ) :
421  args(s), isblocking(blocking), ss(SendFailure)
422  {
423  }
424 
425  void setArguments(const DataSourceSequence& a1)
426  {
427  args = a1;
428  }
429 
430  value_t value() const
431  {
432  return ss;
433  }
434 
435  const_reference_t rvalue() const
436  {
437  return ss;
438  }
439 
440  value_t get() const
441  {
442  // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type.
443  if (isblocking->get())
445  else
448  return ss;
449  }
450 
452  {
453  return new FusedMCollectDataSource<Signature> ( args, isblocking);
454  }
456  std::map<
457  const base::DataSourceBase*,
458  base::DataSourceBase*>& alreadyCloned) const
459  {
460  return new FusedMCollectDataSource<Signature> ( SequenceFactory::copy(args, alreadyCloned), isblocking);
461  }
462  };
463 
468  template<typename Signature>
470  {
471  typedef typename boost::function_traits<Signature>::result_type
473  typedef result_type value_t;
474  typedef create_sequence<
475  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
477  boost::shared_ptr<base::ActionInterface> mact;
478  DataSourceSequence args;
485  boost::shared_ptr<FusedMSignal<Signature> > self;
486  public:
487  typedef boost::shared_ptr<FusedMSignal<Signature> > shared_ptr;
488 
497  const DataSourceSequence& s,
498  ExecutionEngine* subscr ) :
499  mact(act), args(s), subscriber(subscr), self()
500  {
501  }
502 
504  }
505 
511  result_type invoke(const typename SequenceFactory::data_type& seq) const {
512  if ( subscriber ) {
513  // asynchronous
514  shared_ptr sg = this->cloneRT();
515  SequenceFactory::set( seq, sg->args );
516 
517  sg->self = sg;
518  if ( subscriber->process( sg.get() ) ) {
519  // all ok
520  } else {
521  sg->dispose();
522  }
523  } else {
524  // synchronous
525  SequenceFactory::set( seq, args );
526  mact->execute();
527  }
528 
529  return NA<result_type>::na();
530  }
531 
533  mact->execute();
534  dispose();
535  }
536 
541  void dispose() {
542  self.reset();
543  }
544 
545 
546  void setArguments(const DataSourceSequence& a1)
547  {
548  args = a1;
549  }
550 
552  {
553  // returns identical copy of this;
554  return boost::allocate_shared<FusedMSignal<Signature> >(os::rt_allocator<FusedMSignal<Signature> >(), *this);
555  }
556  };
557 
558  }
559 }
560 
561 #endif /* ORO_FUSEDFUNCTORDATASOURCE_HPP_ */
boost::function_traits< Signature >::result_type result_type
DataSource is a base class representing a generic way to read data of type T.
Definition: DataSource.hpp:94
boost::intrusive_ptr< FusedFunctorDataSource< Signature > > shared_ptr
value_t value() const
Return the result of the last evaluate() function.
boost::function_traits< Signature >::result_type result_type
virtual result_t get() const =0
Return the data as type T.
create_sequence< typename boost::function_types::parameter_types< Signature >::type > SequenceFactory
FusedMSignal< Signature >::shared_ptr cloneRT() const
bool evaluate() const
Force an evaluation of the DataSourceBase.
void executeAndDispose()
Execute functionality and free this object.
const_reference_t rvalue() const
Get a const reference to the value of this DataSource.
virtual FusedMCallDataSource< Signature > * clone() const
Return a shallow clone of this DataSource.
The inverse of UnMember.
The base class for all internal data representations.
This class can create three kinds of Boost Fusion Sequences.
remove_cr< result_type >::type value_t
static T na()
Definition: NA.hpp:57
SequenceFactory::atype DataSourceSequence
value_t value() const
Return the result of the last evaluate() function.
void exec(F f)
Stores the result of a function.
void setArguments(const DataSourceSequence &a1)
DataSource< value_t >::const_reference_t const_reference_t
base::DataSourceBase * newFunctorDataSource(Function f, const std::vector< base::DataSourceBase::shared_ptr > &args)
Creates a data source that returns the result of a given function.
FusedMSendDataSource(typename base::OperationCallerBase< Signature >::shared_ptr g, const DataSourceSequence &s=DataSourceSequence())
value_t value() const
Return the result of the last evaluate() function.
A real-time malloc allocator which allocates every block with oro_rt_malloc() and deallocates with or...
virtual FusedMSendDataSource< Signature > * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned) const
Create a deep copy of this internal::DataSource, unless it is already cloned.
A DataSource that collects the result of an asynchronous method which store its results in other data...
remove_cr< result_type >::type value_t
value_t value() const
Return the result of the last evaluate() function.
boost::intrusive_ptr< FusedMSendDataSource< Signature > > shared_ptr
DataSource< value_t >::const_reference_t const_reference_t
boost::function_traits< Signature >::result_type result_type
void reportError()
Executed when the operation execution resulted in a C++ exception.
The base class for all method implementations.
virtual FusedFunctorDataSource< Signature > * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned) const
Create a deep copy of this internal::DataSource, unless it is already cloned.
FusedFunctorDataSource(Func g, const DataSourceSequence &s=DataSourceSequence())
void setArguments(const DataSourceSequence &a1)
CollectType< Signature >::type CollectSignature
An execution engine serialises (executes one after the other) the execution of all commands...
SendStatus
Returns the status of a send() or collect() invocation.
Definition: SendStatus.hpp:53
DataSource< value_t >::const_reference_t const_reference_t
A DataSource that calls a method which gets its arguments from other data sources.
boost::shared_ptr< OperationCallerBase< F > > shared_ptr
boost::intrusive_ptr< FusedMCollectDataSource< Signature > > shared_ptr
static data_type data(const type &seq)
Returns the data contained in the data sources as a Fusion Sequence.
void setArguments(const DataSourceSequence &a1)
The SendHandle is used to collect the result values of an asynchronous invocation.
Definition: rtt-fwd.hpp:79
create_sequence< typename boost::function_types::parameter_types< Signature >::type > SequenceFactory
FusedMCallDataSource(typename base::OperationCallerBase< Signature >::shared_ptr g, const DataSourceSequence &s=DataSourceSequence())
static type copy(const type &seq, std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned)
Copies a sequence of DataSource<T>::shared_ptr according to the copy/clone semantics of data sources...
Returned when the result of the send() could not be collected.
Definition: SendStatus.hpp:55
static type sources(std::vector< base::DataSourceBase::shared_ptr >::const_iterator args, int argnbr=1)
Converts a std::vector of DataSourceBase types into a boost::fusion Sequence of DataSources of the ty...
FusedMCollectDataSource(const DataSourceSequence &s, DataSource< bool >::shared_ptr blocking)
create_sequence< typename boost::function_types::parameter_types< Signature >::type > SequenceFactory
Based on the software pattern &#39;command&#39;, this interface allows execution of action objects...
base::OperationCallerBase< Signature >::shared_ptr ff
boost::intrusive_ptr< FusedMCallDataSource< Signature > > shared_ptr
result_type invoke(const typename SequenceFactory::data_type &seq) const
A Fused function that takes the arguments of the signal, puts them into the assignable data sources a...
const_reference_t rvalue() const
Get a const reference to the value of this DataSource.
virtual FusedMCollectDataSource< Signature > * clone() const
Return a shallow clone of this DataSource.
bf::cons< arg_type, arg_tail_type > data_type
The joint T data type of head and tail.
An object that is executable and is freed after execution.
base::OperationCallerBase< Signature >::shared_ptr ff
virtual FusedMSendDataSource< Signature > * clone() const
Return a shallow clone of this DataSource.
DataSource< SendStatus >::const_reference_t const_reference_t
const_reference_t rvalue() const
Get a const reference to the value of this DataSource.
FusedMSignal(base::ActionInterface *act, const DataSourceSequence &s, ExecutionEngine *subscr)
Create a new object which takes ownership of the action to be executed upon signal.
boost::function_types::parameter_types< CollectSignature >::type arg_types
const_reference_t rvalue() const
Get a const reference to the value of this DataSource.
bf::cons< ds_type, tail_type > type
The joint DataSource<T>::shared_ptr type of head and tail, again a fusion cons.
A DataSource which has set() methods.
Definition: DataSource.hpp:184
void setArguments(const DataSourceSequence &a1)
void dispose()
As long as dispose (or executeAndDispose() ) is not called, this object will not be destroyed...
void setArguments(const DataSourceSequence &a1)
boost::remove_const< typename boost::remove_reference< T >::type >::type type
Definition: mystd.hpp:63
Exception thrown when a factory is requested to create an object but the wrong number of arguments wa...
virtual FusedMCollectDataSource< Signature > * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned) const
Create a deep copy of this internal::DataSource, unless it is already cloned.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:51
static void set(const data_type &in, const atype &seq)
Sets the values of a sequence of AssignableDataSource<T> data sources ot the values contained in in u...
virtual bool process(base::DisposableInterface *c)
Queue and execute (process) a given message.
bool evaluate() const
Force an evaluation of the DataSourceBase.
mpl::push_front< arg_types, SendHandle< Signature > & >::type handle_and_arg_types
static void update(const type &seq)
Calls the DataSourceBase::updated() function for each element in sequence seq, in case the element is...
virtual FusedFunctorDataSource< Signature > * clone() const
Return a shallow clone of this DataSource.
virtual FusedFunctorDataSource< Signature > * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned) const
Create a deep copy of this internal::DataSource, unless it is already cloned.
details::GetConstRef< T >::type const_reference_t
Definition: DataSource.hpp:107
create_sequence< typename boost::function_types::parameter_types< Signature >::type > SequenceFactory
A Function object that reacts to a Signal by writing the arguments in data sources and calling an act...
create_sequence< handle_and_arg_types > SequenceFactory
boost::shared_ptr< base::ActionInterface > mact
A DataSource that sends a method which gets its arguments from other data sources.
virtual FusedMCallDataSource< Signature > * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned) const
Create a deep copy of this internal::DataSource, unless it is already cloned.
boost::shared_ptr< FusedMSignal< Signature > > shared_ptr
A DataSource that calls a functor of signature Signature which gets its arguments from other data sou...