Orocos Real-Time Toolkit  2.9.0
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 #include <iostream>
59 using namespace std;
60 
61 namespace RTT
62 {
63  namespace internal
64  {
65  namespace bf = boost::fusion;
66 
72  template<typename Signature, class Enable=void>
74  : public DataSource<
75  typename remove_cr<typename boost::function_traits<Signature>::result_type>::type >
76  {
77  //BOOST_STATIC_ASSERT( boost::mpl::false_::value );
78  typedef typename boost::function_traits<Signature>::result_type
82  typedef create_sequence<
83  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
85  typedef boost::function<Signature> call_type;
87  boost::function<Signature> ff;
88  DataSourceSequence args;
90  public:
91  typedef boost::intrusive_ptr<FusedFunctorDataSource<Signature> >
93 
94  template<class Func>
96  const DataSourceSequence& s = DataSourceSequence() ) :
97  ff(g), args(s)
98  {
99  }
100 
101  void setArguments(const DataSourceSequence& a1)
102  {
103  args = a1;
104  }
105 
106  value_t value() const
107  {
108  return ret.result();
109  }
110 
111  const_reference_t rvalue() const
112  {
113  return ret.result();
114  }
115 
116  bool evaluate() const {
117  // forward invoke to ret object, which stores return value.
118  // this foo pointer dance is because older compilers don't handle using
119  // &bf::invoke<call_type,arg_type> directly.
120  typedef typename bf::result_of::invoke<call_type,arg_type>::type iret;
121  typedef iret(*IType)(call_type, arg_type const&);
122  IType foo = &bf::invoke<call_type,arg_type>;
123  ret.exec( boost::bind(foo, boost::ref(ff), SequenceFactory::data(args)));
124  SequenceFactory::update(args);
125  return true;
126  }
127 
128  value_t get() const
129  {
131  return ret.result();
132  }
133 
135  {
136  return new FusedFunctorDataSource<Signature> (ff, args);
137  }
139  std::map<
140  const base::DataSourceBase*,
141  base::DataSourceBase*>& alreadyCloned) const
142  {
143  return new FusedFunctorDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
144  }
145  };
146 
147  template<typename Signature>
148  struct FusedFunctorDataSource<Signature, typename boost::enable_if< is_pure_reference<typename boost::function_traits<Signature>::result_type> >::type >
149  : public AssignableDataSource<
150  typename remove_cr<typename boost::function_traits<Signature>::result_type>::type >
151  {
152  //BOOST_STATIC_ASSERT( boost::mpl::false_::value );
153  typedef typename boost::function_traits<Signature>::result_type
158  typedef create_sequence<
159  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
160  typedef typename SequenceFactory::type DataSourceSequence;
161  typedef boost::function<Signature> call_type;
163  boost::function<Signature> ff;
164  DataSourceSequence args;
166  public:
167  typedef boost::intrusive_ptr<FusedFunctorDataSource<Signature> >
169 
170  template<class Func>
172  const DataSourceSequence& s = DataSourceSequence() ) :
173  ff(g), args(s)
174  {
175  }
176 
177  void setArguments(const DataSourceSequence& a1)
178  {
179  args = a1;
180  }
181 
182  value_t value() const
183  {
184  return ret.result();
185  }
186 
187  const_reference_t rvalue() const
188  {
189  return ret.result();
190  }
191 
192  bool evaluate() const {
193  // forward invoke to ret object, which stores return value.
194  // this foo pointer dance is because older compilers don't handle using
195  // &bf::invoke<call_type,arg_type> directly.
196  typedef typename bf::result_of::invoke<call_type,arg_type>::type iret;
197  typedef iret(*IType)(call_type, arg_type const&);
198  IType foo = &bf::invoke<call_type,arg_type>;
199  ret.exec( boost::bind(foo, boost::ref(ff), SequenceFactory::data(args)));
200  SequenceFactory::update(args);
201  return true;
202  }
203  value_t get() const
204  {
206  return ret.result();
207  }
208 
209  void set( typename AssignableDataSource<value_t>::param_t arg) {
210  // we need to get the new reference before we set the arg.
211  get(); ret.result() = arg;
212  }
213 
214  reference_t set() {
215  get(); return ret.result();
216  }
217 
219  {
220  return new FusedFunctorDataSource<Signature> (ff, args);
221  }
223  std::map<
224  const base::DataSourceBase*,
225  base::DataSourceBase*>& alreadyCloned) const
226  {
227  return new FusedFunctorDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
228  }
229  };
240  template<class Function>
241  base::DataSourceBase* newFunctorDataSource(Function f, const std::vector<base::DataSourceBase::shared_ptr>& args)
242  {
243  typedef typename boost::function_types::function_type<Function>::type Signature;
245  if ( args.size() != boost::function_traits<Signature>::arity )
246  throw wrong_number_of_args_exception(boost::function_traits<Signature>::arity, args.size() );
247  return new FusedFunctorDataSource<Signature>(f, SequenceFactory::sources(args.begin()));
248  }
249 
255  template<typename Signature>
257  : public DataSource<
258  typename remove_cr<typename boost::function_traits<Signature>::result_type>::type >
259  {
260  typedef typename boost::function_traits<Signature>::result_type
264  typedef create_sequence<
265  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
268  DataSourceSequence args;
270  public:
271  typedef boost::intrusive_ptr<FusedMCallDataSource<Signature> >
273 
275  const DataSourceSequence& s = DataSourceSequence() ) :
276  ff(g), args(s)
277  {
278  }
279 
280  void setArguments(const DataSourceSequence& a1)
281  {
282  args = a1;
283  }
284 
285  value_t value() const
286  {
287  return ret.result();
288  }
289 
290  const_reference_t rvalue() const
291  {
292  return ret.result();
293  }
294 
295  bool evaluate() const {
296  // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type.
297  typedef bf::cons<base::OperationCallerBase<Signature>*, typename SequenceFactory::data_type> arg_type;
298  typedef typename AddMember<Signature,base::OperationCallerBase<Signature>* >::type call_type;
299  // this foo pointer dance is because older compilers don't handle using
300  // &bf::invoke<call_type,arg_type> directly.
301  typedef typename bf::result_of::invoke<call_type,arg_type>::type iret;
302  typedef iret(*IType)(call_type, arg_type const&);
303  IType foo = &bf::invoke<call_type,arg_type>;
304  // we need to store the ret value ourselves.
305  ret.exec( boost::bind(foo, &base::OperationCallerBase<Signature>::call, arg_type(ff.get(), SequenceFactory::data(args))) );
306  if(ret.isError()) {
307  ff->reportError();
308  ret.checkError();
309  }
310  SequenceFactory::update(args);
311  return true;
312  }
313 
314  value_t get() const
315  {
316  evaluate();
317  return ret.result();
318  }
319 
321  {
322  return new FusedMCallDataSource<Signature> (ff, args);
323  }
325  std::map<
326  const base::DataSourceBase*,
327  base::DataSourceBase*>& alreadyCloned) const
328  {
329  return new FusedMCallDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
330  }
331  };
332 
337  template<typename Signature>
339  : public AssignableDataSource<SendHandle<Signature> >
340  {
342  typedef result_type value_t;
346  typedef create_sequence<
347  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
350  DataSourceSequence args;
351  mutable SendHandle<Signature> sh; // mutable because of get() const
352  mutable bool isqueued;
353  public:
354  typedef boost::intrusive_ptr<FusedMSendDataSource<Signature> >
356 
358  const DataSourceSequence& s = DataSourceSequence() ) :
359  ff(g), args(s), sh(), isqueued(false)
360  {
361  }
362 
363  void setArguments(const DataSourceSequence& a1)
364  {
365  args = a1;
366  }
367 
368  virtual void set( param_t t ) {
369  sh = t;
370  }
371 
372  reference_t set() {
373  return sh;
374  }
375 
376  value_t value() const
377  {
378  return sh;
379  }
380 
381  const_reference_t rvalue() const
382  {
383  return sh;
384  }
385 
386  value_t get() const
387  {
388  if (isqueued)
389  return sh;
390  // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type.
391  sh = bf::invoke(&base::OperationCallerBase<Signature>::send, bf::cons<base::OperationCallerBase<Signature>*, typename SequenceFactory::data_type>(ff.get(), SequenceFactory::data(args)));
392  if ( sh.ready() ) // only queued if sh contains a collectable operation
393  isqueued = true;
394  return sh;
395  }
396 
397  void reset() {
398  isqueued = false;
399  }
400 
402  {
403  return new FusedMSendDataSource<Signature> (ff, args);
404  }
405 
407  std::map<
408  const base::DataSourceBase*,
409  base::DataSourceBase*>& alreadyCloned) const
410  {
411  // we need copy semantics because FusedMCollectDataSource tracks us.
412  if ( alreadyCloned[this] != 0 ) {
413  assert( dynamic_cast<FusedMSendDataSource<Signature>*>( alreadyCloned[this] ) == static_cast<FusedMSendDataSource<Signature>*>( alreadyCloned[this] ) );
414  return static_cast<FusedMSendDataSource<Signature>*>( alreadyCloned[this] );
415  }
416  // Other pieces in the code rely on insertion in the map :
417  alreadyCloned[this] = new FusedMSendDataSource<Signature>(ff, SequenceFactory::copy(args, alreadyCloned));
418  // return copy
419  return static_cast<FusedMSendDataSource<Signature>*>( alreadyCloned[this] );
420  }
421  };
422 
429  template<typename Signature>
431  : public DataSource<SendStatus>
432  {
434  typedef result_type value_t;
436  // push the SendHandle pointer in front.
438  typedef typename boost::function_types::parameter_types<CollectSignature>::type arg_types;
439  typedef typename mpl::push_front<arg_types, SendHandle<Signature>& >::type handle_and_arg_types;
440  typedef create_sequence< handle_and_arg_types
443  DataSourceSequence args;
445  mutable SendStatus ss; // because of get() const
446  public:
447  typedef boost::intrusive_ptr<FusedMCollectDataSource<Signature> >
449 
451  const DataSourceSequence& s, DataSource<bool>::shared_ptr blocking ) :
452  args(s), isblocking(blocking), ss(SendFailure)
453  {
454  }
455 
456  void setArguments(const DataSourceSequence& a1)
457  {
458  args = a1;
459  }
460 
461  value_t value() const
462  {
463  return ss;
464  }
465 
466  const_reference_t rvalue() const
467  {
468  return ss;
469  }
470 
471  value_t get() const
472  {
473  // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type.
474  if (isblocking->get())
475  ss = bf::invoke(&SendHandle<Signature>::CBase::collect, SequenceFactory::data(args));
476  else
477  ss = bf::invoke(&SendHandle<Signature>::CBase::collectIfDone, SequenceFactory::data(args));
478  SequenceFactory::update(args);
479  return ss;
480  }
481 
483  {
484  return new FusedMCollectDataSource<Signature> ( args, isblocking);
485  }
486 
488  std::map<
489  const base::DataSourceBase*,
490  base::DataSourceBase*>& alreadyCloned) const
491  {
492  // we need copy semantics because CmdCollectCondition tracks us.
493  // WARNING: This is a tricky precedent... should all DataSources with state + multiple living references then implement this ? Should we assert on this ?
494  if ( alreadyCloned[this] != 0 ) {
495  assert ( dynamic_cast<FusedMCollectDataSource<Signature>*>( alreadyCloned[this] ) == static_cast<FusedMCollectDataSource<Signature>*>( alreadyCloned[this] ) );
496  return static_cast<FusedMCollectDataSource<Signature>*>( alreadyCloned[this] );
497  }
498  // Other pieces in the code rely on insertion in the map :
499  alreadyCloned[this] = new FusedMCollectDataSource<Signature>(SequenceFactory::copy(args, alreadyCloned), isblocking);
500  // return copy
501  return static_cast<FusedMCollectDataSource<Signature>*>( alreadyCloned[this] );
502  }
503  };
504 
513  template<typename Signature>
515  {
516  typedef typename boost::function_traits<Signature>::result_type
518  typedef result_type value_t;
519  typedef create_sequence<
520  typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
522  boost::shared_ptr<base::ActionInterface> mact;
523  // We need the arg_cache to store data similar to BindStorage,
524  // such that we can safely access it during execute().
526  DataSourceSequence args;
533  boost::shared_ptr<FusedMSignal<Signature> > self;
534  public:
535  typedef boost::shared_ptr<FusedMSignal<Signature> > shared_ptr;
536 
545  const DataSourceSequence& s,
546  ExecutionEngine* subscr ) :
547  mact(act), args(s), subscriber(subscr), self()
548  {
549  }
550 
552  }
553 
559  result_type invoke(const typename SequenceFactory::data_type& seq) const {
560  if ( subscriber ) {
561  // asynchronous
562  shared_ptr sg = this->cloneRT();
563  sg->arg_cache = SequenceFactory::store(seq);
564  sg->self = sg;
565  if ( subscriber->process( sg.get() ) ) {
566  // all ok
567  } else {
568  sg->dispose();
569  }
570  } else {
571  // synchronous
572  SequenceFactory::set( seq, args );
573  mact->execute();
574  }
575 
576  return NA<result_type>::na();
577  }
578 
580  SequenceFactory::load( this->arg_cache, this->args );
581  mact->execute();
582  dispose();
583  }
584 
589  void dispose() {
590  self.reset();
591  }
592 
593 
594  void setArguments(const DataSourceSequence& a1)
595  {
596  args = a1;
597  }
598 
600  {
601  // returns identical copy of this;
602  return boost::allocate_shared<FusedMSignal<Signature> >(os::rt_allocator<FusedMSignal<Signature> >(), *this);
603  }
604  };
605 
606  }
607 }
608 
609 #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
bf::cons< arg_store_type, arg_store_tail_type > data_store_type
The joint T data storage type of head and tail.
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
SequenceFactory::atype DataSourceSequence
value_t value() const
Return the result of the last evaluate() function.
SequenceFactory::data_store_type arg_cache
void exec(F f)
Stores the result of a function.
void setArguments(const DataSourceSequence &a1)
void reset()
Reset the data to initial values.
STL namespace.
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
AssignableDataSource< value_t >::reference_t reference_t
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
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())
Returned when the result of the send() could not be collected.
Definition: SendStatus.hpp:55
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.
This class is used to return a &#39;default&#39; value when no value is available (&#39;Not Available&#39;).
Definition: NA.hpp:53
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
AssignableDataSource< value_t >::const_reference_t const_reference_t
virtual FusedMSendDataSource< Signature > * clone() const
Return a shallow clone of this DataSource.
DataSource< SendStatus >::const_reference_t const_reference_t
AssignableDataSource< value_t >::param_t param_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:52
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
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...
bool ready() const
Inspect if this SendHandle is pointing to valid (existing) invocation.
Definition: SendHandle.hpp:117
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...