ScopeGuard.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2000 Andrei Alexandrescu
00004 // Copyright (c) 2000 Petru Marginean
00005 // Copyright (c) 2005 Joshua Lehrer
00006 //
00007 // Permission to use, copy, modify, distribute and sell this software for any 
00008 //     purpose is hereby granted without fee, provided that the above copyright 
00009 //     notice appear in all copies and that both that copyright notice and this 
00010 //     permission notice appear in supporting documentation.
00011 // The author makes no representations about the 
00012 //     suitability of this software for any purpose. It is provided "as is" 
00013 //     without express or implied warranty.
00015 #ifndef LOKI_SCOPEGUARD_INC_
00016 #define LOKI_SCOPEGUARD_INC_
00017 
00018 // $Id: ScopeGuard.h 799 2006-12-20 00:37:13Z rich_sposato $
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 } // namespace Loki
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 

Generated on Sun Feb 25 16:52:27 2007 for Loki by  doxygen 1.5.1-p1