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