Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 OperationInterfacePartFused.hpp 00003 00004 OperationInterfacePartFused.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_OPERATION_INTERFACE_PART_FUSED_HPP 00040 #define ORO_OPERATION_INTERFACE_PART_FUSED_HPP 00041 00042 00043 #include <boost/shared_ptr.hpp> 00044 #include <boost/function_types/result_type.hpp> 00045 #include <boost/function_types/parameter_types.hpp> 00046 // Fusion behaviour changed at Boost 1.42 00047 #include <boost/version.hpp> 00048 #if BOOST_VERSION >= 104100 00049 // our code goes up to 7 FUSION_MAX_VECTOR_SIZE defaults to 10 00050 #ifndef BOOST_FUSION_UNFUSED_MAX_ARITY 00051 #define BOOST_FUSION_UNFUSED_MAX_ARITY 7 00052 #endif 00053 #include <boost/fusion/functional/generation/make_unfused.hpp> 00054 #else 00055 // our code goes up to 7 FUSION_MAX_VECTOR_SIZE defaults to 10 00056 #ifndef BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY 00057 #define BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY 7 00058 #endif 00059 #include <boost/fusion/include/make_unfused_generic.hpp> 00060 #endif 00061 00062 #include <boost/lambda/lambda.hpp> 00063 00064 #include <vector> 00065 #include <string> 00066 00067 #include "DataSource.hpp" 00068 #include "CreateSequence.hpp" 00069 #include "FusedFunctorDataSource.hpp" 00070 #include "../OperationInterfacePart.hpp" 00071 #include "../FactoryExceptions.hpp" 00072 #include "../Operation.hpp" 00073 #include "../base/OperationCallerBase.hpp" 00074 00080 namespace RTT 00081 { 00082 namespace internal { 00083 00084 class RTT_API OperationInterfacePartHelper { 00085 public: 00086 static std::string description(base::OperationBase* ob); 00087 static std::vector<ArgumentDescription> getArgumentList(base::OperationBase* ob, const int arity, std::vector<std::string> const& types); 00088 }; 00089 00094 template<typename Signature> 00095 class OperationInterfacePartFused 00096 : public OperationInterfacePart 00097 { 00098 typedef typename boost::function_traits<Signature>::result_type result_type; 00100 typedef create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory; 00102 typedef create_sequence<typename boost::function_types::parameter_types<typename CollectType<Signature>::type>::type > CollectSequenceFactory; 00103 Operation<Signature>* op; 00104 public: 00105 OperationInterfacePartFused( Operation<Signature>* o) 00106 : op(o) 00107 { 00108 } 00109 00110 virtual std::string getName() const { 00111 return op->getName(); 00112 } 00113 00114 virtual std::string description() const { 00115 return OperationInterfacePartHelper::description( op ); 00116 } 00117 00118 virtual std::vector<ArgumentDescription> getArgumentList() const { 00119 std::vector<std::string> types; 00120 for (unsigned int i = 1; i <= OperationInterfacePartFused::arity(); ++i ) 00121 types.push_back( SequenceFactory::GetType(i) ); 00122 return OperationInterfacePartHelper::getArgumentList( op, OperationInterfacePartFused::arity(), types ); 00123 } 00124 00125 std::string resultType() const 00126 { 00127 return DataSourceTypeInfo<result_type>::getType() + DataSourceTypeInfo<result_type>::getQualifier(); 00128 } 00129 00130 unsigned int arity() const { return boost::function_traits<Signature>::arity; } 00131 00132 const types::TypeInfo* getArgumentType(unsigned int arg) const 00133 { 00134 if (arg == 0 ) 00135 return internal::DataSourceTypeInfo<result_type>::getTypeInfo(); 00136 return SequenceFactory::GetTypeInfo(arg); 00137 } 00138 00139 unsigned int collectArity() const { return boost::function_traits< typename CollectType<Signature>::type >::arity; } 00140 00141 const types::TypeInfo* getCollectType(unsigned int arg) const 00142 { 00143 return CollectSequenceFactory::GetTypeInfo(arg); 00144 } 00145 00146 base::DataSourceBase::shared_ptr produce( 00147 const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const 00148 { 00149 // convert our args and signature into a boost::fusion Sequence. 00150 if ( args.size() != OperationInterfacePartFused::arity() ) 00151 throw wrong_number_of_args_exception(OperationInterfacePartFused::arity(), args.size() ); 00152 return new FusedMCallDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(args.begin()) ); 00153 } 00154 00155 virtual base::DataSourceBase::shared_ptr produceSend( const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller ) const { 00156 // convert our args and signature into a boost::fusion Sequence. 00157 if ( args.size() != OperationInterfacePartFused::arity() ) throw wrong_number_of_args_exception(OperationInterfacePartFused::arity(), args.size() ); 00158 return new FusedMSendDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(args.begin()) ); 00159 } 00160 00161 virtual base::DataSourceBase::shared_ptr produceHandle() const { 00162 // Because of copy/clone,program script variables ('var') must begin unbound. 00163 return new internal::UnboundDataSource<ValueDataSource<SendHandle<Signature> > >(); 00164 } 00165 00166 virtual base::DataSourceBase::shared_ptr produceCollect( const std::vector<base::DataSourceBase::shared_ptr>& args, DataSource<bool>::shared_ptr blocking ) const { 00167 const unsigned int carity = boost::mpl::size<typename FusedMCollectDataSource<Signature>::handle_and_arg_types>::value; 00168 assert( carity == collectArity() + 1 ); // check for arity functions. (this is actually a compile time assert). 00169 if ( args.size() != carity ) throw wrong_number_of_args_exception(carity, args.size() ); 00170 // we need to ask FusedMCollectDataSource what the arg types are, based on the collect signature. 00171 return new FusedMCollectDataSource<Signature>( create_sequence<typename FusedMCollectDataSource<Signature>::handle_and_arg_types >::sources(args.begin()), blocking ); 00172 } 00173 00174 #ifdef ORO_SIGNALLING_OPERATIONS 00175 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args) const { 00176 // convert our args and signature into a boost::fusion Sequence. 00177 if ( args.size() != OperationInterfacePartFused::arity() ) throw wrong_number_of_args_exception(OperationInterfacePartFused::arity(), args.size() ); 00178 // note: in boost 1.41.0+ the function make_unfused() is available. 00179 #if BOOST_VERSION >= 104100 00180 return op->signals( boost::fusion::make_unfused(boost::bind(&FusedMSignal<Signature>::invoke, 00181 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin())), 00182 boost::lambda::_1 00183 ) 00184 ) 00185 ); 00186 #else 00187 return op->signals( boost::fusion::make_unfused_generic(boost::bind(&FusedMSignal<Signature>::invoke, 00188 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin())), 00189 boost::lambda::_1 00190 ) 00191 ) 00192 ); 00193 #endif 00194 } 00195 #endif 00196 boost::shared_ptr<base::DisposableInterface> getLocalOperation() const { 00197 return op->getImplementation(); 00198 } 00199 }; 00200 00206 template<typename Signature> 00207 class SynchronousOperationInterfacePartFused 00208 : public OperationInterfacePart 00209 { 00210 typedef typename boost::function_traits<Signature>::result_type result_type; 00212 typedef create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory; 00214 typedef create_sequence<typename boost::function_types::parameter_types<typename CollectType<Signature>::type>::type > CollectSequenceFactory; 00215 Operation<Signature>* op; 00216 public: 00217 SynchronousOperationInterfacePartFused( Operation<Signature>* o) 00218 : op(o) 00219 { 00220 } 00221 00222 virtual base::DataSourceBase::shared_ptr produceSend(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const 00223 { throw no_asynchronous_operation_exception("cannot use produceSend on synchronous operations"); } 00224 virtual base::DataSourceBase::shared_ptr produceCollect(const std::vector<base::DataSourceBase::shared_ptr>& args, internal::DataSource<bool>::shared_ptr blocking) const 00225 { throw no_asynchronous_operation_exception("cannot use produceCollect on synchronous operations"); } 00226 #ifdef ORO_SIGNALLING_OPERATIONS 00227 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args) const 00228 { throw no_asynchronous_operation_exception("cannot use produceSignal on synchronous operations"); } 00229 #endif 00230 virtual base::DataSourceBase::shared_ptr produceHandle() const 00231 { throw no_asynchronous_operation_exception("cannot use produceHandle on synchronous operations"); } 00232 00233 virtual std::string getName() const { 00234 return op->getName(); 00235 } 00236 virtual std::string description() const { 00237 return OperationInterfacePartHelper::description( op ); 00238 } 00239 00240 virtual std::vector<ArgumentDescription> getArgumentList() const { 00241 std::vector<std::string> types; 00242 for (unsigned int i = 1; i <= SynchronousOperationInterfacePartFused::arity(); ++i ) 00243 types.push_back( SequenceFactory::GetType(i) ); 00244 return OperationInterfacePartHelper::getArgumentList( op, SynchronousOperationInterfacePartFused::arity(), types ); 00245 } 00246 00247 std::string resultType() const 00248 { 00249 return DataSourceTypeInfo<result_type>::getType() + DataSourceTypeInfo<result_type>::getQualifier(); 00250 } 00251 00252 unsigned int arity() const { return boost::function_traits<Signature>::arity; } 00253 00254 const types::TypeInfo* getArgumentType(unsigned int arg) const 00255 { 00256 if (arg == 0 ) 00257 return internal::DataSourceTypeInfo<result_type>::getTypeInfo(); 00258 return SequenceFactory::GetTypeInfo(arg); 00259 } 00260 00261 unsigned int collectArity() const { return boost::function_traits< typename CollectType<Signature>::type >::arity; } 00262 00263 const types::TypeInfo* getCollectType(unsigned int arg) const 00264 { 00265 return CollectSequenceFactory::GetTypeInfo(arg); 00266 } 00267 00268 base::DataSourceBase::shared_ptr produce( 00269 const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const 00270 { 00271 // convert our args and signature into a boost::fusion Sequence. 00272 if ( args.size() != SynchronousOperationInterfacePartFused::arity() ) 00273 throw wrong_number_of_args_exception(SynchronousOperationInterfacePartFused::arity(), args.size() ); 00274 return new FusedMCallDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(args.begin()) ); 00275 } 00276 00277 boost::shared_ptr<base::DisposableInterface> getLocalOperation() const { 00278 return op->getImplementation(); 00279 } 00280 }; 00281 00290 template<typename Signature,typename ObjT> 00291 class OperationInterfacePartFusedDS 00292 : public OperationInterfacePart 00293 { 00294 typedef create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory; 00295 typedef create_sequence<typename boost::function_types::parameter_types<typename CollectType<Signature>::type>::type > CollectSequenceFactory; 00296 typedef typename boost::function_traits<Signature>::result_type result_type; 00297 Operation<Signature>* op; 00298 // the datasource that stores a weak pointer is itself stored by a shared_ptr. 00299 typename DataSource<boost::shared_ptr<ObjT> >::shared_ptr mwp; 00300 public: 00301 OperationInterfacePartFusedDS( DataSource< boost::shared_ptr<ObjT> >* wp, Operation<Signature>* o) 00302 : op( o ), mwp(wp) 00303 { 00304 } 00305 00306 typedef std::vector<base::DataSourceBase::shared_ptr> ArgList; 00307 00308 std::string resultType() const 00309 { 00310 return DataSourceTypeInfo<result_type>::getType() + DataSourceTypeInfo<result_type>::getQualifier(); 00311 } 00312 00313 unsigned int arity() const { return boost::function_traits<Signature>::arity - 1;/*lie about the hidden member pointer */ } 00314 00315 const types::TypeInfo* getArgumentType(unsigned int arg) const 00316 { 00317 if (arg == 0 ) 00318 return internal::DataSourceTypeInfo<result_type>::getTypeInfo(); 00319 return SequenceFactory::GetTypeInfo(arg); 00320 } 00321 00322 unsigned int collectArity() const { return boost::function_traits< typename CollectType<Signature>::type >::arity; } 00323 00324 const types::TypeInfo* getCollectType(unsigned int arg) const 00325 { 00326 return CollectSequenceFactory::GetTypeInfo(arg); 00327 } 00328 00329 virtual std::string getName() const { 00330 return op->getName(); 00331 } 00332 00333 virtual std::string description() const { 00334 return op->getDescriptions().front(); 00335 } 00336 00337 virtual std::vector<ArgumentDescription> getArgumentList() const { 00338 std::vector<std::string> descr = op->getDescriptions(); 00339 std::vector<ArgumentDescription> ret; 00340 descr.resize( 1 + arity() * 2 ); 00341 for (unsigned int i =1; i < descr.size(); i +=2 ) 00342 ret.push_back(ArgumentDescription(descr[i],descr[i+1], SequenceFactory::GetType((i-1)/2+2)) ); 00343 return ret; 00344 } 00345 00346 base::DataSourceBase::shared_ptr produce(ArgList const& args, ExecutionEngine* caller) const 00347 { 00348 if ( args.size() != arity() ) throw wrong_number_of_args_exception(arity(), args.size() ); 00349 // the user won't give the necessary object argument, so we glue it in front. 00350 ArgList a2; 00351 a2.reserve(args.size()+1); 00352 a2.push_back(mwp); 00353 a2.insert(a2.end(), args.begin(), args.end()); 00354 // convert our args and signature into a boost::fusion Sequence. 00355 return new FusedMCallDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(a2.begin()) ); 00356 } 00357 00358 virtual base::DataSourceBase::shared_ptr produceSend( const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller ) const { 00359 if ( args.size() != arity() ) throw wrong_number_of_args_exception(arity(), args.size() ); 00360 // the user won't give the necessary object argument, so we glue it in front. 00361 ArgList a2; 00362 a2.reserve(args.size()+1); 00363 a2.push_back(mwp); 00364 a2.insert(a2.end(), args.begin(), args.end()); 00365 // convert our args and signature into a boost::fusion Sequence. 00366 return new FusedMSendDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(a2.begin()) ); 00367 } 00368 00369 virtual base::DataSourceBase::shared_ptr produceHandle() const { 00370 // Because of copy/clone,value objects must begin unbound. 00371 return new internal::UnboundDataSource<ValueDataSource<SendHandle<Signature> > >(); 00372 } 00373 00374 virtual base::DataSourceBase::shared_ptr produceCollect( const std::vector<base::DataSourceBase::shared_ptr>& args, DataSource<bool>::shared_ptr blocking ) const { 00375 const unsigned int carity = boost::mpl::size<typename FusedMCollectDataSource<Signature>::handle_and_arg_types>::value; 00376 assert( carity == collectArity() + 1 ); // check for arity functions. (this is actually a compile time assert). 00377 if ( args.size() != carity ) throw wrong_number_of_args_exception(carity, args.size() ); 00378 // we need to ask FusedMCollectDataSource what the arg types are, based on the collect signature. 00379 return new FusedMCollectDataSource<Signature>( create_sequence<typename FusedMCollectDataSource<Signature>::handle_and_arg_types >::sources(args.begin()), blocking ); 00380 } 00381 #ifdef ORO_SIGNALLING_OPERATIONS 00382 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args) const { 00383 if ( args.size() != arity() ) throw wrong_number_of_args_exception(arity(), args.size() ); 00384 // the user won't give the necessary object argument, so we glue it in front. 00385 ArgList a2; 00386 a2.reserve(args.size()+1); 00387 a2.push_back(mwp); 00388 a2.insert(a2.end(), args.begin(), args.end()); 00389 // note: in boost 1.41.0+ the function make_unfused() is available. 00390 #if BOOST_VERSION >= 104100 00391 return op->signals( boost::fusion::make_unfused(boost::bind(&FusedMSignal<Signature>::invoke, 00392 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin())), 00393 _1 00394 ) 00395 ) 00396 ); 00397 #else 00398 return op->signals( boost::fusion::make_unfused_generic(boost::bind(&FusedMSignal<Signature>::invoke, 00399 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin())), 00400 _1 00401 ) 00402 ) 00403 ); 00404 #endif 00405 } 00406 #endif 00407 boost::shared_ptr<base::DisposableInterface> getLocalOperation() const { 00408 return op->getImplementation(); 00409 } 00410 }; 00411 } 00412 } 00413 00414 #endif