Orocos Real-Time Toolkit  2.5.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 
00074             operator T() { return arg;}
00075         };
00076 
00077         template<class T>
00078         struct AStore<T&>
00079         {
00080             T* arg;
00081             AStore() : arg( &NA<T&>::na() ) {}
00082             AStore(T& t) : arg(&t) {}
00083             AStore(AStore const& o) : arg(o.arg) {}
00084 
00085             T& get() { return *arg; }
00086             void operator()(T& a) { arg = &a; }
00087 
00088             operator T&() { return *arg;}
00089         };
00090 
00091         template<class T>
00092         std::ostream& operator<<(std::ostream& o, AStore<T>& a) { o << "aarg:"<<a.get(); return o;}
00093 
00101         template<class T>
00102         struct RStore {
00103             T arg;
00104             bool executed;
00105             RStore() : arg(), executed(false) {}
00106 
00107             bool isExecuted() const {
00108                 return executed;
00109             }
00110 
00111             //bool operator()() { return executed; }
00112 
00113             T& result() { return arg; }
00114             operator T&() { return arg;}
00115 
00122             template<class F>
00123             void exec(F f) {
00124                 arg = f();
00125                 executed = true;
00126             }
00127 
00128         };
00129 
00130         template<class T>
00131         struct RStore<T&>
00132         {
00133             T* arg;
00134             bool executed;
00135             RStore() : arg(0), executed(false) {}
00136 
00137             template<class F>
00138             void exec(F f) {
00139               arg = &f();
00140               executed = true;
00141             }
00142 
00143             bool isExecuted() const {
00144                 return executed;
00145             }
00146 
00147             //bool operator()() { return executed; }
00148 
00149             T& result() { return *arg; }
00150             operator T&() { return *arg;}
00151         };
00152 
00153         template<class T>
00154         struct RStore<const T> {
00155             T arg;
00156             bool executed;
00157             RStore() : arg(), executed(false) {}
00158 
00159             bool isExecuted() const {
00160                 return executed;
00161             }
00162 
00163             //bool operator()() { return executed; }
00164 
00165             T& result() { return arg; }
00166             operator T&() { return arg;}
00167 
00174             template<class F>
00175             void exec(F f) {
00176                 arg = f();
00177                 executed = true;
00178             }
00179 
00180         };
00181 
00182         template<>
00183         struct RStore<void> {
00184             bool executed;
00185             RStore() :executed(false) {}
00186 
00187             template<class F>
00188             void exec(F f) {
00189                 f();
00190                 executed = true;
00191             }
00192 
00193             bool isExecuted() const {
00194                 return executed;
00195             }
00196 
00197             //bool operator()() { return executed; }
00198 
00199             void result() { return; }
00200         };
00201 
00202         template<class T>
00203         std::ostream& operator<<(std::ostream& o, RStore<T>& a) { o << "rarg:"<<a.result(); return o;}
00204 
00212         template<class Arg>
00213         struct is_arg_return : public mpl::false_ {};
00214 
00215         template<class T>
00216         struct is_arg_return<AStore<T&> > : public mpl::true_
00217         {};
00218 
00219         template<class T>
00220         struct is_arg_return<AStore<T const &> > : public mpl::false_
00221         {};
00222 
00223         template<>
00224         struct is_arg_return<RStore<void> > : public mpl::false_
00225         {};
00226 
00227         template<class T>
00228         struct is_arg_return<RStore<T> > : public mpl::true_
00229         {};
00230 
00234         template<class Arg>
00235         struct is_out_arg : public mpl::false_ {};
00236 
00237         template<class T>
00238         struct is_out_arg<AStore<T&> > : public mpl::true_
00239         {};
00240 
00241         template<class T>
00242         struct is_out_arg<AStore<T const &> > : public mpl::false_
00243         {};
00244 
00245         template<int, class T>
00246         struct BindStorageImpl;
00247 
00252         template<class ToBind>
00253         struct BindStorageImpl<0, ToBind>
00254         {
00255             typedef typename boost::function_traits<ToBind>::result_type result_type;
00256             typedef RStore<result_type> RStoreType;
00257 
00258             boost::function<ToBind> mmeth;
00259 
00260             mutable RStore<result_type> retv;
00261 #ifdef ORO_SIGNALLING_OPERATIONS
00262             typename Signal<ToBind>::shared_ptr msig;
00263 #endif
00264             // stores the original function pointer
00265 
00266             // the list of all our storage.
00267             bf::vector< RStore<result_type>&> vStore;
00268             BindStorageImpl() :  vStore(boost::ref(retv)) {}
00269             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv) {}
00270 
00271             void exec() {
00272 #ifdef ORO_SIGNALLING_OPERATIONS
00273                 if (msig) msig->emit();
00274 #endif
00275                 if (mmeth)
00276                     retv.exec( mmeth );
00277                 else
00278                     retv.executed = true;
00279             }
00280         };
00281 
00285         template<class ToBind>
00286         struct BindStorageImpl<1, ToBind>
00287         {
00288             typedef typename boost::function_traits<ToBind>::result_type result_type;
00289             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00290             typedef RStore<result_type> RStoreType;
00291 
00292             // stores the original function pointer, supplied by the user.
00293             boost::function<ToBind>  mmeth;
00294             // Store the argument.
00295             mutable AStore<arg1_type> a1;
00296             mutable RStore<result_type> retv;
00297 #ifdef ORO_SIGNALLING_OPERATIONS
00298             typename Signal<ToBind>::shared_ptr msig;
00299 #endif
00300 
00301             // the list of all our storage.
00302             bf::vector< RStore<result_type>&, AStore<arg1_type>& > vStore;
00303             BindStorageImpl() : vStore(retv,a1) {}
00304             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1) {}
00305             void store(arg1_type t1) { a1(t1); }
00306             void exec() {
00307 #ifdef ORO_SIGNALLING_OPERATIONS
00308                 if (msig) (*msig)(a1.get());
00309 #endif
00310                 if (mmeth)
00311                     retv.exec( boost::bind(mmeth, boost::ref(a1.get()) ) );
00312                 else
00313                     retv.executed = true;
00314             }
00315 
00316         };
00317 
00318         template<class ToBind>
00319         struct BindStorageImpl<2, ToBind>
00320         {
00321             typedef typename boost::function_traits<ToBind>::result_type result_type;
00322             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00323             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00324             typedef RStore<result_type> RStoreType;
00325 
00326             // stores the original function pointer
00327             boost::function<ToBind> mmeth;
00328             // Store the arguments.
00329             mutable AStore<arg1_type> a1;
00330             mutable AStore<arg2_type> a2;
00331             mutable RStore<result_type> retv;
00332 #ifdef ORO_SIGNALLING_OPERATIONS
00333             typename Signal<ToBind>::shared_ptr msig;
00334 #endif
00335 
00336             // the list of all our storage.
00337             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>& > vStore;
00338             BindStorageImpl() : vStore(retv,a1,a2) {}
00339             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2) {}
00340 
00341             void store(arg1_type t1, arg2_type t2) { a1(t1); a2(t2); }
00342             void exec() {
00343 #ifdef ORO_SIGNALLING_OPERATIONS
00344                 if (msig) (*msig)(a1.get(), a2.get());
00345 #endif
00346                 if (mmeth)
00347                     retv.exec( boost::bind(mmeth, boost::ref(a1.get()), boost::ref(a2.get()) ) );
00348                 else
00349                     retv.executed = true;
00350             }
00351 
00352         };
00353 
00354         template<class ToBind>
00355         struct BindStorageImpl<3, ToBind>
00356         {
00357             typedef typename boost::function_traits<ToBind>::result_type result_type;
00358             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00359             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00360             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00361             typedef RStore<result_type> RStoreType;
00362 
00363             // stores the original function pointer
00364             boost::function<ToBind> mmeth;
00365             // Store the arguments.
00366             mutable AStore<arg1_type> a1;
00367             mutable AStore<arg2_type> a2;
00368             mutable AStore<arg3_type> a3;
00369             mutable RStore<result_type> retv;
00370 #ifdef ORO_SIGNALLING_OPERATIONS
00371             typename Signal<ToBind>::shared_ptr msig;
00372 #endif
00373 
00374             // the list of all our storage.
00375             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>&, AStore<arg3_type>& > vStore;
00376             BindStorageImpl() : vStore(retv,a1,a2,a3) {}
00377             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3) {}
00378 
00379             void store(arg1_type t1, arg2_type t2, arg3_type t3) { a1(t1); a2(t2); a3(t3); }
00380             void exec() {
00381 #ifdef ORO_SIGNALLING_OPERATIONS
00382                 if (msig) (*msig)(a1.get(), a2.get(), a3.get());
00383 #endif
00384                 if (mmeth)
00385                     retv.exec( boost::bind(mmeth, boost::ref(a1.get()), boost::ref(a2.get()), boost::ref(a3.get()) ) );
00386                 else
00387                     retv.executed = true;
00388             }
00389         };
00390 
00391         template<class ToBind>
00392         struct BindStorageImpl<4, ToBind>
00393         {
00394             typedef typename boost::function_traits<ToBind>::result_type result_type;
00395             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00396             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00397             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00398             typedef typename boost::function_traits<ToBind>::arg4_type   arg4_type;
00399             typedef RStore<result_type> RStoreType;
00400 
00401             // stores the original function pointer
00402             boost::function<ToBind> mmeth;
00403             // Store the arguments.
00404             mutable AStore<arg1_type> a1;
00405             mutable AStore<arg2_type> a2;
00406             mutable AStore<arg3_type> a3;
00407             mutable AStore<arg4_type> a4;
00408             mutable RStore<result_type> retv;
00409 #ifdef ORO_SIGNALLING_OPERATIONS
00410             typename Signal<ToBind>::shared_ptr msig;
00411 #endif
00412 
00413             // the list of all our storage.
00414             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>&, AStore<arg3_type>&, AStore<arg4_type>& > vStore;
00415             BindStorageImpl() : vStore(retv,a1,a2,a3,a4) {}
00416             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3,a4) {}
00417 
00418             void store(arg1_type t1, arg2_type t2, arg3_type t3, arg4_type t4) { a1(t1); a2(t2); a3(t3); a4(t4); }
00419             void exec() {
00420 #ifdef ORO_SIGNALLING_OPERATIONS
00421                 if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get());
00422 #endif
00423                 if (mmeth)
00424                     retv.exec( boost::bind( mmeth, boost::ref(a1.get()), boost::ref(a2.get()), boost::ref(a3.get()), boost::ref(a4.get()) ) );
00425                 else
00426                     retv.executed = true;
00427             }
00428         };
00429 
00430         template<class ToBind>
00431         struct BindStorageImpl<5, ToBind>
00432         {
00433             typedef typename boost::function_traits<ToBind>::result_type result_type;
00434             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00435             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00436             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00437             typedef typename boost::function_traits<ToBind>::arg4_type   arg4_type;
00438             typedef typename boost::function_traits<ToBind>::arg5_type   arg5_type;
00439             typedef RStore<result_type> RStoreType;
00440 
00441             // stores the original function pointer
00442             boost::function<ToBind> mmeth;
00443             // Store the arguments.
00444             mutable AStore<arg1_type> a1;
00445             mutable AStore<arg2_type> a2;
00446             mutable AStore<arg3_type> a3;
00447             mutable AStore<arg4_type> a4;
00448             mutable AStore<arg5_type> a5;
00449             mutable RStore<result_type> retv;
00450 #ifdef ORO_SIGNALLING_OPERATIONS
00451             typename Signal<ToBind>::shared_ptr msig;
00452 #endif
00453 
00454             // the list of all our storage.
00455             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>&, AStore<arg3_type>&, AStore<arg4_type>&, AStore<arg5_type>& > vStore;
00456             BindStorageImpl() : vStore(retv,a1,a2,a3,a4,a5) {}
00457             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3,a4,a5) {}
00458 
00459             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);}
00460             void exec() {
00461 #ifdef ORO_SIGNALLING_OPERATIONS
00462                 if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get(), a5.get());
00463 #endif
00464                 if (mmeth)
00465                     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()) ) );
00466                 else
00467                     retv.executed = true;
00468             }
00469         };
00470 
00471         template<class ToBind>
00472         struct BindStorageImpl<6, ToBind>
00473         {
00474             typedef typename boost::function_traits<ToBind>::result_type result_type;
00475             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00476             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00477             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00478             typedef typename boost::function_traits<ToBind>::arg4_type   arg4_type;
00479             typedef typename boost::function_traits<ToBind>::arg5_type   arg5_type;
00480             typedef typename boost::function_traits<ToBind>::arg6_type   arg6_type;
00481             typedef RStore<result_type> RStoreType;
00482 
00483             // stores the original function pointer
00484             boost::function<ToBind> mmeth;
00485             // Store the arguments.
00486             mutable AStore<arg1_type> a1;
00487             mutable AStore<arg2_type> a2;
00488             mutable AStore<arg3_type> a3;
00489             mutable AStore<arg4_type> a4;
00490             mutable AStore<arg5_type> a5;
00491             mutable AStore<arg6_type> a6;
00492             mutable RStore<result_type> retv;
00493 #ifdef ORO_SIGNALLING_OPERATIONS
00494             typename Signal<ToBind>::shared_ptr msig;
00495 #endif
00496 
00497             // the list of all our storage.
00498             bf::vector< RStore<result_type>&, AStore<arg1_type>&, AStore<arg2_type>&, AStore<arg3_type>&, AStore<arg4_type>&, AStore<arg5_type>&, AStore<arg6_type>& > vStore;
00499             BindStorageImpl() : vStore(retv,a1,a2,a3,a4,a5,a6) {}
00500             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3,a4,a5,a6) {}
00501 
00502             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);}
00503             void exec() {
00504 #ifdef ORO_SIGNALLING_OPERATIONS
00505                 if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get(), a5.get(), a6.get());
00506 #endif
00507                 if (mmeth)
00508                     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()) ) );
00509                 else
00510                     retv.executed = true;
00511             }
00512         };
00513 
00514         template<class ToBind>
00515         struct BindStorageImpl<7, ToBind>
00516         {
00517             typedef typename boost::function_traits<ToBind>::result_type result_type;
00518             typedef typename boost::function_traits<ToBind>::arg1_type   arg1_type;
00519             typedef typename boost::function_traits<ToBind>::arg2_type   arg2_type;
00520             typedef typename boost::function_traits<ToBind>::arg3_type   arg3_type;
00521             typedef typename boost::function_traits<ToBind>::arg4_type   arg4_type;
00522             typedef typename boost::function_traits<ToBind>::arg5_type   arg5_type;
00523             typedef typename boost::function_traits<ToBind>::arg6_type   arg6_type;
00524             typedef typename boost::function_traits<ToBind>::arg7_type   arg7_type;
00525             typedef RStore<result_type> RStoreType;
00526 
00527             // stores the original function pointer
00528             boost::function<ToBind> mmeth;
00529             // Store the arguments.
00530             mutable AStore<arg1_type> a1;
00531             mutable AStore<arg2_type> a2;
00532             mutable AStore<arg3_type> a3;
00533             mutable AStore<arg4_type> a4;
00534             mutable AStore<arg5_type> a5;
00535             mutable AStore<arg6_type> a6;
00536             mutable AStore<arg7_type> a7;
00537             mutable RStore<result_type> retv;
00538 #ifdef ORO_SIGNALLING_OPERATIONS
00539             typename Signal<ToBind>::shared_ptr msig;
00540 #endif
00541 
00542             // the list of all our storage.
00543             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;
00544             BindStorageImpl() : vStore(retv,a1,a2,a3,a4,a5,a6,a7) {}
00545             BindStorageImpl(const BindStorageImpl& orig) : mmeth(orig.mmeth), vStore(retv,a1,a2,a3,a4,a5,a6,a7) {}
00546 
00547             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);}
00548             void exec() {
00549 #ifdef ORO_SIGNALLING_OPERATIONS
00550                 if (msig) (*msig)(a1.get(), a2.get(), a3.get(), a4.get(), a5.get(), a6.get(), a7.get());
00551 #endif
00552                 if (mmeth)
00553                     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()) ) );
00554                 else
00555                     retv.executed = true;
00556             }
00557         };
00558 
00559 
00578         template<class ToBind>
00579         struct BindStorage
00580             : public BindStorageImpl<boost::function_traits<ToBind>::arity, ToBind>
00581         {
00582         };
00583     }
00584 }
00585 #endif