Orocos Real-Time Toolkit  2.5.0
LocalOperationCaller.hpp
00001 /***************************************************************************
00002   tag: FMTC  do nov 2 13:06:05 CET 2006  LocalOperationCaller.hpp
00003 
00004                         LocalOperationCaller.hpp -  description
00005                            -------------------
00006     begin                : do november 02 2006
00007     copyright            : (C) 2006 FMTC
00008     email                : peter.soetens@fmtc.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 #ifndef ORO_LOCAL_METHOD_HPP
00040 #define ORO_LOCAL_METHOD_HPP
00041 
00042 #include <boost/function.hpp>
00043 #include <boost/shared_ptr.hpp>
00044 #include <boost/make_shared.hpp>
00045 #include <string>
00046 #include "Invoker.hpp"
00047 #include "../base/OperationCallerBase.hpp"
00048 #include "../base/OperationBase.hpp"
00049 #include "BindStorage.hpp"
00050 #include "../SendStatus.hpp"
00051 #include "../SendHandle.hpp"
00052 #include "../ExecutionEngine.hpp"
00053 #include "OperationCallerBinder.hpp"
00054 #include "GlobalEngine.hpp"
00055 #include <boost/fusion/include/vector_tie.hpp>
00056 #include "../os/oro_allocator.hpp"
00057 
00058 #include <iostream>
00059 // For doing I/O
00060 #include <boost/fusion/sequence/io.hpp>
00061 
00062 namespace RTT
00063 {
00064     namespace internal
00065     {
00077         template<class FunctionT>
00078         class LocalOperationCallerImpl
00079             : public base::OperationCallerBase<FunctionT>,
00080               public internal::CollectBase<FunctionT>,
00081               protected BindStorage<FunctionT>
00082         {
00083         public:
00084             LocalOperationCallerImpl() : myengine(GlobalEngine::Instance()), caller(GlobalEngine::Instance()) {}
00085             typedef FunctionT Signature;
00086             typedef typename boost::function_traits<Signature>::result_type result_type;
00087             typedef typename boost::function_traits<Signature>::result_type result_reference;
00088             typedef boost::function_traits<Signature> traits;
00089 
00090             typedef boost::shared_ptr<LocalOperationCallerImpl> shared_ptr;
00091 
00092             virtual bool ready() const {
00093                 return true;
00094             }
00095 
00096             virtual void setExecutor(ExecutionEngine* ee) {
00097                 if (met == OwnThread)
00098                     myengine = ee;
00099                 else
00100                     myengine = GlobalEngine::Instance();
00101             }
00102 
00103             virtual void setCaller(ExecutionEngine* ee) {
00104                 if (ee)
00105                     caller = ee;
00106                 else
00107                     caller = GlobalEngine::Instance();
00108             }
00109 
00110             virtual bool setThread(ExecutionThread et, ExecutionEngine* executor) {
00111                 met = et;
00112                 setExecutor(executor);
00113                 return true;
00114             }
00115 
00116             void executeAndDispose() {
00117                 if (!this->retv.isExecuted()) {
00118                     this->exec(); // calls BindStorage.
00119                     //cout << "executed method"<<endl;
00120                     bool result = false;
00121                     if (caller){
00122                         result = caller->process(this);
00123                     }
00124                     if (!result)
00125                         dispose();
00126                 } else {
00127                     //cout << "received method done msg."<<endl;
00128                     // Already executed, are in caller.
00129                     // nop, we will check ret in collect()
00130                     // This is the place to call call-back functions,
00131                     // since we're in the caller's (or proxy's) EE.
00132                     dispose();
00133                 }
00134                 return;
00135             }
00136 
00141             void dispose() {
00142                 //this->~LocalOperationCallerImpl();
00143                 //oro_rt_free(this);
00144                 self.reset();
00145             }
00146 
00147             ExecutionEngine* getMessageProcessor() const { return myengine; }
00148 
00149             SendHandle<Signature> do_send(shared_ptr cl) {
00150                 assert(myengine); // myengine must be either the caller's engine or GlobalEngine::Instance().
00151                 //std::cout << "Sending clone..."<<std::endl;
00152                 if ( myengine->process( cl.get() ) ) {
00153                     cl->self = cl;
00154                     return SendHandle<Signature>( cl );
00155                 } else {
00156                     // cleanup. Done by shared_ptr.
00157                     //cl->~OperationCallerBase();
00158                     //oro_rt_free(cl);
00159                     return SendHandle<Signature>();
00160                 }
00161             }
00162             // We need a handle object !
00163             SendHandle<Signature> send_impl() {
00164                 return do_send( this->cloneRT() );
00165             }
00166 
00167             template<class T1>
00168             SendHandle<Signature> send_impl( T1 a1 ) {
00169                 // bind types from Storage<Function>
00170                 shared_ptr cl = this->cloneRT();
00171                 cl->store( a1 );
00172                 return do_send(cl);
00173             }
00174 
00175             template<class T1, class T2>
00176             SendHandle<Signature> send_impl( T1 a1, T2 a2 ) {
00177                 // bind types from Storage<Function>
00178                 shared_ptr cl = this->cloneRT();
00179                 cl->store( a1,a2 );
00180                 return do_send(cl);
00181             }
00182 
00183             template<class T1, class T2, class T3>
00184             SendHandle<Signature> send_impl( T1 a1, T2 a2, T3 a3 ) {
00185                 // bind types from Storage<Function>
00186                 shared_ptr cl = this->cloneRT();
00187                 cl->store( a1,a2,a3 );
00188                 return do_send(cl);
00189             }
00190 
00191             template<class T1, class T2, class T3, class T4>
00192             SendHandle<Signature> send_impl( T1 a1, T2 a2, T3 a3, T4 a4 ) {
00193                 // bind types from Storage<Function>
00194                 shared_ptr cl = this->cloneRT();
00195                 cl->store( a1,a2,a3,a4 );
00196                 return do_send(cl);
00197             }
00198 
00199             template<class T1, class T2, class T3, class T4, class T5>
00200             SendHandle<Signature> send_impl( T1 a1, T2 a2, T3 a3, T4 a4, T5 a5 ) {
00201                 // bind types from Storage<Function>
00202                 shared_ptr cl = this->cloneRT();
00203                 cl->store( a1,a2,a3,a4,a5 );
00204                 return do_send(cl);
00205             }
00206 
00207             template<class T1, class T2, class T3, class T4, class T5, class T6>
00208             SendHandle<Signature> send_impl( T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6 ) {
00209                 // bind types from Storage<Function>
00210                 shared_ptr cl = this->cloneRT();
00211                 cl->store( a1,a2,a3,a4,a5,a6 );
00212                 return do_send(cl);
00213             }
00214 
00215             template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
00216             SendHandle<Signature> send_impl( T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7 ) {
00217                 // bind types from Storage<Function>
00218                 shared_ptr cl = this->cloneRT();
00219                 cl->store( a1,a2,a3,a4,a5,a6,a7 );
00220                 return do_send(cl);
00221             }
00222 
00223 
00224             SendStatus collectIfDone_impl() {
00225                 if ( this->retv.isExecuted()) {
00226                     return SendSuccess;
00227                 } else
00228                     return SendNotReady;
00229             }
00230 
00231             // collect_impl belongs in LocalOperationCallerImpl because it would need
00232             // to be repeated in each BindStorage spec.
00233             template<class T1>
00234             SendStatus collectIfDone_impl( T1& a1 ) {
00235                 if ( this->retv.isExecuted()) {
00236                     bf::vector_tie(a1) = bf::filter_if< is_arg_return<boost::remove_reference<mpl::_> > >(this->vStore);
00237                     return SendSuccess;
00238                 } else
00239                     return SendNotReady;
00240             }
00241 
00242             template<class T1, class T2>
00243             SendStatus collectIfDone_impl( T1& a1, T2& a2 ) {
00244                 if ( this->retv.isExecuted()) {
00245                     bf::vector_tie(a1,a2) = bf::filter_if< is_arg_return<boost::remove_reference<mpl::_> > >(this->vStore);
00246                     return SendSuccess;
00247                 }
00248                 return SendNotReady;
00249             }
00250 
00251             template<class T1, class T2, class T3>
00252             SendStatus collectIfDone_impl( T1& a1, T2& a2, T3& a3 ) {
00253                 if ( this->retv.isExecuted()) {
00254                     bf::vector_tie(a1,a2,a3) = bf::filter_if< is_arg_return<boost::remove_reference<mpl::_> > >(this->vStore);
00255                     return SendSuccess;
00256                 } else
00257                     return SendNotReady;
00258             }
00259 
00260             template<class T1, class T2, class T3, class T4>
00261             SendStatus collectIfDone_impl( T1& a1, T2& a2, T3& a3, T4& a4 ) {
00262                 if ( this->retv.isExecuted()) {
00263                     bf::vector_tie(a1,a2,a3,a4) = bf::filter_if< is_arg_return<boost::remove_reference<mpl::_> > >(this->vStore);
00264                     return SendSuccess;
00265                 } else
00266                     return SendNotReady;
00267             }
00268 
00269             template<class T1, class T2, class T3, class T4, class T5>
00270             SendStatus collectIfDone_impl( T1& a1, T2& a2, T3& a3, T4& a4, T5& a5 ) {
00271                 if ( this->retv.isExecuted()) {
00272                     bf::vector_tie(a1,a2,a3,a4,a5) = bf::filter_if< is_arg_return<boost::remove_reference<mpl::_> > >(this->vStore);
00273                     return SendSuccess;
00274                 } else
00275                     return SendNotReady;
00276             }
00277 
00278             template<class T1, class T2, class T3, class T4, class T5, class T6>
00279             SendStatus collectIfDone_impl( T1& a1, T2& a2, T3& a3, T4& a4, T5& a5, T6& a6 ) {
00280                 if ( this->retv.isExecuted()) {
00281                     bf::vector_tie(a1,a2,a3,a4,a5,a6) = bf::filter_if< is_arg_return<boost::remove_reference<mpl::_> > >(this->vStore);
00282                     return SendSuccess;
00283                 } else
00284                     return SendNotReady;
00285             }
00286 
00287             template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
00288             SendStatus collectIfDone_impl( T1& a1, T2& a2, T3& a3, T4& a4, T5& a5, T6& a6, T7& a7 ) {
00289                 if ( this->retv.isExecuted()) {
00290                     bf::vector_tie(a1,a2,a3,a4,a5,a6,a7) = bf::filter_if< is_arg_return<boost::remove_reference<mpl::_> > >(this->vStore);
00291                     return SendSuccess;
00292                 } else
00293                     return SendNotReady;
00294             }
00295 
00296             SendStatus collect_impl() {
00297                 caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) );
00298                 return this->collectIfDone_impl();
00299             }
00300             template<class T1>
00301             SendStatus collect_impl( T1& a1 ) {
00302                 caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) );
00303                 return this->collectIfDone_impl(a1);
00304             }
00305 
00306             template<class T1, class T2>
00307             SendStatus collect_impl( T1& a1, T2& a2 ) {
00308                 caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) );
00309                 return this->collectIfDone_impl(a1,a2);
00310             }
00311 
00312             template<class T1, class T2, class T3>
00313             SendStatus collect_impl( T1& a1, T2& a2, T3& a3 ) {
00314                 caller->waitForMessages( boost::bind(&Store::RStoreType::isExecuted,boost::ref(this->retv)) );
00315                 return this->collectIfDone_impl(a1,a2,a3);
00316             }
00317 
00321             result_type call_impl()
00322             {
00323 
00324                 if (met == OwnThread && myengine != caller) {
00325                     SendHandle<Signature> h = send_impl();
00326                     if ( h.collect() == SendSuccess )
00327                         return h.ret();
00328                     else
00329                         throw SendFailure;
00330                 } else {
00331 #ifdef ORO_SIGNALLING_OPERATIONS
00332                     if (this->msig) this->msig->emit();
00333 #endif
00334                     if ( this->mmeth )
00335                         return this->mmeth(); // ClientThread
00336                     else
00337                         return NA<result_type>::na();
00338                 }
00339             }
00340 
00341 
00345             template<class T1>
00346             result_type call_impl(T1 a1)
00347             {
00348                 SendHandle<Signature> h;
00349                 if (met == OwnThread && myengine != caller) {
00350                     h = send_impl<T1>(a1);
00351                     // collect_impl may take diff number of arguments than
00352                     // call_impl/ret_impl(), so we use generic collect() + ret_impl()
00353                     if ( h.collect() == SendSuccess )
00354                         return h.ret(a1);
00355                     else
00356                         throw SendFailure;
00357                 } else{
00358 #ifdef ORO_SIGNALLING_OPERATIONS
00359                     if (this->msig) this->msig->emit(a1);
00360 #endif
00361                     if ( this->mmeth )
00362                         return this->mmeth(a1);
00363                     else
00364                         return NA<result_type>::na();
00365                 }
00366                 return NA<result_type>::na();
00367             }
00368 
00369             template<class T1, class T2>
00370             result_type call_impl(T1 a1, T2 a2)
00371             {
00372                 SendHandle<Signature> h;
00373                 if (met == OwnThread && myengine != caller) {
00374                     h = send_impl<T1,T2>(a1,a2);
00375                     if ( h.collect() == SendSuccess )
00376                         return h.ret(a1,a2);
00377                     else
00378                         throw SendFailure;
00379                 } else {
00380 #ifdef ORO_SIGNALLING_OPERATIONS
00381                     if (this->msig) this->msig->emit(a1,a2);
00382 #endif
00383                     if ( this->mmeth )
00384                         return this->mmeth(a1,a2);
00385                     else
00386                         return NA<result_type>::na();
00387                 }
00388                 return NA<result_type>::na();
00389             }
00390 
00391             template<class T1, class T2, class T3>
00392             result_type call_impl(T1 a1, T2 a2, T3 a3)
00393             {
00394                 SendHandle<Signature> h;
00395                 if (met == OwnThread && myengine != caller) {
00396                     h = send_impl<T1,T2,T3>(a1,a2,a3);
00397                     if ( h.collect() == SendSuccess )
00398                         return h.ret(a1,a2,a3);
00399                     else
00400                         throw SendFailure;
00401                 } else {
00402 #ifdef ORO_SIGNALLING_OPERATIONS
00403                     if (this->msig) this->msig->emit(a1,a2,a3);
00404 #endif
00405                     if ( this->mmeth )
00406                         return this->mmeth(a1,a2,a3);
00407                     else
00408                         return NA<result_type>::na();
00409                 }
00410                 return NA<result_type>::na();
00411             }
00412 
00413             template<class T1, class T2, class T3, class T4>
00414             result_type call_impl(T1 a1, T2 a2, T3 a3, T4 a4)
00415             {
00416                 SendHandle<Signature> h;
00417                 if (met == OwnThread && myengine != caller) {
00418                     h = send_impl<T1,T2,T3,T4>(a1,a2,a3,a4);
00419                     if ( h.collect() == SendSuccess )
00420                         return h.ret(a1,a2,a3,a4);
00421                     else
00422                         throw SendFailure;
00423                 } else {
00424 #ifdef ORO_SIGNALLING_OPERATIONS
00425                     if (this->msig) this->msig->emit(a1,a2,a3,a4);
00426 #endif
00427                     if ( this->mmeth )
00428                         return this->mmeth(a1,a2,a3,a4);
00429                     else
00430                         return NA<result_type>::na();
00431                 }
00432                 return NA<result_type>::na();
00433             }
00434 
00435             template<class T1, class T2, class T3, class T4, class T5>
00436             result_type call_impl(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
00437             {
00438                 SendHandle<Signature> h;
00439                 if (met == OwnThread && myengine != caller) {
00440                     h = send_impl<T1,T2,T3,T4,T5>(a1,a2,a3,a4,a5);
00441                     if ( h.collect() == SendSuccess )
00442                         return h.ret(a1,a2,a3,a4,a5);
00443                     else
00444                         throw SendFailure;
00445                 } else {
00446 #ifdef ORO_SIGNALLING_OPERATIONS
00447                     if (this->msig) this->msig->emit(a1,a2,a3,a4,a5);
00448 #endif
00449                     if ( this->mmeth )
00450                         return this->mmeth(a1,a2,a3,a4,a5);
00451                     else
00452                         return NA<result_type>::na();
00453                 }
00454                 return NA<result_type>::na();
00455             }
00456 
00457             template<class T1, class T2, class T3, class T4, class T5, class T6>
00458             result_type call_impl(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
00459             {
00460                 SendHandle<Signature> h;
00461                 if (met == OwnThread && myengine != caller) {
00462                     h = send_impl<T1,T2,T3,T4,T5,T6>(a1,a2,a3,a4,a5,a6);
00463                     if ( h.collect() == SendSuccess )
00464                         return h.ret(a1,a2,a3,a4,a5,a6);
00465                     else
00466                         throw SendFailure;
00467                 } else {
00468 #ifdef ORO_SIGNALLING_OPERATIONS
00469                     if (this->msig) this->msig->emit(a1,a2,a3,a4,a5,a6);
00470 #endif
00471                     if ( this->mmeth )
00472                         return this->mmeth(a1,a2,a3,a4,a5,a6);
00473                     else
00474                         return NA<result_type>::na();
00475                 }
00476                 return NA<result_type>::na();
00477             }
00478 
00479             template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
00480             result_type call_impl(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
00481             {
00482                 SendHandle<Signature> h;
00483                 if (met == OwnThread && myengine != caller) {
00484                     h = send_impl<T1,T2,T3,T4,T5,T6,T7>(a1,a2,a3,a4,a5,a6,a7);
00485                     if ( h.collect() == SendSuccess )
00486                         return h.ret(a1,a2,a3,a4,a5,a6,a7);
00487                     else
00488                         throw SendFailure;
00489                 } else {
00490 #ifdef ORO_SIGNALLING_OPERATIONS
00491                     if (this->msig) this->msig->emit(a1,a2,a3,a4,a5,a6,a7);
00492 #endif
00493                     if ( this->mmeth )
00494                         return this->mmeth(a1,a2,a3,a4,a5,a6,a7);
00495                     else
00496                         return NA<result_type>::na();
00497                 }
00498                 return NA<result_type>::na();
00499             }
00500 
00501             result_type ret_impl()
00502             {
00503                 return this->retv.result(); // may return void.
00504             }
00505 
00511             template<class T1>
00512             result_type ret_impl(T1 a1)
00513             {
00514                 typedef mpl::and_<boost::is_reference<mpl::_>, mpl::not_<boost::is_const<boost::remove_reference<mpl::_> > > > pred;
00515                 bf::vector<T1> vArgs( boost::ref(a1) );
00516                 if ( this->retv.isExecuted())
00517                     as_vector(bf::filter_if< pred >(vArgs)) = bf::filter_if< is_out_arg<boost::remove_reference<mpl::_> > >(this->vStore);
00518                 return this->retv.result(); // may return void.
00519             }
00520 
00521             template<class T1,class T2>
00522             result_type ret_impl(T1 a1, T2 a2)
00523             {
00524                 typedef mpl::and_<boost::is_reference<mpl::_>, mpl::not_<boost::is_const<boost::remove_reference<mpl::_> > > > pred;
00525                 bf::vector<T1,T2> vArgs( boost::ref(a1), boost::ref(a2) );
00526                 if ( this->retv.isExecuted())
00527                     as_vector(bf::filter_if< pred >(vArgs)) = bf::filter_if< is_out_arg< boost::remove_reference<mpl::_> > >(this->vStore);
00528                 return this->retv.result(); // may return void.
00529             }
00530 
00531             template<class T1,class T2, class T3>
00532             result_type ret_impl(T1 a1, T2 a2, T3 a3)
00533             {
00534                 typedef mpl::and_<boost::is_reference<mpl::_>, mpl::not_<boost::is_const<boost::remove_reference<mpl::_> > > > pred;
00535                 bf::vector<T1,T2,T3> vArgs( boost::ref(a1), boost::ref(a2), boost::ref(a3) );
00536                 if ( this->retv.isExecuted())
00537                     as_vector(bf::filter_if< pred >(vArgs)) = bf::filter_if< is_out_arg<boost::remove_reference<mpl::_> > >(this->vStore);
00538                 return this->retv.result(); // may return void.
00539             }
00540 
00541             template<class T1,class T2, class T3, class T4>
00542             result_type ret_impl(T1 a1, T2 a2, T3 a3, T4 a4)
00543             {
00544                 typedef mpl::and_<boost::is_reference<mpl::_>, mpl::not_<boost::is_const<boost::remove_reference<mpl::_> > > > pred;
00545                 bf::vector<T1,T2,T3,T4> vArgs( boost::ref(a1), boost::ref(a2), boost::ref(a3), boost::ref(a4) );
00546                 if ( this->retv.isExecuted())
00547                     as_vector(bf::filter_if< pred >(vArgs)) = bf::filter_if< is_out_arg<boost::remove_reference<mpl::_> > >(this->vStore);
00548                 return this->retv.result(); // may return void.
00549             }
00550 
00551             template<class T1,class T2, class T3, class T4, class T5>
00552             result_type ret_impl(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
00553             {
00554                 typedef mpl::and_<boost::is_reference<mpl::_>, mpl::not_<boost::is_const<boost::remove_reference<mpl::_> > > > pred;
00555                 bf::vector<T1,T2,T3,T4,T5> vArgs( boost::ref(a1), boost::ref(a2), boost::ref(a3), boost::ref(a4), boost::ref(a5) );
00556                 if ( this->retv.isExecuted())
00557                     as_vector(bf::filter_if< pred >(vArgs)) = bf::filter_if< is_out_arg<boost::remove_reference<mpl::_> > >(this->vStore);
00558                 return this->retv.result(); // may return void.
00559             }
00560 
00561             template<class T1,class T2, class T3, class T4, class T5, class T6>
00562             result_type ret_impl(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
00563             {
00564                 typedef mpl::and_<boost::is_reference<mpl::_>, mpl::not_<boost::is_const<boost::remove_reference<mpl::_> > > > pred;
00565                 bf::vector<T1,T2,T3,T4,T5,T6> vArgs( boost::ref(a1), boost::ref(a2), boost::ref(a3), boost::ref(a4), boost::ref(a5), boost::ref(a6) );
00566                 if ( this->retv.isExecuted())
00567                     as_vector(bf::filter_if< pred >(vArgs)) = bf::filter_if< is_out_arg<boost::remove_reference<mpl::_> > >(this->vStore);
00568                 return this->retv.result(); // may return void.
00569             }
00570 
00571             template<class T1,class T2, class T3, class T4, class T5, class T6, class T7>
00572             result_type ret_impl(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
00573             {
00574                 typedef mpl::and_<boost::is_reference<mpl::_>, mpl::not_<boost::is_const<boost::remove_reference<mpl::_> > > > pred;
00575                 bf::vector<T1,T2,T3,T4,T5,T6,T7> vArgs( boost::ref(a1), boost::ref(a2), boost::ref(a3), boost::ref(a4), boost::ref(a5), boost::ref(a6), boost::ref(a7) );
00576                 if ( this->retv.isExecuted())
00577                     as_vector(bf::filter_if< pred >(vArgs)) = bf::filter_if< is_out_arg<boost::remove_reference<mpl::_> > >(this->vStore);
00578                 return this->retv.result(); // may return void.
00579             }
00580 
00581             virtual shared_ptr cloneRT() const = 0;
00582 
00583         protected:
00584             ExecutionEngine* myengine;
00585             ExecutionEngine* caller;
00586             typedef BindStorage<FunctionT> Store;
00587             ExecutionThread met;
00593             typename base::OperationCallerBase<FunctionT>::shared_ptr self;
00594         };
00595 
00605         template<class FunctionT>
00606         struct LocalOperationCaller
00607             : public Invoker<FunctionT,LocalOperationCallerImpl<FunctionT> >
00608         {
00609             typedef FunctionT Signature;
00610             typedef typename boost::function_traits<Signature>::result_type result_type;
00611             typedef boost::function_traits<Signature> traits;
00612 
00613             typedef boost::shared_ptr<LocalOperationCaller> shared_ptr;
00614 
00620             LocalOperationCaller()
00621             {}
00622 
00631             template<class M, class ObjectType>
00632             LocalOperationCaller(M meth, ObjectType object, ExecutionEngine* ee, ExecutionEngine* caller, ExecutionThread et = ClientThread )
00633             {
00634                 if (!ee)
00635                     ee = GlobalEngine::Instance();
00636                 this->mmeth = OperationCallerBinder<Signature>()(meth, object);
00637                 this->myengine = ee;
00638                 this->caller = caller;
00639                 this->met = et;
00640             }
00641 
00648             template<class M>
00649             LocalOperationCaller(M meth, ExecutionEngine* ee, ExecutionEngine* caller, ExecutionThread et = ClientThread )
00650             {
00651                 if (!ee)
00652                     ee = GlobalEngine::Instance();
00653                 this->mmeth = meth;
00654                 this->myengine = ee;
00655                 this->caller = caller;
00656                 this->met = et;
00657             }
00658 
00659             boost::function<Signature> getOperationCallerFunction() const
00660             {
00661                 return this->mmeth;
00662             }
00663 
00664 #ifdef ORO_SIGNALLING_OPERATIONS
00665             void setSignal(typename Signal<Signature>::shared_ptr sig) {
00666                 this->msig = sig;
00667             }
00668 #endif
00669             base::OperationCallerBase<Signature>* cloneI(ExecutionEngine* caller) const
00670             {
00671                 LocalOperationCaller<Signature>* ret = new LocalOperationCaller<Signature>(*this);
00672                 ret->setCaller( caller );
00673 #ifdef ORO_SIGNALLING_OPERATIONS
00674                 ret->setSignal( this->msig );
00675 #endif
00676                 return ret;
00677             }
00678 
00679             typename LocalOperationCallerImpl<Signature>::shared_ptr cloneRT() const
00680             {
00681                 //void* obj = oro_rt_malloc(sizeof(LocalOperationCallerImpl<Signature>));
00682                 //return new(obj) LocalOperationCaller<Signature>(*this);
00683                 return boost::allocate_shared<LocalOperationCaller<Signature> >(os::rt_allocator<LocalOperationCaller<Signature> >(), *this);
00684             }
00685         };
00686     }
00687 }
00688 
00689 #endif