$search
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 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; // mutable because of get() const 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 // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type. 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 // push the SendHandle pointer in front. 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; // because of get() const 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 // put the member's object as first since SequenceFactory does not know about the OperationCallerBase type. 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 /* ORO_FUSEDFUNCTORDATASOURCE_HPP_ */