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 if(ret.isError()) {
00300 ff->reportError();
00301 ret.checkError();
00302 }
00303 SequenceFactory::update(args);
00304 return true;
00305 }
00306
00307 value_t get() const
00308 {
00309 evaluate();
00310 return ret.result();
00311 }
00312
00313 virtual FusedMCallDataSource<Signature>* clone() const
00314 {
00315 return new FusedMCallDataSource<Signature> (ff, args);
00316 }
00317 virtual FusedMCallDataSource<Signature>* copy(
00318 std::map<
00319 const base::DataSourceBase*,
00320 base::DataSourceBase*>& alreadyCloned) const
00321 {
00322 return new FusedMCallDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
00323 }
00324 };
00325
00330 template<typename Signature>
00331 struct FusedMSendDataSource
00332 : public DataSource<SendHandle<Signature> >
00333 {
00334 typedef SendHandle<Signature> result_type;
00335 typedef result_type value_t;
00336 typedef typename DataSource<value_t>::const_reference_t const_reference_t;
00337 typedef create_sequence<
00338 typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00339 typedef typename SequenceFactory::type DataSourceSequence;
00340 typename base::OperationCallerBase<Signature>::shared_ptr ff;
00341 DataSourceSequence args;
00342 mutable SendHandle<Signature> sh;
00343 public:
00344 typedef boost::intrusive_ptr<FusedMSendDataSource<Signature> >
00345 shared_ptr;
00346
00347 FusedMSendDataSource(typename base::OperationCallerBase<Signature>::shared_ptr g,
00348 const DataSourceSequence& s = DataSourceSequence() ) :
00349 ff(g), args(s)
00350 {
00351 }
00352
00353 void setArguments(const DataSourceSequence& a1)
00354 {
00355 args = a1;
00356 }
00357
00358 value_t value() const
00359 {
00360 return sh;
00361 }
00362
00363 const_reference_t rvalue() const
00364 {
00365 return sh;
00366 }
00367
00368 value_t get() const
00369 {
00370
00371 sh = bf::invoke(&base::OperationCallerBase<Signature>::send, bf::cons<base::OperationCallerBase<Signature>*, typename SequenceFactory::data_type>(ff.get(), SequenceFactory::data(args)));
00372 return sh;
00373 }
00374
00375 virtual FusedMSendDataSource<Signature>* clone() const
00376 {
00377 return new FusedMSendDataSource<Signature> (ff, args);
00378 }
00379 virtual FusedMSendDataSource<Signature>* copy(
00380 std::map<
00381 const base::DataSourceBase*,
00382 base::DataSourceBase*>& alreadyCloned) const
00383 {
00384 return new FusedMSendDataSource<Signature> (ff, SequenceFactory::copy(args, alreadyCloned));
00385 }
00386 };
00387
00394 template<typename Signature>
00395 struct FusedMCollectDataSource
00396 : public DataSource<SendStatus>
00397 {
00398 typedef SendStatus result_type;
00399 typedef result_type value_t;
00400 typedef DataSource<SendStatus>::const_reference_t const_reference_t;
00401
00402 typedef typename CollectType<Signature>::type CollectSignature;
00403 typedef typename boost::function_types::parameter_types<CollectSignature>::type arg_types;
00404 typedef typename mpl::push_front<arg_types, SendHandle<Signature>& >::type handle_and_arg_types;
00405 typedef create_sequence< handle_and_arg_types
00406 > SequenceFactory;
00407 typedef typename SequenceFactory::type DataSourceSequence;
00408 DataSourceSequence args;
00409 DataSource<bool>::shared_ptr isblocking;
00410 mutable SendStatus ss;
00411 public:
00412 typedef boost::intrusive_ptr<FusedMCollectDataSource<Signature> >
00413 shared_ptr;
00414
00415 FusedMCollectDataSource(
00416 const DataSourceSequence& s, DataSource<bool>::shared_ptr blocking ) :
00417 args(s), isblocking(blocking), ss(SendFailure)
00418 {
00419 }
00420
00421 void setArguments(const DataSourceSequence& a1)
00422 {
00423 args = a1;
00424 }
00425
00426 value_t value() const
00427 {
00428 return ss;
00429 }
00430
00431 const_reference_t rvalue() const
00432 {
00433 return ss;
00434 }
00435
00436 value_t get() const
00437 {
00438
00439 if (isblocking->get())
00440 ss = bf::invoke(&SendHandle<Signature>::CBase::collect, SequenceFactory::data(args));
00441 else
00442 ss = bf::invoke(&SendHandle<Signature>::CBase::collectIfDone, SequenceFactory::data(args));
00443 SequenceFactory::update(args);
00444 return ss;
00445 }
00446
00447 virtual FusedMCollectDataSource<Signature>* clone() const
00448 {
00449 return new FusedMCollectDataSource<Signature> ( args, isblocking);
00450 }
00451 virtual FusedMCollectDataSource<Signature>* copy(
00452 std::map<
00453 const base::DataSourceBase*,
00454 base::DataSourceBase*>& alreadyCloned) const
00455 {
00456 return new FusedMCollectDataSource<Signature> ( SequenceFactory::copy(args, alreadyCloned), isblocking);
00457 }
00458 };
00459
00464 template<typename Signature>
00465 struct FusedMSignal
00466 {
00467 typedef typename boost::function_traits<Signature>::result_type
00468 result_type;
00469 typedef result_type value_t;
00470 typedef create_sequence<
00471 typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00472 typedef typename SequenceFactory::atype DataSourceSequence;
00473 base::ActionInterface* mact;
00474 DataSourceSequence args;
00475 public:
00476 typedef boost::shared_ptr<FusedMSignal<Signature> >
00477 shared_ptr;
00478
00479 FusedMSignal(base::ActionInterface* act,
00480 const DataSourceSequence& s = DataSourceSequence() ) :
00481 mact(act), args(s)
00482 {
00483 }
00484
00490 result_type invoke(typename SequenceFactory::data_type seq) {
00491 SequenceFactory::set( seq, args );
00492 mact->execute();
00493 return NA<result_type>::na();
00494 }
00495
00496 void setArguments(const DataSourceSequence& a1)
00497 {
00498 args = a1;
00499 }
00500 };
00501
00502 }
00503 }
00504
00505 #endif