Orocos Real-Time Toolkit  2.6.0
BindStorage.hpp
00001 /***************************************************************************
00002   tag: FMTC  do nov 2 13:06:12 CET 2006  BindStorage.hpp
00003 
00004                         BindStorage.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_TASK_BIND_STORAGE_HPP
00040 #define ORO_TASK_BIND_STORAGE_HPP
00041 
00042 #include <boost/function.hpp>
00043 #include <boost/type_traits/function_traits.hpp>
00044 #include <boost/bind.hpp>
00045 #include <boost/fusion/include/vector.hpp>
00046 #include <boost/fusion/include/filter_if.hpp>
00047 #include "NA.hpp"
00048 
00049 #ifdef ORO_SIGNALLING_OPERATIONS
00050 #include "Signal.hpp"
00051 #endif
00052 
00053 namespace RTT
00054 {
00055     namespace internal
00056     {
00057         namespace bf=boost::fusion;
00058         namespace mpl=boost::mpl;
00063         template<class T>
00064         struct AStore
00065         {
00066             T arg;
00067             AStore() : arg() {}
00068             AStore(T t) : arg(t) {}
00069             AStore(AStore const& o) : arg(o.arg) {}
00070 
00071             T& get() { return arg; }
00072             void operator()(T a) { arg = a; }
00073             operator T() { return arg;}
00074         };
00075 
00076         template<class T>
00077         struct AStore<T&>
00078         {
00079             T* arg;
00080             AStore() : arg( &NA<T&>::na() ) {}
00081             AStore(T& t) : arg(&t) {}
00082             AStore(AStore const& o) : arg(o.arg) {}
00083 
00084             T& get() { return *arg; }
00085             void operator()(T& a) { arg = &a; }
00086             operator T&() { return *arg;}
00087         };
00088 
00089         template<class T>
00090         std::ostream& operator<<(std::ostream& o, AStore<T>& a) { o << "aarg:"<<a.get(); return o;}
00091 
00092         template<>
00093         struct RStore<void> {
00094             bool executed;
00095             bool error;
00096             RStore() : executed(false), error(false) {}
00097 
00098             void checkError() const {
00099               if(error) throw std::runtime_error("Unable to complete the operation call. The called operation has thrown an exception");
00100             }
00101 
00102             bool isError() const {
00103               return error;
00104             }
00105 
00106             bool isExecuted() const {
00107                 return executed;
00108             }
00109 
00110             template<class F>
00111             void exec(F f) {
00112                 error = false;
00113                 try{
00114                     f();
00115                 } catch (std::exception& e) {
00116                     log(Error) << "Exception raised while executing an operation : "  << e.what() << endlog();
00117                     error = true;
00118                 } catch (...) {
00119                     log(Error) << "Unknown exception raised while executing an operation." << endlog();
00120                     error = true;
00121                 }
00122                 executed = true;
00123             }
00124 
00125             void result() { checkError(); return; }
00126         };
00127 
00128 
00136         template<class T>
00137         struct RStore : public RStore<void> {
00138             T arg;
00139             RStore() : arg() {}
00140 
00141             T& result() { checkError(); return arg; }
00142             operator T&() { return arg;}
00143 
00150             template<class F>
00151             void exec(F f) {
00152                 error = false;
00153                 try{
00154                     arg = f();
00155                 } catch (std::exception& e) {
00156                     log(Error) << "Exception raised while executing an operation : "  << e.what() << endlog();
00157                     error = true;
00158                 } catch (...) {
00159                     log(Error) << "Unknown exception raised while executing an operation." << endlog();
00160                     error = true;
00161                 }
00162                 executed = true;
00163             }
00164         };
00165 
00166         template<class T>
00167         struct RStore<T&> : public RStore<void>
00168         {
00169             T* arg;
00170             RStore() : arg() {}
00171 
00172             template<class F>
00173             void exec(F f) {
00174                 error = false;
00175                 try{
00176                     arg = &f();
00177                 } catch (std::exception& e) {
00178                     log(Error) << "Exception raised while executing an operation : "  << e.what() << endlog();
00179                     error = true;
00180                 } catch (...) {
00181                     log(Error) << "Unknown exception raised while executing an operation." << endlog();
00182                     error = true;
00183                 }
00184                 executed = true;
00185             }
00186 
00187             //bool operator()() { return executed; }
00188 
00189             T& result() { checkError(); return *arg; }
00190             operator T&() { checkError(); return *arg;}
00191         };
00192 
00193         template<class T>
00194         struct RStore<const T> : public RStore<void> {
00195             T arg;
00196             RStore() : arg() {}
00197 
00198             T& result() { checkError(); return arg; }
00199             operator T&() { checkError(); return arg;}
00200 
00207             template<class F>
00208             void exec(F f) {
00209                 error = false;
00210                 try{
00211                     arg = f();
00212                 } catch (std::exception& e) {
00213                     log(Error) << "Exception raised while executing an operation : "  << e.what() << endlog();
00214                     error = true;
00215                 } catch(...) {
00216                     log(Error) << "Unknown exception raised while executing an operation." << endlog();
00217                     error = true;
00218                 }
00219                 executed = true;
00220             }
00221 
00222         };
00223 
00224         template<class T>
00225         std::ostream& operator<<(std::ostream& o, RStore<T>& a) { o << "rarg:"<<a.result(); return o;}
00226 
00234         template<class Arg>
00235         struct is_arg_return : public mpl::false_ {};
00236 
00237         template<class T>
00238         struct is_arg_return<AStore<T&> > : public mpl::true_
00239         {};
00240 
00241         template<class T>
00242         struct is_arg_return<AStore<T const &> > : public mpl::false_
00243         {};
00244 
00245         template<>
00246         struct is_arg_return<RStore<void> > : public mpl::false_
00247         {};
00248 
00249         template<class T>
00250         struct is_arg_return<RStore<T> > : public mpl::true_
00251         {};
00252 
00256         template<class Arg>
00257         struct is_out_arg : public mpl::false_ {};
00258 
00259         template<class T>
00260         struct is_out_arg<AStore<T&> > : public mpl::true_
00261         {};
00262 
00263         template<class T>
00264         struct is_out_arg<AStore<T const &> > : public mpl::false_
00265         {};
00266 
00267         template<int, class T>
00268         struct BindStorageImpl;
00269 
00274         template<class ToBind>
00275         struct BindStorageImpl<0, ToBind>
00276         {
00277             typedef typename boost::function_traits<ToBind>::result_type result_type;
00278             typedef RStore<result_type> RStoreType;
00279 
00280             boost::function<ToBind> mmeth;
00281 
00282             mutable RStore<result_type> retv;
00283 #ifdef ORO_SIGNALLING_OPERATIONS
00284             typename Signal<ToBind>::shared_ptr msig;
00285 #endif
00286             // stores the original function pointer
00287 
00288             // the list of all our storage.
00289             bf::vector< RStore<result_type>&> vStore;
00290             BindStorageImpl() :  vStore(boost::ref(retv)) {}
00291             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv) {}
00292 
00293             void exec() {
00294 #ifdef ORO_SIGNALLING_OPERATIONS
00295                 if (msig) msig->emit();
00296 #endif
00297                 if (mmeth)
00298                     retv.exec( mmeth );
00299                 else
00300                     retv.executed = true;
00301             }
00302         };
00303 
00307         template<class ToBind>
00308         struct BindStorageImpl<1, ToBind>
00309         {
00310             typedef typename boost::function_traits<ToBind>::result_type result_type;
00311             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00312             typedef RStore<result_type> RStoreType;
00313 
00314             // stores the original function pointer, supplied by the user.
00315             boost::function<ToBind>  mmeth;
00316             // Store the argument.
00317             mutable AStore<arg1_type> a1;
00318             mutable RStore<result_type> retv;
00319 #ifdef ORO_SIGNALLING_OPERATIONS
00320             typename Signal<ToBind>::shared_ptr msig;
00321 #endif
00322 
00323             // the list of all our storage.
00324             bf::vector< RStore<result_type>&, AStore<arg1_type>& > vStore;
00325             BindStorageImpl() : vStore(retv,a1) {}
00326             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1) {}
00327             void store(arg1_type t1) { a1(t1); }
00328             void exec() {
00329 #ifdef ORO_SIGNALLING_OPERATIONS
00330                 if (msig) (*msig)(a1.get());
00331 #endif
00332                 if (mmeth)
00333                     retv.exec( boost::bind(mmeth, boost::ref(a1.get()) ) );
00334                 else
00335                     retv.executed = true;
00336             }
00337 
00338         };
00339 
00340         template<class ToBind>
00341         struct BindStorageImpl<2, ToBind>
00342         {
00343             typedef typename boost::function_traits<ToBind>::result_type result_type;
00344             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00345             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00346             typedef RStore<result_type> RStoreType;
00347 
00348             // stores the original function pointer
00349             boost::function<ToBind> mmeth;
00350             // Store the arguments.
00351             mutable AStore<arg1_type> a1;
00352             mutable AStore<arg2_type> a2;
00353             mutable RStore<result_type> retv;
00354 #ifdef ORO_SIGNALLING_OPERATIONS
00355             typename Signal<ToBind>::shared_ptr msig;
00356 #endif
00357 
00358             // the list of all our storage.
00359             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>& > vStore;
00360             BindStorageImpl() : vStore(retv,a1,a2) {}
00361             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2) {}
00362 
00363             void store(arg1_type t1, arg2_type t2) { a1(t1); a2(t2); }
00364             void exec() {
00365 #ifdef ORO_SIGNALLING_OPERATIONS
00366                 if (msig) (*msig)(a1.get(), a2.get());
00367 #endif
00368                 if (mmeth)
00369                     retv.exec( boost::bind(mmeth, boost::ref(a1.get()), boost::ref(a2.get()) ) );
00370                 else
00371                     retv.executed = true;
00372             }
00373 
00374         };
00375 
00376         template<class ToBind>
00377         struct BindStorageImpl<3, ToBind>
00378         {
00379             typedef typename boost::function_traits<ToBind>::result_type result_type;
00380             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00381             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00382             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00383             typedef RStore<result_type> RStoreType;
00384 
00385             // stores the original function pointer
00386             boost::function<ToBind> mmeth;
00387             // Store the arguments.
00388             mutable AStore<arg1_type> a1;
00389             mutable AStore<arg2_type> a2;
00390             mutable AStore<arg3_type> a3;
00391             mutable RStore<result_type> retv;
00392 #ifdef ORO_SIGNALLING_OPERATIONS
00393             typename Signal<ToBind>::shared_ptr msig;
00394 #endif
00395 
00396             // the list of all our storage.
00397             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>&, AStore<arg3_type>& > vStore;
00398             BindStorageImpl() : vStore(retv,a1,a2,a3) {}
00399             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3) {}
00400 
00401             void store(arg1_type t1, arg2_type t2, arg3_type t3) { a1(t1); a2(t2); a3(t3); }
00402             void exec() {
00403 #ifdef ORO_SIGNALLING_OPERATIONS
00404                 if (msig) (*msig)(a1.get(), a2.get(), a3.get());
00405 #endif
00406                 if (mmeth)
00407                     retv.exec( boost::bind(mmeth, boost::ref(a1.get()), boost::ref(a2.get()), boost::ref(a3.get()) ) );
00408                 else
00409                     retv.executed = true;
00410             }
00411         };
00412 
00413         template<class ToBind>
00414         struct BindStorageImpl<4, ToBind>
00415         {
00416             typedef typename boost::function_traits<ToBind>::result_type result_type;
00417             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00418             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00419             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00420             typedef typename boost::function_traits<ToBind>::arg4_type   arg4_type;
00421             typedef RStore<result_type> RStoreType;
00422 
00423             // stores the original function pointer
00424             boost::function<ToBind> mmeth;
00425             // Store the arguments.
00426             mutable AStore<arg1_type> a1;
00427             mutable AStore<arg2_type> a2;
00428             mutable AStore<arg3_type> a3;
00429             mutable AStore<arg4_type> a4;
00430             mutable RStore<result_type> retv;
00431 #ifdef ORO_SIGNALLING_OPERATIONS
00432             typename Signal<ToBind>::shared_ptr msig;
00433 #endif
00434 
00435             // the list of all our storage.
00436             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>&, AStore<arg3_type>&, AStore<arg4_type>& > vStore;
00437             BindStorageImpl() : vStore(retv,a1,a2,a3,a4) {}
00438             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3,a4) {}
00439 
00440             void store(arg1_type t1, arg2_type t2, arg3_type t3, arg4_type t4) { a1(t1); a2(t2); a3(t3); a4(t4); }
00441             void exec() {
00442 #ifdef ORO_SIGNALLING_OPERATIONS
00443                 if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get());
00444 #endif
00445                 if (mmeth)
00446                     retv.exec( boost::bind( mmeth, boost::ref(a1.get()), boost::ref(a2.get()), boost::ref(a3.get()), boost::ref(a4.get()) ) );
00447                 else
00448                     retv.executed = true;
00449             }
00450         };
00451 
00452         template<class ToBind>
00453         struct BindStorageImpl<5, ToBind>
00454         {
00455             typedef typename boost::function_traits<ToBind>::result_type result_type;
00456             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00457             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00458             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00459             typedef typename boost::function_traits<ToBind>::arg4_type   arg4_type;
00460             typedef typename boost::function_traits<ToBind>::arg5_type   arg5_type;
00461             typedef RStore<result_type> RStoreType;
00462 
00463             // stores the original function pointer
00464             boost::function<ToBind> mmeth;
00465             // Store the arguments.
00466             mutable AStore<arg1_type> a1;
00467             mutable AStore<arg2_type> a2;
00468             mutable AStore<arg3_type> a3;
00469             mutable AStore<arg4_type> a4;
00470             mutable AStore<arg5_type> a5;
00471             mutable RStore<result_type> retv;
00472 #ifdef ORO_SIGNALLING_OPERATIONS
00473             typename Signal<ToBind>::shared_ptr msig;
00474 #endif
00475 
00476             // the list of all our storage.
00477             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>&, AStore<arg3_type>&, AStore<arg4_type>&, AStore<arg5_type>& > vStore;
00478             BindStorageImpl() : vStore(retv,a1,a2,a3,a4,a5) {}
00479             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3,a4,a5) {}
00480 
00481             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);}
00482             void exec() {
00483 #ifdef ORO_SIGNALLING_OPERATIONS
00484                 if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get(), a5.get());
00485 #endif
00486                 if (mmeth)
00487                     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()) ) );
00488                 else
00489                     retv.executed = true;
00490             }
00491         };
00492 
00493         template<class ToBind>
00494         struct BindStorageImpl<6, ToBind>
00495         {
00496             typedef typename boost::function_traits<ToBind>::result_type result_type;
00497             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00498             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00499             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00500             typedef typename boost::function_traits<ToBind>::arg4_type   arg4_type;
00501             typedef typename boost::function_traits<ToBind>::arg5_type   arg5_type;
00502             typedef typename boost::function_traits<ToBind>::arg6_type   arg6_type;
00503             typedef RStore<result_type> RStoreType;
00504 
00505             // stores the original function pointer
00506             boost::function<ToBind> mmeth;
00507             // Store the arguments.
00508             mutable AStore<arg1_type> a1;
00509             mutable AStore<arg2_type> a2;
00510             mutable AStore<arg3_type> a3;
00511             mutable AStore<arg4_type> a4;
00512             mutable AStore<arg5_type> a5;
00513             mutable AStore<arg6_type> a6;
00514             mutable RStore<result_type> retv;
00515 #ifdef ORO_SIGNALLING_OPERATIONS
00516             typename Signal<ToBind>::shared_ptr msig;
00517 #endif
00518 
00519             // the list of all our storage.
00520             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>&, AStore<arg3_type>&, AStore<arg4_type>&, AStore<arg5_type>&, AStore<arg6_type>& > vStore;
00521             BindStorageImpl() : vStore(retv,a1,a2,a3,a4,a5,a6) {}
00522             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3,a4,a5,a6) {}
00523 
00524             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);}
00525             void exec() {
00526 #ifdef ORO_SIGNALLING_OPERATIONS
00527                 if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get(), a5.get(), a6.get());
00528 #endif
00529                 if (mmeth)
00530                     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()) ) );
00531                 else
00532                     retv.executed = true;
00533             }
00534         };
00535 
00536         template<class ToBind>
00537         struct BindStorageImpl<7, ToBind>
00538         {
00539             typedef typename boost::function_traits<ToBind>::result_type result_type;
00540             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00541             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00542             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00543             typedef typename boost::function_traits<ToBind>::arg4_type   arg4_type;
00544             typedef typename boost::function_traits<ToBind>::arg5_type   arg5_type;
00545             typedef typename boost::function_traits<ToBind>::arg6_type   arg6_type;
00546             typedef typename boost::function_traits<ToBind>::arg7_type   arg7_type;
00547             typedef RStore<result_type> RStoreType;
00548 
00549             // stores the original function pointer
00550             boost::function<ToBind> mmeth;
00551             // Store the arguments.
00552             mutable AStore<arg1_type> a1;
00553             mutable AStore<arg2_type> a2;
00554             mutable AStore<arg3_type> a3;
00555             mutable AStore<arg4_type> a4;
00556             mutable AStore<arg5_type> a5;
00557             mutable AStore<arg6_type> a6;
00558             mutable AStore<arg7_type> a7;
00559             mutable RStore<result_type> retv;
00560 #ifdef ORO_SIGNALLING_OPERATIONS
00561             typename Signal<ToBind>::shared_ptr msig;
00562 #endif
00563 
00564             // the list of all our storage.
00565             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>&, AStore<arg3_type>&, AStore<arg4_type>&, AStore<arg5_type>&, AStore<arg6_type>&, AStore<arg7_type>& > vStore;
00566             BindStorageImpl() : vStore(retv,a1,a2,a3,a4,a5,a6,a7) {}
00567             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3,a4,a5,a6,a7) {}
00568 
00569             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);}
00570             void exec() {
00571 #ifdef ORO_SIGNALLING_OPERATIONS
00572                 if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get(), a5.get(), a6.get(), a7.get());
00573 #endif
00574                 if (mmeth)
00575                     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()) ) );
00576                 else
00577                     retv.executed = true;
00578             }
00579         };
00580 
00581 
00600         template<class ToBind>
00601         struct BindStorage
00602             : public BindStorageImpl<boost::function_traits<ToBind>::arity, ToBind>
00603         {
00604         };
00605     }
00606 }
00607 #endif