diff --git a/rtt/internal/BindStorage.hpp b/rtt/internal/BindStorage.hpp index 663ead4f4..d80cb1a8e 100644 --- a/rtt/internal/BindStorage.hpp +++ b/rtt/internal/BindStorage.hpp @@ -64,6 +64,7 @@ namespace RTT template struct AStore { + typedef T arg_type; T arg; AStore() : arg() {} AStore(T t) : arg(t) {} @@ -71,12 +72,13 @@ namespace RTT T& get() { return arg; } void operator()(T a) { arg = a; } - operator T() { return arg;} + operator T&() { return arg; } }; template struct AStore { + typedef T& arg_type; T* arg; AStore() : arg( &NA::na() ) {} AStore(T& t) : arg(&t) {} @@ -84,7 +86,7 @@ namespace RTT T& get() { return *arg; } void operator()(T& a) { arg = &a; } - operator T&() { return *arg;} + operator T&() { return *arg; } }; template @@ -287,7 +289,7 @@ namespace RTT typename Signal::shared_ptr msig; #endif - BindStorageImpl() : vStore(boost::ref(retv)) {} + BindStorageImpl() : vStore(retv) {} BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv) #ifdef ORO_SIGNALLING_OPERATIONS , msig(orig.msig) @@ -335,10 +337,10 @@ namespace RTT void store(arg1_type t1) { a1(t1); } void exec() { #ifdef ORO_SIGNALLING_OPERATIONS - if (msig) (*msig)(a1.get()); + if (msig) (*msig)(a1); #endif if (mmeth) - retv.exec( boost::bind(mmeth, boost::ref(a1.get()) ) ); + retv.exec( boost::bind(mmeth, a1 ) ); else retv.executed = true; } @@ -375,10 +377,10 @@ namespace RTT void store(arg1_type t1, arg2_type t2) { a1(t1); a2(t2); } void exec() { #ifdef ORO_SIGNALLING_OPERATIONS - if (msig) (*msig)(a1.get(), a2.get()); + if (msig) (*msig)(a1, a2); #endif if (mmeth) - retv.exec( boost::bind(mmeth, boost::ref(a1.get()), boost::ref(a2.get()) ) ); + retv.exec( boost::bind(mmeth, a1, a2 ) ); else retv.executed = true; } @@ -417,10 +419,10 @@ namespace RTT void store(arg1_type t1, arg2_type t2, arg3_type t3) { a1(t1); a2(t2); a3(t3); } void exec() { #ifdef ORO_SIGNALLING_OPERATIONS - if (msig) (*msig)(a1.get(), a2.get(), a3.get()); + if (msig) (*msig)(a1, a2, a3); #endif if (mmeth) - retv.exec( boost::bind(mmeth, boost::ref(a1.get()), boost::ref(a2.get()), boost::ref(a3.get()) ) ); + retv.exec( boost::bind(mmeth, a1, a2, a3 ) ); else retv.executed = true; } @@ -460,10 +462,10 @@ namespace RTT void store(arg1_type t1, arg2_type t2, arg3_type t3, arg4_type t4) { a1(t1); a2(t2); a3(t3); a4(t4); } void exec() { #ifdef ORO_SIGNALLING_OPERATIONS - if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get()); + if (msig) (*msig)(a1, a2, a3, a4); #endif if (mmeth) - retv.exec( boost::bind( mmeth, boost::ref(a1.get()), boost::ref(a2.get()), boost::ref(a3.get()), boost::ref(a4.get()) ) ); + retv.exec( boost::bind( mmeth, a1, a2, a3, a4 ) ); else retv.executed = true; } @@ -505,10 +507,10 @@ namespace RTT void store(arg1_type t1, arg2_type t2, arg3_type t3, arg4_type t4, arg5_type t5) { a1(t1); a2(t2); a3(t3); a4(t4); a5(t5);} void exec() { #ifdef ORO_SIGNALLING_OPERATIONS - if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get(), a5.get()); + if (msig) (*msig)(a1, a2, a3, a4, a5); #endif if (mmeth) - retv.exec( boost::bind( mmeth, boost::ref(a1.get()), boost::ref(a2.get()), boost::ref(a3.get()), boost::ref(a4.get()), boost::ref(a5.get()) ) ); + retv.exec( boost::bind( mmeth, a1, a2, a3, a4, a5 ) ); else retv.executed = true; } @@ -552,10 +554,10 @@ namespace RTT void store(arg1_type t1, arg2_type t2, arg3_type t3, arg4_type t4, arg5_type t5, arg6_type t6) { a1(t1); a2(t2); a3(t3); a4(t4); a5(t5); a6(t6);} void exec() { #ifdef ORO_SIGNALLING_OPERATIONS - if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get(), a5.get(), a6.get()); + if (msig) (*msig)(a1, a2, a3, a4, a5, a6); #endif if (mmeth) - retv.exec( boost::bind( mmeth, boost::ref(a1.get()), boost::ref(a2.get()), boost::ref(a3.get()), boost::ref(a4.get()), boost::ref(a5.get()), boost::ref(a6.get()) ) ); + retv.exec( boost::bind( mmeth, a1, a2, a3, a4, a5, a6 ) ); else retv.executed = true; } @@ -601,10 +603,10 @@ namespace RTT void store(arg1_type t1, arg2_type t2, arg3_type t3, arg4_type t4, arg5_type t5, arg6_type t6, arg7_type t7) { a1(t1); a2(t2); a3(t3); a4(t4); a5(t5); a6(t6); a7(t7);} void exec() { #ifdef ORO_SIGNALLING_OPERATIONS - if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get(), a5.get(), a6.get(), a7.get()); + if (msig) (*msig)(a1, a2, a3, a4, a5, a6, a7); #endif if (mmeth) - retv.exec( boost::bind( mmeth, boost::ref(a1.get()), boost::ref(a2.get()), boost::ref(a3.get()), boost::ref(a4.get()), boost::ref(a5.get()), boost::ref(a6.get()), boost::ref(a7.get()) ) ); + retv.exec( boost::bind( mmeth, a1, a2, a3, a4, a5, a6, a7 ) ); else retv.executed = true; } diff --git a/rtt/internal/CreateSequence.hpp b/rtt/internal/CreateSequence.hpp index 5d4e05d87..8d8b716ad 100644 --- a/rtt/internal/CreateSequence.hpp +++ b/rtt/internal/CreateSequence.hpp @@ -51,6 +51,7 @@ #include #include +#include "BindStorage.hpp" #include "DataSource.hpp" #include "Exceptions.hpp" #include "../FactoryExceptions.hpp" @@ -65,9 +66,6 @@ namespace RTT namespace bf = boost::fusion; namespace mpl = boost::mpl; - - template struct incomplete; - /** * Helper class for extracting the bare pointer from a shared_ptr * data source. Used in create_sequence::data() to unwrap the shared_ptr; @@ -123,7 +121,10 @@ namespace RTT typedef typename ds_type::element_type element_type; ds_type a = - boost::dynamic_pointer_cast< element_type >( DataSourceTypeInfo::getTypeInfo()->convert(*front) ); + boost::dynamic_pointer_cast< element_type >( *front ); + if ( ! a ) { + a = boost::dynamic_pointer_cast< element_type >( DataSourceTypeInfo::getTypeInfo()->convert(*front) ); + } if ( ! a ) { //cout << typeid(DataSource).name() << endl; ORO_THROW_OR_RETURN(wrong_types_of_args_exception( argnbr, tname, (*front)->getType() ), ds_type()); @@ -135,8 +136,10 @@ namespace RTT template static ads_type assignable(std::vector::const_iterator front, int argnbr, std::string const& tname ) { + typedef typename ads_type::element_type element_type; + ads_type a = - boost::dynamic_pointer_cast< AssignableDataSource >( *front ); // note: no conversion done, must be same type. + boost::dynamic_pointer_cast< element_type >( *front ); // note: no conversion done, must be same type. if ( ! a ) { ORO_THROW_OR_RETURN(wrong_types_of_args_exception( argnbr, tname, (*front)->getType() ), ads_type()); } @@ -194,6 +197,11 @@ namespace RTT */ typedef typename mpl::front::type arg_type; + /** + * The argument storage type + */ + typedef AStore arg_store_type; + /** * The data source value type of an assignable data source is non-const, non-reference. */ @@ -223,12 +231,18 @@ namespace RTT typedef bf::cons atype; typedef typename tail::data_type arg_tail_type; + typedef typename tail::data_store_type arg_store_tail_type; /** * The joint T data type of head and tail. */ typedef bf::cons data_type; + /** + * The joint T data storage type of head and tail. + */ + typedef bf::cons data_store_type; + /** * Converts a std::vector of DataSourceBase types into a boost::fusion Sequence of DataSources * of the types given in List. Will throw if an element of the vector could not @@ -279,7 +293,32 @@ namespace RTT */ static void set(const data_type& in, const atype& seq) { AssignHelper::set(seq, in); - return tail::set( bf::pop_front(in), bf::pop_front(seq) ); + tail::set( bf::pop_front(in), bf::pop_front(seq) ); + } + + /** + * Sets the values of a sequence of AssignableDataSource + * data sources ot the values contained in \a in using set(). + * @param in The values to write. + * @param seq The receiving assignable data sources. Because + * the datasources are shared pointers, it's ok to work on the + * temporary copies of seq. + */ + static void load(const data_store_type& in, const atype& seq) { + AssignHelper::set(seq, in); + tail::load( bf::pop_front(in), bf::pop_front(seq) ); + } + + /** + * Stores the values of a sequence of data_type into + * a data_store_type sequence for later retrieval during load. + * We must return the resulting sequence by value, since boost fusion + * returns temporaries, which we can't take a reference to. + * @param in The values to store + * @return The receiving AStore sequence. + */ + static data_store_type store(const data_type& in ) { + return data_store_type(bf::front(in), tail::store(bf::pop_front(in))); } /** @@ -289,7 +328,7 @@ namespace RTT */ static void update(const type&seq) { UpdateHelper::update( bf::front(seq) ); - return tail::update( bf::pop_front(seq) ); + tail::update( bf::pop_front(seq) ); } /** @@ -347,6 +386,9 @@ namespace RTT typedef typename remove_cr::type ds_arg_type; typedef bf::cons data_type; + typedef AStore arg_store_type; + typedef bf::cons data_store_type; + /** * The type of a single element of the vector. */ @@ -385,13 +427,20 @@ namespace RTT static void update(const type&seq) { UpdateHelper::update( bf::front(seq) ); - return; } static void set(const data_type& in, const atype& seq) { AssignHelper::set(seq, in); } + static void load(const data_store_type& in, const atype& seq) { + AssignHelper::set(seq, in); + } + + static data_store_type store(const data_type& in ) { + return data_store_type( bf::front(in) ); + } + /** * Copies a sequence of DataSource::shared_ptr according to the * copy/clone semantics of data sources. @@ -421,6 +470,7 @@ namespace RTT struct create_sequence_impl // empty mpl list { typedef bf::vector<> data_type; + typedef bf::vector<> data_store_type; // the result sequence type is a cons of the last argument in the vector. typedef bf::vector<> type; @@ -455,6 +505,13 @@ namespace RTT return; } + static void load(const data_store_type& in, const atype& seq) { + return; + } + + static data_store_type store(const data_type& in ) { + return data_store_type(); + } /** * Copies a sequence of DataSource::shared_ptr according to the diff --git a/rtt/internal/FusedFunctorDataSource.hpp b/rtt/internal/FusedFunctorDataSource.hpp index fad59a9e1..3b385abff 100644 --- a/rtt/internal/FusedFunctorDataSource.hpp +++ b/rtt/internal/FusedFunctorDataSource.hpp @@ -475,6 +475,9 @@ namespace RTT typename boost::function_types::parameter_types::type> SequenceFactory; typedef typename SequenceFactory::atype DataSourceSequence; boost::shared_ptr mact; + // We need the arg_cache to store data similar to BindStorage, + // such that we can safely access it during execute(). + typename SequenceFactory::data_store_type arg_cache; DataSourceSequence args; ExecutionEngine* subscriber; /** @@ -512,8 +515,7 @@ namespace RTT if ( subscriber ) { // asynchronous shared_ptr sg = this->cloneRT(); - SequenceFactory::set( seq, sg->args ); - + sg->arg_cache = SequenceFactory::store(seq); sg->self = sg; if ( subscriber->process( sg.get() ) ) { // all ok @@ -530,6 +532,7 @@ namespace RTT } void executeAndDispose() { + SequenceFactory::load( this->arg_cache, this->args ); mact->execute(); dispose(); }