00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015 #ifndef LOKI_SCOPEGUARD_INC_
00016 #define LOKI_SCOPEGUARD_INC_
00017
00018
00019
00020
00021 #include <loki/RefToValue.h>
00022
00024
00025 namespace Loki
00026 {
00027
00042
00043 class ScopeGuardImplBase
00044 {
00046 ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
00047
00048 protected:
00049
00050 ~ScopeGuardImplBase()
00051 {}
00052
00054 ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
00055 : dismissed_(other.dismissed_)
00056 {
00057 other.Dismiss();
00058 }
00059
00060 template <typename J>
00061 static void SafeExecute(J& j) throw()
00062 {
00063 if (!j.dismissed_)
00064 try
00065 {
00066 j.Execute();
00067 }
00068 catch(...)
00069 {}
00070 }
00071
00072 mutable bool dismissed_;
00073
00074 public:
00075 ScopeGuardImplBase() throw() : dismissed_(false)
00076 {}
00077
00078 void Dismiss() const throw()
00079 {
00080 dismissed_ = true;
00081 }
00082 };
00083
00090
00091 typedef const ScopeGuardImplBase& ScopeGuard;
00092
00106
00107 template <typename F>
00108 class ScopeGuardImpl0 : public ScopeGuardImplBase
00109 {
00110 public:
00111 static ScopeGuardImpl0<F> MakeGuard(F fun)
00112 {
00113 return ScopeGuardImpl0<F>(fun);
00114 }
00115
00116 ~ScopeGuardImpl0() throw()
00117 {
00118 SafeExecute(*this);
00119 }
00120
00121 void Execute()
00122 {
00123 fun_();
00124 }
00125
00126 protected:
00127 ScopeGuardImpl0(F fun) : fun_(fun)
00128 {}
00129
00130 F fun_;
00131 };
00132
00133 template <typename F>
00134 inline ScopeGuardImpl0<F> MakeGuard(F fun)
00135 {
00136 return ScopeGuardImpl0<F>::MakeGuard(fun);
00137 }
00138
00153
00154 template <typename F, typename P1>
00155 class ScopeGuardImpl1 : public ScopeGuardImplBase
00156 {
00157 public:
00158 static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
00159 {
00160 return ScopeGuardImpl1<F, P1>(fun, p1);
00161 }
00162
00163 ~ScopeGuardImpl1() throw()
00164 {
00165 SafeExecute(*this);
00166 }
00167
00168 void Execute()
00169 {
00170 fun_(p1_);
00171 }
00172
00173 protected:
00174 ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
00175 {}
00176
00177 F fun_;
00178 const P1 p1_;
00179 };
00180
00181 template <typename F, typename P1>
00182 inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
00183 {
00184 return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
00185 }
00186
00201
00202 template <typename F, typename P1, typename P2>
00203 class ScopeGuardImpl2: public ScopeGuardImplBase
00204 {
00205 public:
00206 static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
00207 {
00208 return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
00209 }
00210
00211 ~ScopeGuardImpl2() throw()
00212 {
00213 SafeExecute(*this);
00214 }
00215
00216 void Execute()
00217 {
00218 fun_(p1_, p2_);
00219 }
00220
00221 protected:
00222 ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2)
00223 {}
00224
00225 F fun_;
00226 const P1 p1_;
00227 const P2 p2_;
00228 };
00229
00230 template <typename F, typename P1, typename P2>
00231 inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
00232 {
00233 return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
00234 }
00235
00250
00251 template <typename F, typename P1, typename P2, typename P3>
00252 class ScopeGuardImpl3 : public ScopeGuardImplBase
00253 {
00254 public:
00255 static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
00256 {
00257 return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
00258 }
00259
00260 ~ScopeGuardImpl3() throw()
00261 {
00262 SafeExecute(*this);
00263 }
00264
00265 void Execute()
00266 {
00267 fun_(p1_, p2_, p3_);
00268 }
00269
00270 protected:
00271 ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3)
00272 {}
00273
00274 F fun_;
00275 const P1 p1_;
00276 const P2 p2_;
00277 const P3 p3_;
00278 };
00279
00280 template <typename F, typename P1, typename P2, typename P3>
00281 inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
00282 {
00283 return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
00284 }
00285
00300
00301 template < typename F, typename P1, typename P2, typename P3, typename P4 >
00302 class ScopeGuardImpl4 : public ScopeGuardImplBase
00303 {
00304 public:
00305 static ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard(
00306 F fun, P1 p1, P2 p2, P3 p3, P4 p4 )
00307 {
00308 return ScopeGuardImpl4< F, P1, P2, P3, P4 >( fun, p1, p2, p3, p4 );
00309 }
00310
00311 ~ScopeGuardImpl4() throw()
00312 {
00313 SafeExecute( *this );
00314 }
00315
00316 void Execute()
00317 {
00318 fun_( p1_, p2_, p3_, p4_ );
00319 }
00320
00321 protected:
00322 ScopeGuardImpl4( F fun, P1 p1, P2 p2, P3 p3, P4 p4 ) :
00323 fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 )
00324 {}
00325
00326 F fun_;
00327 const P1 p1_;
00328 const P2 p2_;
00329 const P3 p3_;
00330 const P4 p4_;
00331 };
00332
00333 template < typename F, typename P1, typename P2, typename P3, typename P4 >
00334 inline ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4 )
00335 {
00336 return ScopeGuardImpl4< F, P1, P2, P3, P4 >::MakeGuard( fun, p1, p2, p3, p4 );
00337 }
00338
00353
00354 template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 >
00355 class ScopeGuardImpl5 : public ScopeGuardImplBase
00356 {
00357 public:
00358 static ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard(
00359 F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 )
00360 {
00361 return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >( fun, p1, p2, p3, p4, p5 );
00362 }
00363
00364 ~ScopeGuardImpl5() throw()
00365 {
00366 SafeExecute( *this );
00367 }
00368
00369 void Execute()
00370 {
00371 fun_( p1_, p2_, p3_, p4_, p5_ );
00372 }
00373
00374 protected:
00375 ScopeGuardImpl5( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) :
00376 fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 ), p5_( p5 )
00377 {}
00378
00379 F fun_;
00380 const P1 p1_;
00381 const P2 p2_;
00382 const P3 p3_;
00383 const P4 p4_;
00384 const P5 p5_;
00385 };
00386
00387 template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 >
00388 inline ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 )
00389 {
00390 return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >::MakeGuard( fun, p1, p2, p3, p4, p5 );
00391 }
00392
00408
00409 template <class Obj, typename MemFun>
00410 class ObjScopeGuardImpl0 : public ScopeGuardImplBase
00411 {
00412 public:
00413 static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
00414 {
00415 return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
00416 }
00417
00418 ~ObjScopeGuardImpl0() throw()
00419 {
00420 SafeExecute(*this);
00421 }
00422
00423 void Execute()
00424 {
00425 (obj_.*memFun_)();
00426 }
00427
00428 protected:
00429 ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun)
00430 {}
00431
00432 Obj& obj_;
00433 MemFun memFun_;
00434 };
00435
00436 template <class Obj, typename MemFun>
00437 inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
00438 {
00439 return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
00440 }
00441
00442 template <typename Ret, class Obj1, class Obj2>
00443 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj)
00444 {
00445 return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(obj,memFun);
00446 }
00447
00448 template <typename Ret, class Obj1, class Obj2>
00449 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj)
00450 {
00451 return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(*obj,memFun);
00452 }
00453
00470
00471 template <class Obj, typename MemFun, typename P1>
00472 class ObjScopeGuardImpl1 : public ScopeGuardImplBase
00473 {
00474 public:
00475 static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00476 {
00477 return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
00478 }
00479
00480 ~ObjScopeGuardImpl1() throw()
00481 {
00482 SafeExecute(*this);
00483 }
00484
00485 void Execute()
00486 {
00487 (obj_.*memFun_)(p1_);
00488 }
00489
00490 protected:
00491 ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1)
00492 {}
00493
00494 Obj& obj_;
00495 MemFun memFun_;
00496 const P1 p1_;
00497 };
00498
00499 template <class Obj, typename MemFun, typename P1>
00500 inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00501 {
00502 return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
00503 }
00504
00505 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
00506 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1)
00507 {
00508 return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(obj,memFun,p1);
00509 }
00510
00511 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
00512 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1)
00513 {
00514 return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1);
00515 }
00516
00533
00534 template <class Obj, typename MemFun, typename P1, typename P2>
00535 class ObjScopeGuardImpl2 : public ScopeGuardImplBase
00536 {
00537 public:
00538 static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00539 {
00540 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
00541 }
00542
00543 ~ObjScopeGuardImpl2() throw()
00544 {
00545 SafeExecute(*this);
00546 }
00547
00548 void Execute()
00549 {
00550 (obj_.*memFun_)(p1_, p2_);
00551 }
00552
00553 protected:
00554 ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2)
00555 {}
00556
00557 Obj& obj_;
00558 MemFun memFun_;
00559 const P1 p1_;
00560 const P2 p2_;
00561 };
00562
00563 template <class Obj, typename MemFun, typename P1, typename P2>
00564 inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00565 {
00566 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
00567 }
00568
00569 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
00570 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2)
00571 {
00572 return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2);
00573 }
00574
00575 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
00576 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2)
00577 {
00578 return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2);
00579 }
00580
00597
00598 template < class Obj, typename MemFun, typename P1, typename P2, typename P3 >
00599 class ObjScopeGuardImpl3 : public ScopeGuardImplBase
00600 {
00601 public:
00602 static ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard(
00603 Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 )
00604 {
00605 return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >( obj, memFun, p1, p2, p3 );
00606 }
00607
00608 ~ObjScopeGuardImpl3() throw()
00609 {
00610 SafeExecute( *this );
00611 }
00612
00613 void Execute()
00614 {
00615 ( obj_.*memFun_ )( p1_, p2_, p3_ );
00616 }
00617
00618 protected:
00619 ObjScopeGuardImpl3( Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 ) :
00620 obj_( obj ), memFun_( memFun ), p1_( p1 ), p2_( p2 ), p3_( p3 )
00621 {}
00622
00623 Obj& obj_;
00624 MemFun memFun_;
00625 const P1 p1_;
00626 const P2 p2_;
00627 const P3 p3_;
00628 };
00629
00630 template < class Obj, typename MemFun, typename P1, typename P2, typename P3 >
00631 inline ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard(
00632 Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 )
00633 {
00634 return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >::MakeObjGuard(
00635 obj, memFun, p1, p2, p3 );
00636 }
00637
00638 template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b,
00639 typename P2a, typename P2b, typename P3a, typename P3b >
00640 inline ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
00641 MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 & obj, P1b p1, P2b p2, P3b p3 )
00642 {
00643 return ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
00644 ::MakeObjGuard( obj, memFun, p1, p2, p3 );
00645 }
00646
00647 template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b,
00648 typename P2a, typename P2b, typename P3a, typename P3b >
00649 inline ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
00650 MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 * obj, P1b p1, P2b p2, P3b p3 )
00651 {
00652 return ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
00653 ::MakeObjGuard( *obj, memFun, p1, p2, p3 );
00654 }
00655
00656 }
00657
00658 #define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2
00659 #define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2)
00660 #define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__)
00661
00662 #define LOKI_ON_BLOCK_EXIT ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeGuard
00663 #define LOKI_ON_BLOCK_EXIT_OBJ ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeObjGuard
00664
00665 #endif // end file guardian
00666