Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 FusedFunctorDataSource.hpp 00003 00004 FusedFunctorDataSource.hpp - description 00005 ------------------- 00006 begin : Tue September 07 2010 00007 copyright : (C) 2010 The SourceWorks 00008 email : peter@thesourceworks.com 00009 00010 *************************************************************************** 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU General Public * 00013 * License as published by the Free Software Foundation; * 00014 * version 2 of the License. * 00015 * * 00016 * As a special exception, you may use this file as part of a free * 00017 * software library without restriction. Specifically, if other files * 00018 * instantiate templates or use macros or inline functions from this * 00019 * file, or you compile this file and link it with other files to * 00020 * produce an executable, this file does not by itself cause the * 00021 * resulting executable to be covered by the GNU General Public * 00022 * License. This exception does not however invalidate any other * 00023 * reasons why the executable file might be covered by the GNU General * 00024 * Public License. * 00025 * * 00026 * This library is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00029 * Lesser General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public * 00032 * License along with this library; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place, * 00034 * Suite 330, Boston, MA 02111-1307 USA * 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 //BOOST_STATIC_ASSERT( boost::mpl::false_::value ); 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 // forward invoke to ret object, which stores return value. 00111 // this foo pointer dance is because older compilers don't handle using 00112 // &bf::invoke<call_type,arg_type> directly. 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 //BOOST_STATIC_ASSERT( boost::mpl::false_::value ); 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 // forward invoke to ret object, which stores return value. 00187 // this foo pointer dance is because older compilers don't handle using 00188 // &bf::invoke<call_type,arg_type> directly. 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 // we need to get the new reference before we set the arg. 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 // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type. 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 // this foo pointer dance is because older compilers don't handle using 00293 // &bf::invoke<call_type,arg_type> directly. 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 // we need to store the ret value ourselves. 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; // mutable because of get() const 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 // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type. 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 // push the SendHandle pointer in front. 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; // because of get() const 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 // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type. 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 /* ORO_FUSEDFUNCTORDATASOURCE_HPP_ */