$search
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