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 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
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
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
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 );
00169 if ( args.size() != carity ) throw wrong_number_of_args_exception(carity, args.size() );
00170
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
00177 if ( args.size() != OperationInterfacePartFused::arity() ) throw wrong_number_of_args_exception(OperationInterfacePartFused::arity(), args.size() );
00178
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
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
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; }
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
00350 ArgList a2;
00351 a2.reserve(args.size()+1);
00352 a2.push_back(mwp);
00353 a2.insert(a2.end(), args.begin(), args.end());
00354
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
00361 ArgList a2;
00362 a2.reserve(args.size()+1);
00363 a2.push_back(mwp);
00364 a2.insert(a2.end(), args.begin(), args.end());
00365
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
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 );
00377 if ( args.size() != carity ) throw wrong_number_of_args_exception(carity, args.size() );
00378
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
00385 ArgList a2;
00386 a2.reserve(args.size()+1);
00387 a2.push_back(mwp);
00388 a2.insert(a2.end(), args.begin(), args.end());
00389
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