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 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args) const {
00175
00176 if ( args.size() != OperationInterfacePartFused::arity() ) throw wrong_number_of_args_exception(OperationInterfacePartFused::arity(), args.size() );
00177
00178 #if BOOST_VERSION >= 104100
00179 return op->signals( boost::fusion::make_unfused(boost::bind(&FusedMSignal<Signature>::invoke,
00180 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin())),
00181 boost::lambda::_1
00182 )
00183 )
00184 );
00185 #else
00186 return op->signals( boost::fusion::make_unfused_generic(boost::bind(&FusedMSignal<Signature>::invoke,
00187 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin())),
00188 boost::lambda::_1
00189 )
00190 )
00191 );
00192 #endif
00193 }
00194
00195 boost::shared_ptr<base::DisposableInterface> getLocalOperation() const {
00196 return op->getImplementation();
00197 }
00198 };
00199
00205 template<typename Signature>
00206 class SynchronousOperationInterfacePartFused
00207 : public OperationInterfacePart
00208 {
00209 typedef typename boost::function_traits<Signature>::result_type result_type;
00211 typedef create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00213 typedef create_sequence<typename boost::function_types::parameter_types<typename CollectType<Signature>::type>::type > CollectSequenceFactory;
00214 Operation<Signature>* op;
00215 public:
00216 SynchronousOperationInterfacePartFused( Operation<Signature>* o)
00217 : op(o)
00218 {
00219 }
00220
00221 virtual base::DataSourceBase::shared_ptr produceSend(const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const
00222 { throw no_asynchronous_operation_exception("cannot use produceSend on synchronous operations"); }
00223 virtual base::DataSourceBase::shared_ptr produceCollect(const std::vector<base::DataSourceBase::shared_ptr>& args, internal::DataSource<bool>::shared_ptr blocking) const
00224 { throw no_asynchronous_operation_exception("cannot use produceCollect on synchronous operations"); }
00225 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args) const
00226 { throw no_asynchronous_operation_exception("cannot use produceSignal on synchronous operations"); }
00227 virtual base::DataSourceBase::shared_ptr produceHandle() const
00228 { throw no_asynchronous_operation_exception("cannot use produceHandle on synchronous operations"); }
00229
00230 virtual std::string getName() const {
00231 return op->getName();
00232 }
00233
00234 virtual std::string description() const {
00235 return OperationInterfacePartHelper::description( op );
00236 }
00237
00238 virtual std::vector<ArgumentDescription> getArgumentList() const {
00239 std::vector<std::string> types;
00240 for (unsigned int i = 1; i <= SynchronousOperationInterfacePartFused::arity(); ++i )
00241 types.push_back( SequenceFactory::GetType(i) );
00242 return OperationInterfacePartHelper::getArgumentList( op, SynchronousOperationInterfacePartFused::arity(), types );
00243 }
00244
00245 std::string resultType() const
00246 {
00247 return DataSourceTypeInfo<result_type>::getType() + DataSourceTypeInfo<result_type>::getQualifier();
00248 }
00249
00250 unsigned int arity() const { return boost::function_traits<Signature>::arity; }
00251
00252 const types::TypeInfo* getArgumentType(unsigned int arg) const
00253 {
00254 if (arg == 0 )
00255 return internal::DataSourceTypeInfo<result_type>::getTypeInfo();
00256 return SequenceFactory::GetTypeInfo(arg);
00257 }
00258
00259 unsigned int collectArity() const { return boost::function_traits< typename CollectType<Signature>::type >::arity; }
00260
00261 const types::TypeInfo* getCollectType(unsigned int arg) const
00262 {
00263 return CollectSequenceFactory::GetTypeInfo(arg);
00264 }
00265
00266 base::DataSourceBase::shared_ptr produce(
00267 const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller) const
00268 {
00269
00270 if ( args.size() != SynchronousOperationInterfacePartFused::arity() )
00271 throw wrong_number_of_args_exception(SynchronousOperationInterfacePartFused::arity(), args.size() );
00272 return new FusedMCallDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(args.begin()) );
00273 }
00274
00275 boost::shared_ptr<base::DisposableInterface> getLocalOperation() const {
00276 return op->getImplementation();
00277 }
00278 };
00279
00288 template<typename Signature,typename ObjT>
00289 class OperationInterfacePartFusedDS
00290 : public OperationInterfacePart
00291 {
00292 typedef create_sequence<typename boost::function_types::parameter_types<Signature>::type> SequenceFactory;
00293 typedef create_sequence<typename boost::function_types::parameter_types<typename CollectType<Signature>::type>::type > CollectSequenceFactory;
00294 typedef typename boost::function_traits<Signature>::result_type result_type;
00295 Operation<Signature>* op;
00296
00297 typename DataSource<boost::shared_ptr<ObjT> >::shared_ptr mwp;
00298 public:
00299 OperationInterfacePartFusedDS( DataSource< boost::shared_ptr<ObjT> >* wp, Operation<Signature>* o)
00300 : op( o ), mwp(wp)
00301 {
00302 }
00303
00304 typedef std::vector<base::DataSourceBase::shared_ptr> ArgList;
00305
00306 std::string resultType() const
00307 {
00308 return DataSourceTypeInfo<result_type>::getType() + DataSourceTypeInfo<result_type>::getQualifier();
00309 }
00310
00311 unsigned int arity() const { return boost::function_traits<Signature>::arity - 1; }
00312
00313 const types::TypeInfo* getArgumentType(unsigned int arg) const
00314 {
00315 if (arg == 0 )
00316 return internal::DataSourceTypeInfo<result_type>::getTypeInfo();
00317 return SequenceFactory::GetTypeInfo(arg);
00318 }
00319
00320 unsigned int collectArity() const { return boost::function_traits< typename CollectType<Signature>::type >::arity; }
00321
00322 const types::TypeInfo* getCollectType(unsigned int arg) const
00323 {
00324 return CollectSequenceFactory::GetTypeInfo(arg);
00325 }
00326
00327 virtual std::string getName() const {
00328 return op->getName();
00329 }
00330
00331 virtual std::string description() const {
00332 return op->getDescriptions().front();
00333 }
00334
00335 virtual std::vector<ArgumentDescription> getArgumentList() const {
00336 std::vector<std::string> descr = op->getDescriptions();
00337 std::vector<ArgumentDescription> ret;
00338 descr.resize( 1 + arity() * 2 );
00339 for (unsigned int i =1; i < descr.size(); i +=2 )
00340 ret.push_back(ArgumentDescription(descr[i],descr[i+1], SequenceFactory::GetType((i-1)/2+2)) );
00341 return ret;
00342 }
00343
00344 base::DataSourceBase::shared_ptr produce(ArgList const& args, ExecutionEngine* caller) const
00345 {
00346 if ( args.size() != arity() ) throw wrong_number_of_args_exception(arity(), args.size() );
00347
00348 ArgList a2;
00349 a2.reserve(args.size()+1);
00350 a2.push_back(mwp);
00351 a2.insert(a2.end(), args.begin(), args.end());
00352
00353 return new FusedMCallDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(a2.begin()) );
00354 }
00355
00356 virtual base::DataSourceBase::shared_ptr produceSend( const std::vector<base::DataSourceBase::shared_ptr>& args, ExecutionEngine* caller ) const {
00357 if ( args.size() != arity() ) throw wrong_number_of_args_exception(arity(), args.size() );
00358
00359 ArgList a2;
00360 a2.reserve(args.size()+1);
00361 a2.push_back(mwp);
00362 a2.insert(a2.end(), args.begin(), args.end());
00363
00364 return new FusedMSendDataSource<Signature>(typename base::OperationCallerBase<Signature>::shared_ptr(op->getOperationCaller()->cloneI(caller)), SequenceFactory::sources(a2.begin()) );
00365 }
00366
00367 virtual base::DataSourceBase::shared_ptr produceHandle() const {
00368
00369 return new internal::UnboundDataSource<ValueDataSource<SendHandle<Signature> > >();
00370 }
00371
00372 virtual base::DataSourceBase::shared_ptr produceCollect( const std::vector<base::DataSourceBase::shared_ptr>& args, DataSource<bool>::shared_ptr blocking ) const {
00373 const unsigned int carity = boost::mpl::size<typename FusedMCollectDataSource<Signature>::handle_and_arg_types>::value;
00374 assert( carity == collectArity() + 1 );
00375 if ( args.size() != carity ) throw wrong_number_of_args_exception(carity, args.size() );
00376
00377 return new FusedMCollectDataSource<Signature>( create_sequence<typename FusedMCollectDataSource<Signature>::handle_and_arg_types >::sources(args.begin()), blocking );
00378 }
00379
00380 virtual Handle produceSignal( base::ActionInterface* func, const std::vector<base::DataSourceBase::shared_ptr>& args) const {
00381 if ( args.size() != arity() ) throw wrong_number_of_args_exception(arity(), args.size() );
00382
00383 ArgList a2;
00384 a2.reserve(args.size()+1);
00385 a2.push_back(mwp);
00386 a2.insert(a2.end(), args.begin(), args.end());
00387
00388 #if BOOST_VERSION >= 104100
00389 return op->signals( boost::fusion::make_unfused(boost::bind(&FusedMSignal<Signature>::invoke,
00390 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin())),
00391 _1
00392 )
00393 )
00394 );
00395 #else
00396 return op->signals( boost::fusion::make_unfused_generic(boost::bind(&FusedMSignal<Signature>::invoke,
00397 boost::make_shared<FusedMSignal<Signature> >(func, SequenceFactory::assignable(args.begin())),
00398 _1
00399 )
00400 )
00401 );
00402 #endif
00403 }
00404
00405 boost::shared_ptr<base::DisposableInterface> getLocalOperation() const {
00406 return op->getImplementation();
00407 }
00408 };
00409 }
00410 }
00411
00412 #endif