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_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
00047 #include <boost/version.hpp>
00048 #if BOOST_VERSION >= 104100
00049
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
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 protected:
00099 typedef typename boost::function_traits<Signature>::result_type result_type;
00101 typedef create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00103 typedef create_sequence<typename boost::function_types::parameter_types<typename CollectType<Signature>::type>::type > CollectSequenceFactory;
00104 Operation<Signature>* op;
00105 public:
00106 OperationInterfacePartFused( Operation<Signature>* o)
00107 : op(o)
00108 {
00109 }
00110
00111 virtual std::string getName() const {
00112 return op->getName();
00113 }
00114
00115 virtual std::string description() const {
00116 return OperationInterfacePartHelper::description( op );
00117 }
00118
00119 virtual std::vector<ArgumentDescription> getArgumentList() const {
00120 std::vector<std::string> types;
00121 for (unsigned int i = 1; i <= OperationInterfacePartFused::arity(); ++i )
00122 types.push_back( SequenceFactory::GetType(i) );
00123 return OperationInterfacePartHelper::getArgumentList( op, OperationInterfacePartFused::arity(), types );
00124 }
00125
00126 std::string resultType() const
00127 {
00128 return DataSourceTypeInfo<result_type>::getType() + DataSourceTypeInfo<result_type>::getQualifier();
00129 }
00130
00131 unsigned int arity() const { return boost::function_traits<Signature>::arity; }
00132
00133 const types::TypeInfo* getArgumentType(unsigned int arg) const
00134 {
00135 if (arg == 0 )
00136 return internal::DataSourceTypeInfo<result_type>::getTypeInfo();
00137 return SequenceFactory::GetTypeInfo(arg);
00138 }
00139
00140 unsigned int collectArity() const { return boost::function_traits< typename CollectType<Signature>::type >::arity; }
00141
00142 const types::TypeInfo* getCollectType(unsigned int arg) const
00143 {
00144 return CollectSequenceFactory::GetTypeInfo(arg);
00145 }
00146
00147 base::DataSourceBase::shared_ptr produce(
00148 const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const
00149 {
00150
00151 if ( args.size() != OperationInterfacePartFused::arity() )
00152 throw wrong_number_of_args_exception(OperationInterfacePartFused::arity(), args.size() );
00153 return new FusedMCallDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(args.begin()) );
00154 }
00155
00156 virtual base::DataSourceBase::shared_ptr produceSend( const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller ) const {
00157
00158 if ( args.size() != OperationInterfacePartFused::arity() ) throw wrong_number_of_args_exception(OperationInterfacePartFused::arity(), args.size() );
00159 return new FusedMSendDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(args.begin()) );
00160 }
00161
00162 virtual base::DataSourceBase::shared_ptr produceHandle() const {
00163
00164 return new internal::UnboundDataSource<ValueDataSource<SendHandle<Signature> > >();
00165 }
00166
00167 virtual base::DataSourceBase::shared_ptr produceCollect( const std::vector<base::DataSourceBase::shared_ptr>& args, DataSource<bool>::shared_ptr blocking ) const {
00168 const unsigned int carity = boost::mpl::size<typename FusedMCollectDataSource<Signature>::handle_and_arg_types>::value;
00169 assert( carity == collectArity() + 1 );
00170 if ( args.size() != carity ) throw wrong_number_of_args_exception(carity, args.size() );
00171
00172 return new FusedMCollectDataSource<Signature>( create_sequence<typename FusedMCollectDataSource<Signature>::handle_and_arg_types >::sources(args.begin()), blocking );
00173 }
00174
00175 #ifdef ORO_SIGNALLING_OPERATIONS
00176 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* subscriber) const
00177 {
00178 throw no_asynchronous_operation_exception("cannot use produceSignal on non-signalling operations");
00179 }
00180 #endif
00181 boost::shared_ptr<base::DisposableInterface> getLocalOperation() const {
00182 return op->getImplementation();
00183 }
00184 };
00185
00186
00187 #ifdef ORO_SIGNALLING_OPERATIONS
00188
00192 template<typename Signature>
00193 class EventOperationInterfacePartFused
00194 : public OperationInterfacePartFused<Signature>
00195 {
00196 typedef typename boost::function_traits<Signature>::result_type result_type;
00198 typedef create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00200 typedef create_sequence<typename boost::function_types::parameter_types<typename CollectType<Signature>::type>::type > CollectSequenceFactory;
00201
00202 public:
00203 EventOperationInterfacePartFused( Operation<Signature>* o)
00204 : OperationInterfacePartFused<Signature>(o)
00205 {
00206 }
00207
00208
00209 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* subscriber) const {
00210 base::OperationCallerInterface::shared_ptr impl = this->op->getOperationCaller();
00211 if ( subscriber == impl->getMessageProcessor() )
00212 subscriber = 0;
00213
00214 if ( args.size() != OperationInterfacePartFused<Signature>::arity() ) throw wrong_number_of_args_exception(OperationInterfacePartFused<Signature>::arity(), args.size() );
00215
00216 #if BOOST_VERSION >= 104100
00217 return this->op->signals( boost::fusion::make_unfused(boost::bind(&FusedMSignal<Signature>::invoke,
00218 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin()), subscriber),
00219 boost::lambda::_1
00220 )
00221 )
00222 );
00223 #else
00224 return this->op->signals( boost::fusion::make_unfused_generic(boost::bind(&FusedMSignal<Signature>::invoke,
00225 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin()),subscriber),
00226 boost::lambda::_1
00227 )
00228 )
00229 );
00230 #endif
00231 }
00232 };
00233 #endif
00234
00240 template<typename Signature>
00241 class SynchronousOperationInterfacePartFused
00242 : public OperationInterfacePart
00243 {
00244 typedef typename boost::function_traits<Signature>::result_type result_type;
00246 typedef create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00248 typedef create_sequence<typename boost::function_types::parameter_types<typename CollectType<Signature>::type>::type > CollectSequenceFactory;
00249 Operation<Signature>* op;
00250 public:
00251 SynchronousOperationInterfacePartFused( Operation<Signature>* o)
00252 : op(o)
00253 {
00254 }
00255
00256 virtual base::DataSourceBase::shared_ptr produceSend(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const
00257 { throw no_asynchronous_operation_exception("cannot use produceSend on synchronous operations"); }
00258 virtual base::DataSourceBase::shared_ptr produceCollect(const std::vector<base::DataSourceBase::shared_ptr>& args, internal::DataSource<bool>::shared_ptr blocking) const
00259 { throw no_asynchronous_operation_exception("cannot use produceCollect on synchronous operations"); }
00260 #ifdef ORO_SIGNALLING_OPERATIONS
00261 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* subscriber) const
00262 { throw no_asynchronous_operation_exception("cannot use produceSignal on synchronous operations"); }
00263 #endif
00264 virtual base::DataSourceBase::shared_ptr produceHandle() const
00265 { throw no_asynchronous_operation_exception("cannot use produceHandle on synchronous operations"); }
00266
00267 virtual std::string getName() const {
00268 return op->getName();
00269 }
00270 virtual std::string description() const {
00271 return OperationInterfacePartHelper::description( op );
00272 }
00273
00274 virtual std::vector<ArgumentDescription> getArgumentList() const {
00275 std::vector<std::string> types;
00276 for (unsigned int i = 1; i <= SynchronousOperationInterfacePartFused::arity(); ++i )
00277 types.push_back( SequenceFactory::GetType(i) );
00278 return OperationInterfacePartHelper::getArgumentList( op, SynchronousOperationInterfacePartFused::arity(), types );
00279 }
00280
00281 std::string resultType() const
00282 {
00283 return DataSourceTypeInfo<result_type>::getType() + DataSourceTypeInfo<result_type>::getQualifier();
00284 }
00285
00286 unsigned int arity() const { return boost::function_traits<Signature>::arity; }
00287
00288 const types::TypeInfo* getArgumentType(unsigned int arg) const
00289 {
00290 if (arg == 0 )
00291 return internal::DataSourceTypeInfo<result_type>::getTypeInfo();
00292 return SequenceFactory::GetTypeInfo(arg);
00293 }
00294
00295 unsigned int collectArity() const { return boost::function_traits< typename CollectType<Signature>::type >::arity; }
00296
00297 const types::TypeInfo* getCollectType(unsigned int arg) const
00298 {
00299 return CollectSequenceFactory::GetTypeInfo(arg);
00300 }
00301
00302 base::DataSourceBase::shared_ptr produce(
00303 const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const
00304 {
00305
00306 if ( args.size() != SynchronousOperationInterfacePartFused::arity() )
00307 throw wrong_number_of_args_exception(SynchronousOperationInterfacePartFused::arity(), args.size() );
00308 return new FusedMCallDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(args.begin()) );
00309 }
00310
00311 boost::shared_ptr<base::DisposableInterface> getLocalOperation() const {
00312 return op->getImplementation();
00313 }
00314 };
00315
00324 template<typename Signature,typename ObjT>
00325 class OperationInterfacePartFusedDS
00326 : public OperationInterfacePart
00327 {
00328 typedef create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00329 typedef create_sequence<typename boost::function_types::parameter_types<typename CollectType<Signature>::type>::type > CollectSequenceFactory;
00330 typedef typename boost::function_traits<Signature>::result_type result_type;
00331 Operation<Signature>* op;
00332
00333 typename DataSource<boost::shared_ptr<ObjT> >::shared_ptr mwp;
00334 public:
00335 OperationInterfacePartFusedDS( DataSource< boost::shared_ptr<ObjT> >* wp, Operation<Signature>* o)
00336 : op( o ), mwp(wp)
00337 {
00338 }
00339
00340 typedef std::vector<base::DataSourceBase::shared_ptr> ArgList;
00341
00342 std::string resultType() const
00343 {
00344 return DataSourceTypeInfo<result_type>::getType() + DataSourceTypeInfo<result_type>::getQualifier();
00345 }
00346
00347 unsigned int arity() const { return boost::function_traits<Signature>::arity - 1; }
00348
00349 const types::TypeInfo* getArgumentType(unsigned int arg) const
00350 {
00351 if (arg == 0 )
00352 return internal::DataSourceTypeInfo<result_type>::getTypeInfo();
00353 return SequenceFactory::GetTypeInfo(arg);
00354 }
00355
00356 unsigned int collectArity() const { return boost::function_traits< typename CollectType<Signature>::type >::arity; }
00357
00358 const types::TypeInfo* getCollectType(unsigned int arg) const
00359 {
00360 return CollectSequenceFactory::GetTypeInfo(arg);
00361 }
00362
00363 virtual std::string getName() const {
00364 return op->getName();
00365 }
00366
00367 virtual std::string description() const {
00368 return op->getDescriptions().front();
00369 }
00370
00371 virtual std::vector<ArgumentDescription> getArgumentList() const {
00372 std::vector<std::string> descr = op->getDescriptions();
00373 std::vector<ArgumentDescription> ret;
00374 descr.resize( 1 + arity() * 2 );
00375 for (unsigned int i =1; i < descr.size(); i +=2 )
00376 ret.push_back(ArgumentDescription(descr[i],descr[i+1], SequenceFactory::GetType((i-1)/2+2)) );
00377 return ret;
00378 }
00379
00380 base::DataSourceBase::shared_ptr produce(ArgList const& args, ExecutionEngine* caller) const
00381 {
00382 if ( args.size() != arity() ) throw wrong_number_of_args_exception(arity(), args.size() );
00383
00384 ArgList a2;
00385 a2.reserve(args.size()+1);
00386 a2.push_back(mwp);
00387 a2.insert(a2.end(), args.begin(), args.end());
00388
00389 return new FusedMCallDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(a2.begin()) );
00390 }
00391
00392 virtual base::DataSourceBase::shared_ptr produceSend( const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller ) const {
00393 if ( args.size() != arity() ) throw wrong_number_of_args_exception(arity(), args.size() );
00394
00395 ArgList a2;
00396 a2.reserve(args.size()+1);
00397 a2.push_back(mwp);
00398 a2.insert(a2.end(), args.begin(), args.end());
00399
00400 return new FusedMSendDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(a2.begin()) );
00401 }
00402
00403 virtual base::DataSourceBase::shared_ptr produceHandle() const {
00404
00405 return new internal::UnboundDataSource<ValueDataSource<SendHandle<Signature> > >();
00406 }
00407
00408 virtual base::DataSourceBase::shared_ptr produceCollect( const std::vector<base::DataSourceBase::shared_ptr>& args, DataSource<bool>::shared_ptr blocking ) const {
00409 const unsigned int carity = boost::mpl::size<typename FusedMCollectDataSource<Signature>::handle_and_arg_types>::value;
00410 assert( carity == collectArity() + 1 );
00411 if ( args.size() != carity ) throw wrong_number_of_args_exception(carity, args.size() );
00412
00413 return new FusedMCollectDataSource<Signature>( create_sequence<typename FusedMCollectDataSource<Signature>::handle_and_arg_types >::sources(args.begin()), blocking );
00414 }
00415 #ifdef ORO_SIGNALLING_OPERATIONS
00416 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* subscriber) const {
00417 if ( args.size() != arity() ) throw wrong_number_of_args_exception(arity(), args.size() );
00418 base::OperationCallerInterface::shared_ptr impl = op->getOperationCaller();
00419 if ( subscriber == impl->getMessageProcessor() )
00420 subscriber = 0;
00421
00422 ArgList a2;
00423 a2.reserve(args.size()+1);
00424 a2.push_back(mwp);
00425 a2.insert(a2.end(), args.begin(), args.end());
00426
00427 #if BOOST_VERSION >= 104100
00428 return this->op->signals( boost::fusion::make_unfused(boost::bind(&FusedMSignal<Signature>::invoke,
00429 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin()),subscriber),
00430 _1
00431 )
00432 )
00433 );
00434 #else
00435 return this->op->signals( boost::fusion::make_unfused_generic(boost::bind(&FusedMSignal<Signature>::invoke,
00436 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin()),subscriber),
00437 _1
00438 )
00439 )
00440 );
00441 #endif
00442 }
00443 #endif
00444 boost::shared_ptr<base::DisposableInterface> getLocalOperation() const {
00445 return this->op->getImplementation();
00446 }
00447 };
00448 }
00449 }
00450
00451 #endif