00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef ORO_FUSEDFUNCTORDATASOURCE_HPP_
00040 #define ORO_FUSEDFUNCTORDATASOURCE_HPP_
00041
00042 #include "DataSource.hpp"
00043 #include "CreateSequence.hpp"
00044 #include "../SendStatus.hpp"
00045 #include "BindStorage.hpp"
00046 #include <boost/bind.hpp>
00047 #include <boost/type_traits.hpp>
00048 #include <boost/function.hpp>
00049 #include <boost/function_types/function_type.hpp>
00050 #include <boost/fusion/include/invoke.hpp>
00051 #include <boost/fusion/include/invoke_procedure.hpp>
00052 #include <boost/mpl/bool.hpp>
00053
00054 namespace RTT
00055 {
00056 namespace internal
00057 {
00058 namespace bf = boost::fusion;
00059
00065 template<typename Signature, class Enable=void>
00066 struct FusedFunctorDataSource
00067 : public DataSource<
00068 typename remove_cr<typename boost::function_traits<Signature>::result_type>::type >
00069 {
00070
00071 typedef typename boost::function_traits<Signature>::result_type
00072 result_type;
00073 typedef typename remove_cr<result_type>::type value_t;
00074 typedef typename DataSource<value_t>::const_reference_t const_reference_t;
00075 typedef create_sequence<
00076 typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00077 typedef typename SequenceFactory::type DataSourceSequence;
00078 typedef boost::function<Signature> call_type;
00079 typedef typename SequenceFactory::data_type arg_type;
00080 boost::function<Signature> ff;
00081 DataSourceSequence args;
00082 mutable RStore<result_type> ret;
00083 public:
00084 typedef boost::intrusive_ptr<FusedFunctorDataSource<Signature> >
00085 shared_ptr;
00086
00087 template<class Func>
00088 FusedFunctorDataSource(Func g,
00089 const DataSourceSequence& s = DataSourceSequence() ) :
00090 ff(g), args(s)
00091 {
00092 }
00093
00094 void setArguments(const DataSourceSequence& a1)
00095 {
00096 args = a1;
00097 }
00098
00099 value_t value() const
00100 {
00101 return ret.result();
00102 }
00103
00104 const_reference_t rvalue() const
00105 {
00106 return ret.result();
00107 }
00108
00109 bool evaluate() const {
00110
00111
00112
00113 typedef typename bf::result_of::invoke<call_type,arg_type>::type iret;
00114 typedef iret(*IType)(call_type, arg_type const&);
00115 IType foo = &bf::invoke<call_type,arg_type>;
00116 ret.exec( boost::bind(foo, boost::ref(ff), SequenceFactory::data(args)));
00117 SequenceFactory::update(args);
00118 return true;
00119 }
00120
00121 value_t get() const
00122 {
00123 FusedFunctorDataSource<Signature>::evaluate();
00124 return ret.result();
00125 }
00126
00127 virtual FusedFunctorDataSource<Signature>* clone() const
00128 {
00129 return new FusedFunctorDataSource<Signature> (ff, args);
00130 }
00131 virtual FusedFunctorDataSource<Signature>* copy(
00132 std::map<
00133 const base::DataSourceBase*,
00134 base::DataSourceBase*>& alreadyCloned) const
00135 {
00136 return new FusedFunctorDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
00137 }
00138 };
00139
00140 template<typename Signature>
00141 struct FusedFunctorDataSource<Signature, typename boost::enable_if< is_pure_reference<typename boost::function_traits<Signature>::result_type> >::type >
00142 : public AssignableDataSource<
00143 typename remove_cr<typename boost::function_traits<Signature>::result_type>::type >
00144 {
00145
00146 typedef typename boost::function_traits<Signature>::result_type
00147 result_type;
00148 typedef typename remove_cr<result_type>::type value_t;
00149 typedef typename DataSource<value_t>::const_reference_t const_reference_t;
00150 typedef typename AssignableDataSource<value_t>::reference_t reference_t;
00151 typedef create_sequence<
00152 typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00153 typedef typename SequenceFactory::type DataSourceSequence;
00154 typedef boost::function<Signature> call_type;
00155 typedef typename SequenceFactory::data_type arg_type;
00156 boost::function<Signature> ff;
00157 DataSourceSequence args;
00158 mutable RStore<result_type> ret;
00159 public:
00160 typedef boost::intrusive_ptr<FusedFunctorDataSource<Signature> >
00161 shared_ptr;
00162
00163 template<class Func>
00164 FusedFunctorDataSource(Func g,
00165 const DataSourceSequence& s = DataSourceSequence() ) :
00166 ff(g), args(s)
00167 {
00168 }
00169
00170 void setArguments(const DataSourceSequence& a1)
00171 {
00172 args = a1;
00173 }
00174
00175 value_t value() const
00176 {
00177 return ret.result();
00178 }
00179
00180 const_reference_t rvalue() const
00181 {
00182 return ret.result();
00183 }
00184
00185 bool evaluate() const {
00186
00187
00188
00189 typedef typename bf::result_of::invoke<call_type,arg_type>::type iret;
00190 typedef iret(*IType)(call_type, arg_type const&);
00191 IType foo = &bf::invoke<call_type,arg_type>;
00192 ret.exec( boost::bind(foo, boost::ref(ff), SequenceFactory::data(args)));
00193 SequenceFactory::update(args);
00194 return true;
00195 }
00196 value_t get() const
00197 {
00198 FusedFunctorDataSource<Signature>::evaluate();
00199 return ret.result();
00200 }
00201
00202 void set( typename AssignableDataSource<value_t>::param_t arg) {
00203
00204 get(); ret.result() = arg;
00205 }
00206
00207 reference_t set() {
00208 get(); return ret.result();
00209 }
00210
00211 virtual FusedFunctorDataSource<Signature>* clone() const
00212 {
00213 return new FusedFunctorDataSource<Signature> (ff, args);
00214 }
00215 virtual FusedFunctorDataSource<Signature>* copy(
00216 std::map<
00217 const base::DataSourceBase*,
00218 base::DataSourceBase*>& alreadyCloned) const
00219 {
00220 return new FusedFunctorDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
00221 }
00222 };
00233 template<class Function>
00234 base::DataSourceBase* newFunctorDataSource(Function f, const std::vector<base::DataSourceBase::shared_ptr>& args)
00235 {
00236 typedef typename boost::function_types::function_type<Function>::type Signature;
00237 typedef internal::create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00238 if ( args.size() != boost::function_traits<Signature>::arity )
00239 throw wrong_number_of_args_exception(boost::function_traits<Signature>::arity, args.size() );
00240 return new FusedFunctorDataSource<Signature>(f, SequenceFactory::sources(args.begin()));
00241 }
00242
00248 template<typename Signature>
00249 struct FusedMCallDataSource
00250 : public DataSource<
00251 typename remove_cr<typename boost::function_traits<Signature>::result_type>::type >
00252 {
00253 typedef typename boost::function_traits<Signature>::result_type
00254 result_type;
00255 typedef typename remove_cr<result_type>::type value_t;
00256 typedef typename DataSource<value_t>::const_reference_t const_reference_t;
00257 typedef create_sequence<
00258 typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00259 typedef typename SequenceFactory::type DataSourceSequence;
00260 typename base::OperationCallerBase<Signature>::shared_ptr ff;
00261 DataSourceSequence args;
00262 mutable RStore<result_type> ret;
00263 public:
00264 typedef boost::intrusive_ptr<FusedMCallDataSource<Signature> >
00265 shared_ptr;
00266
00267 FusedMCallDataSource(typename base::OperationCallerBase<Signature>::shared_ptr g,
00268 const DataSourceSequence& s = DataSourceSequence() ) :
00269 ff(g), args(s)
00270 {
00271 }
00272
00273 void setArguments(const DataSourceSequence& a1)
00274 {
00275 args = a1;
00276 }
00277
00278 value_t value() const
00279 {
00280 return ret.result();
00281 }
00282
00283 const_reference_t rvalue() const
00284 {
00285 return ret.result();
00286 }
00287
00288 bool evaluate() const {
00289
00290 typedef bf::cons<base::OperationCallerBase<Signature>*, typename SequenceFactory::data_type> arg_type;
00291 typedef typename AddMember<Signature,base::OperationCallerBase<Signature>* >::type call_type;
00292
00293
00294 typedef typename bf::result_of::invoke<call_type,arg_type>::type iret;
00295 typedef iret(*IType)(call_type, arg_type const&);
00296 IType foo = &bf::invoke<call_type,arg_type>;
00297
00298 ret.exec( boost::bind(foo, &base::OperationCallerBase<Signature>::call, arg_type(ff.get(), SequenceFactory::data(args))) );
00299 SequenceFactory::update(args);
00300 return true;
00301 }
00302
00303 value_t get() const
00304 {
00305 FusedMCallDataSource<Signature>::evaluate();
00306 return ret.result();
00307 }
00308
00309 virtual FusedMCallDataSource<Signature>* clone() const
00310 {
00311 return new FusedMCallDataSource<Signature> (ff, args);
00312 }
00313 virtual FusedMCallDataSource<Signature>* copy(
00314 std::map<
00315 const base::DataSourceBase*,
00316 base::DataSourceBase*>& alreadyCloned) const
00317 {
00318 return new FusedMCallDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
00319 }
00320 };
00321
00326 template<typename Signature>
00327 struct FusedMSendDataSource
00328 : public DataSource<SendHandle<Signature> >
00329 {
00330 typedef SendHandle<Signature> result_type;
00331 typedef result_type value_t;
00332 typedef typename DataSource<value_t>::const_reference_t const_reference_t;
00333 typedef create_sequence<
00334 typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00335 typedef typename SequenceFactory::type DataSourceSequence;
00336 typename base::OperationCallerBase<Signature>::shared_ptr ff;
00337 DataSourceSequence args;
00338 mutable SendHandle<Signature> sh;
00339 public:
00340 typedef boost::intrusive_ptr<FusedMSendDataSource<Signature> >
00341 shared_ptr;
00342
00343 FusedMSendDataSource(typename base::OperationCallerBase<Signature>::shared_ptr g,
00344 const DataSourceSequence& s = DataSourceSequence() ) :
00345 ff(g), args(s)
00346 {
00347 }
00348
00349 void setArguments(const DataSourceSequence& a1)
00350 {
00351 args = a1;
00352 }
00353
00354 value_t value() const
00355 {
00356 return sh;
00357 }
00358
00359 const_reference_t rvalue() const
00360 {
00361 return sh;
00362 }
00363
00364 value_t get() const
00365 {
00366
00367 sh = bf::invoke(&base::OperationCallerBase<Signature>::send, bf::cons<base::OperationCallerBase<Signature>*, typename SequenceFactory::data_type>(ff.get(), SequenceFactory::data(args)));
00368 return sh;
00369 }
00370
00371 virtual FusedMSendDataSource<Signature>* clone() const
00372 {
00373 return new FusedMSendDataSource<Signature> (ff, args);
00374 }
00375 virtual FusedMSendDataSource<Signature>* copy(
00376 std::map<
00377 const base::DataSourceBase*,
00378 base::DataSourceBase*>& alreadyCloned) const
00379 {
00380 return new FusedMSendDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
00381 }
00382 };
00383
00390 template<typename Signature>
00391 struct FusedMCollectDataSource
00392 : public DataSource<SendStatus>
00393 {
00394 typedef SendStatus result_type;
00395 typedef result_type value_t;
00396 typedef DataSource<SendStatus>::const_reference_t const_reference_t;
00397
00398 typedef typename CollectType<Signature>::type CollectSignature;
00399 typedef typename boost::function_types::parameter_types<CollectSignature>::type arg_types;
00400 typedef typename mpl::push_front<arg_types, SendHandle<Signature>& >::type handle_and_arg_types;
00401 typedef create_sequence< handle_and_arg_types
00402 > SequenceFactory;
00403 typedef typename SequenceFactory::type DataSourceSequence;
00404 DataSourceSequence args;
00405 DataSource<bool>::shared_ptr isblocking;
00406 mutable SendStatus ss;
00407 public:
00408 typedef boost::intrusive_ptr<FusedMCollectDataSource<Signature> >
00409 shared_ptr;
00410
00411 FusedMCollectDataSource(
00412 const DataSourceSequence& s, DataSource<bool>::shared_ptr blocking ) :
00413 args(s), isblocking(blocking), ss(SendFailure)
00414 {
00415 }
00416
00417 void setArguments(const DataSourceSequence& a1)
00418 {
00419 args = a1;
00420 }
00421
00422 value_t value() const
00423 {
00424 return ss;
00425 }
00426
00427 const_reference_t rvalue() const
00428 {
00429 return ss;
00430 }
00431
00432 value_t get() const
00433 {
00434
00435 if (isblocking->get())
00436 ss = bf::invoke(&SendHandle<Signature>::CBase::collect, SequenceFactory::data(args));
00437 else
00438 ss = bf::invoke(&SendHandle<Signature>::CBase::collectIfDone, SequenceFactory::data(args));
00439 SequenceFactory::update(args);
00440 return ss;
00441 }
00442
00443 virtual FusedMCollectDataSource<Signature>* clone() const
00444 {
00445 return new FusedMCollectDataSource<Signature> ( args, isblocking);
00446 }
00447 virtual FusedMCollectDataSource<Signature>* copy(
00448 std::map<
00449 const base::DataSourceBase*,
00450 base::DataSourceBase*>& alreadyCloned) const
00451 {
00452 return new FusedMCollectDataSource<Signature> ( SequenceFactory::copy(args, alreadyCloned), isblocking);
00453 }
00454 };
00455
00460 template<typename Signature>
00461 struct FusedMSignal
00462 {
00463 typedef typename boost::function_traits<Signature>::result_type
00464 result_type;
00465 typedef result_type value_t;
00466 typedef create_sequence<
00467 typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00468 typedef typename SequenceFactory::atype DataSourceSequence;
00469 base::ActionInterface* mact;
00470 DataSourceSequence args;
00471 public:
00472 typedef boost::shared_ptr<FusedMSignal<Signature> >
00473 shared_ptr;
00474
00475 FusedMSignal(base::ActionInterface* act,
00476 const DataSourceSequence& s = DataSourceSequence() ) :
00477 mact(act), args(s)
00478 {
00479 }
00480
00486 result_type invoke(typename SequenceFactory::data_type seq) {
00487 SequenceFactory::set( seq, args );
00488 mact->execute();
00489 return NA<result_type>::na();
00490 }
00491
00492 void setArguments(const DataSourceSequence& a1)
00493 {
00494 args = a1;
00495 }
00496 };
00497
00498 }
00499 }
00500
00501 #endif