diff --git a/include/loki/ScopeGuard.h b/include/loki/ScopeGuard.h index b2ab1b7..5b277ee 100644 --- a/include/loki/ScopeGuard.h +++ b/include/loki/ScopeGuard.h @@ -4,12 +4,12 @@ // Copyright (c) 2000 Petru Marginean // Copyright (c) 2005 Joshua Lehrer // -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. -// The author makes no representations about the -// suitability of this software for any purpose. It is provided "as is" +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// #ifndef LOKI_SCOPEGUARD_INC_ @@ -17,6 +17,7 @@ // $Id$ +#include // needed for calls to uncaught_exception. #include @@ -42,6 +43,30 @@ namespace Loki class ScopeGuardImplBase { + + public: + + enum ExceptionPolicy + { + AlwaysExecute = 0, + CallIfNoException = 1, + CallIfException = 2 + }; + + ScopeGuardImplBase() throw() : dismissed_(false), exceptionPolicy_( AlwaysExecute ) + {} + + void Dismiss() const throw() + { + dismissed_ = true; + } + + void SetExceptionPolicy( ExceptionPolicy policy ) const throw() + { + exceptionPolicy_ = policy; + } + + private: /// Copy-assignment operator is not implemented and private. ScopeGuardImplBase& operator =(const ScopeGuardImplBase&); @@ -51,34 +76,42 @@ namespace Loki {} /// Copy-constructor takes over responsibility from other ScopeGuard. - ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() + ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() : dismissed_(other.dismissed_) + , exceptionPolicy_( other.exceptionPolicy_ ) { other.Dismiss(); } template - static void SafeExecute(J& j) throw() + static void SafeExecute(J& j) throw() { + if ( AlwaysExecute != j.exceptionPolicy_ ) + { + const bool anyThrown = ::std::uncaught_exception(); + if ( anyThrown ) + { + if ( CallIfNoException == j.exceptionPolicy_ ) + j.Dismiss(); + } + else if ( CallIfException == j.exceptionPolicy_ ) + { + j.Dismiss(); + } + } if (!j.dismissed_) + { try { j.Execute(); } catch(...) {} + } } - + mutable bool dismissed_; - - public: - ScopeGuardImplBase() throw() : dismissed_(false) - {} - - void Dismiss() const throw() - { - dismissed_ = true; - } + mutable ExceptionPolicy exceptionPolicy_; }; //////////////////////////////////////////////////////////////// @@ -113,24 +146,24 @@ namespace Loki return ScopeGuardImpl0(fun); } - ~ScopeGuardImpl0() throw() + ~ScopeGuardImpl0() throw() { SafeExecute(*this); } - void Execute() + void Execute() { fun_(); } protected: - ScopeGuardImpl0(F fun) : fun_(fun) + ScopeGuardImpl0(F fun) : fun_(fun) {} F fun_; }; - template + template inline ScopeGuardImpl0 MakeGuard(F fun) { return ScopeGuardImpl0::MakeGuard(fun); @@ -160,7 +193,7 @@ namespace Loki return ScopeGuardImpl1(fun, p1); } - ~ScopeGuardImpl1() throw() + ~ScopeGuardImpl1() throw() { SafeExecute(*this); } @@ -171,14 +204,14 @@ namespace Loki } protected: - ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) + ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) {} F fun_; const P1 p1_; }; - template + template inline ScopeGuardImpl1 MakeGuard(F fun, P1 p1) { return ScopeGuardImpl1::MakeGuard(fun, p1); @@ -208,7 +241,7 @@ namespace Loki return ScopeGuardImpl2(fun, p1, p2); } - ~ScopeGuardImpl2() throw() + ~ScopeGuardImpl2() throw() { SafeExecute(*this); } @@ -219,7 +252,7 @@ namespace Loki } protected: - ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) + ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) {} F fun_; @@ -257,7 +290,7 @@ namespace Loki return ScopeGuardImpl3(fun, p1, p2, p3); } - ~ScopeGuardImpl3() throw() + ~ScopeGuardImpl3() throw() { SafeExecute(*this); } @@ -268,7 +301,7 @@ namespace Loki } protected: - ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) + ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) {} F fun_; @@ -308,7 +341,7 @@ namespace Loki return ScopeGuardImpl4< F, P1, P2, P3, P4 >( fun, p1, p2, p3, p4 ); } - ~ScopeGuardImpl4() throw() + ~ScopeGuardImpl4() throw() { SafeExecute( *this ); } @@ -361,7 +394,7 @@ namespace Loki return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >( fun, p1, p2, p3, p4, p5 ); } - ~ScopeGuardImpl5() throw() + ~ScopeGuardImpl5() throw() { SafeExecute( *this ); } @@ -415,18 +448,18 @@ namespace Loki return ObjScopeGuardImpl0(obj, memFun); } - ~ObjScopeGuardImpl0() throw() + ~ObjScopeGuardImpl0() throw() { SafeExecute(*this); } - void Execute() + void Execute() { (obj_.*memFun_)(); } protected: - ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun) + ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun) {} Obj& obj_; @@ -440,13 +473,13 @@ namespace Loki } template - inline ObjScopeGuardImpl0 MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj) + inline ObjScopeGuardImpl0 MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj) { return ObjScopeGuardImpl0::MakeObjGuard(obj,memFun); } template - inline ObjScopeGuardImpl0 MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj) + inline ObjScopeGuardImpl0 MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj) { return ObjScopeGuardImpl0::MakeObjGuard(*obj,memFun); } @@ -477,20 +510,20 @@ namespace Loki return ObjScopeGuardImpl1(obj, memFun, p1); } - ~ObjScopeGuardImpl1() throw() + ~ObjScopeGuardImpl1() throw() { SafeExecute(*this); } - void Execute() + void Execute() { (obj_.*memFun_)(p1_); } protected: - ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1) + ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1) {} - + Obj& obj_; MemFun memFun_; const P1 p1_; @@ -503,13 +536,13 @@ namespace Loki } template - inline ObjScopeGuardImpl1 MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) + inline ObjScopeGuardImpl1 MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) { return ObjScopeGuardImpl1::MakeObjGuard(obj,memFun,p1); } template - inline ObjScopeGuardImpl1 MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) + inline ObjScopeGuardImpl1 MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) { return ObjScopeGuardImpl1::MakeObjGuard(*obj,memFun,p1); } @@ -540,18 +573,18 @@ namespace Loki return ObjScopeGuardImpl2(obj, memFun, p1, p2); } - ~ObjScopeGuardImpl2() throw() + ~ObjScopeGuardImpl2() throw() { SafeExecute(*this); } - void Execute() + void Execute() { (obj_.*memFun_)(p1_, p2_); } protected: - ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) + ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {} Obj& obj_; @@ -567,13 +600,13 @@ namespace Loki } template - inline ObjScopeGuardImpl2 MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2) + inline ObjScopeGuardImpl2 MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2) { return ObjScopeGuardImpl2::MakeObjGuard(obj,memFun,p1,p2); } template - inline ObjScopeGuardImpl2 MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2) + inline ObjScopeGuardImpl2 MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2) { return ObjScopeGuardImpl2::MakeObjGuard(*obj,memFun,p1,p2); } @@ -605,12 +638,12 @@ namespace Loki return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >( obj, memFun, p1, p2, p3 ); } - ~ObjScopeGuardImpl3() throw() + ~ObjScopeGuardImpl3() throw() { SafeExecute( *this ); } - void Execute() + void Execute() { ( obj_.*memFun_ )( p1_, p2_, p3_ ); }