// No Copyright here // Based on Nov 2000 CUJ Experts articole by // Andrei Alexandrescu and Petru Marginean #ifndef SCOPEGUARD_H_ #define SCOPEGUARD_H_ template class RefHolder { T& ref_; public: RefHolder(T& ref) : ref_(ref) {} operator T& () const { return ref_; } }; template inline RefHolder ByRef(T& t) { return RefHolder(t); } class ScopeGuardImplBase { ScopeGuardImplBase& operator =(const ScopeGuardImplBase&); protected: ~ScopeGuardImplBase() { } ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() : dismissed_(other.dismissed_) { other.Dismiss(); } template static void SafeExecute(J& j) throw() { if (!j.dismissed_) try { j.Execute(); } catch(...) { } } mutable bool dismissed_; public: ScopeGuardImplBase() throw() : dismissed_(false) { } void Dismiss() const throw() { dismissed_ = true; } }; typedef const ScopeGuardImplBase& ScopeGuard; template class ScopeGuardImpl0 : public ScopeGuardImplBase { public: static ScopeGuardImpl0 MakeGuard(F fun) { return ScopeGuardImpl0(fun); } ~ScopeGuardImpl0() throw() { SafeExecute(*this); } void Execute() { fun_(); } protected: ScopeGuardImpl0(F fun) : fun_(fun) { } F fun_; }; template inline ScopeGuardImpl0 MakeGuard(F fun) { return ScopeGuardImpl0::MakeGuard(fun); } template class ScopeGuardImpl1 : public ScopeGuardImplBase { public: static ScopeGuardImpl1 MakeGuard(F fun, P1 p1) { return ScopeGuardImpl1(fun, p1); } ~ScopeGuardImpl1() throw() { SafeExecute(*this); } void Execute() { fun_(p1_); } protected: ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) { } F fun_; const P1 p1_; }; template inline ScopeGuardImpl1 MakeGuard(F fun, P1 p1) { return ScopeGuardImpl1::MakeGuard(fun, p1); } template class ScopeGuardImpl2: public ScopeGuardImplBase { public: static ScopeGuardImpl2 MakeGuard(F fun, P1 p1, P2 p2) { return ScopeGuardImpl2(fun, p1, p2); } ~ScopeGuardImpl2() throw() { SafeExecute(*this); } void Execute() { fun_(p1_, p2_); } protected: ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) { } F fun_; const P1 p1_; const P2 p2_; }; template inline ScopeGuardImpl2 MakeGuard(F fun, P1 p1, P2 p2) { return ScopeGuardImpl2::MakeGuard(fun, p1, p2); } template class ScopeGuardImpl3 : public ScopeGuardImplBase { public: static ScopeGuardImpl3 MakeGuard(F fun, P1 p1, P2 p2, P3 p3) { return ScopeGuardImpl3(fun, p1, p2, p3); } ~ScopeGuardImpl3() throw() { SafeExecute(*this); } void Execute() { fun_(p1_, p2_, p3_); } protected: ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) { } F fun_; const P1 p1_; const P2 p2_; const P3 p3_; }; template inline ScopeGuardImpl3 MakeGuard(F fun, P1 p1, P2 p2, P3 p3) { return ScopeGuardImpl3::MakeGuard(fun, p1, p2, p3); } //************************************************************ template class ObjScopeGuardImpl0 : public ScopeGuardImplBase { public: static ObjScopeGuardImpl0 MakeObjGuard(Obj& obj, MemFun memFun) { return ObjScopeGuardImpl0(obj, memFun); } ~ObjScopeGuardImpl0() throw() { SafeExecute(*this); } void Execute() { (obj_.*memFun_)(); } protected: ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun) {} Obj& obj_; MemFun memFun_; }; template inline ObjScopeGuardImpl0 MakeObjGuard(Obj& obj, MemFun memFun) { return ObjScopeGuardImpl0::MakeObjGuard(obj, memFun); } template class ObjScopeGuardImpl1 : public ScopeGuardImplBase { public: static ObjScopeGuardImpl1 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) { return ObjScopeGuardImpl1(obj, memFun, p1); } ~ObjScopeGuardImpl1() throw() { SafeExecute(*this); } void Execute() { (obj_.*memFun_)(p1_); } protected: ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1) {} Obj& obj_; MemFun memFun_; const P1 p1_; }; template inline ObjScopeGuardImpl1 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) { return ObjScopeGuardImpl1::MakeObjGuard(obj, memFun, p1); } template class ObjScopeGuardImpl2 : public ScopeGuardImplBase { public: static ObjScopeGuardImpl2 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) { return ObjScopeGuardImpl2(obj, memFun, p1, p2); } ~ObjScopeGuardImpl2() throw() { SafeExecute(*this); } void Execute() { (obj_.*memFun_)(p1_, p2_); } protected: ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {} Obj& obj_; MemFun memFun_; const P1 p1_; const P2 p2_; }; template inline ObjScopeGuardImpl2 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) { return ObjScopeGuardImpl2::MakeObjGuard(obj, memFun, p1, p2); } // Rollback helper functions template void deletePtr(const T* p) { delete p; } template void deleteArray(T* p) { delete[] p; } #define CONCATENATE_DIRECT(s1, s2) s1##s2 #define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2) #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__) #define ON_BLOCK_EXIT ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard #define ON_BLOCK_EXIT_OBJ ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard #endif //SCOPEGUARD_H_