// // file: scopeguard.h // Used with permission from // 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(bool active) throw() : dismissed_(!active) { } void Dismiss() const throw() { dismissed_ = true; } }; typedef const ScopeGuardImplBase& ScopeGuard; template class ScopeGuardImpl0 : public ScopeGuardImplBase { public: static ScopeGuardImpl0 MakeGuard(bool active, F fun) { return ScopeGuardImpl0(active, fun); } ~ScopeGuardImpl0() throw() { SafeExecute(*this); } void Execute() { fun_(); } protected: ScopeGuardImpl0(bool active, F fun) : ScopeGuardImplBase(active), fun_(fun) { } F fun_; }; template inline ScopeGuardImpl0 MakeGuard(F fun) { return ScopeGuardImpl0::MakeGuard(true, fun); } template inline ScopeGuardImpl0 MakeGuardIF(bool active, F fun) { return ScopeGuardImpl0::MakeGuard(active, fun); } template class ScopeGuardImpl1 : public ScopeGuardImplBase { public: static ScopeGuardImpl1 MakeGuard(bool active, F fun, P1 p1) { return ScopeGuardImpl1(active, fun, p1); } ~ScopeGuardImpl1() throw() { SafeExecute(*this); } void Execute() { fun_(p1_); } protected: ScopeGuardImpl1(bool active, F fun, P1 p1) : ScopeGuardImplBase(active), fun_(fun), p1_(p1) { } F fun_; const P1 p1_; }; template inline ScopeGuardImpl1 MakeGuard(F fun, P1 p1) { return ScopeGuardImpl1::MakeGuard(true, fun, p1); } template inline ScopeGuardImpl1 MakeGuardIF(bool active, F fun, P1 p1) { return ScopeGuardImpl1::MakeGuard(active, fun, p1); } template class ScopeGuardImpl2: public ScopeGuardImplBase { public: static ScopeGuardImpl2 MakeGuard(bool active, F fun, P1 p1, P2 p2) { return ScopeGuardImpl2(active, fun, p1, p2); } ~ScopeGuardImpl2() throw() { SafeExecute(*this); } void Execute() { fun_(p1_, p2_); } protected: ScopeGuardImpl2(bool active, F fun, P1 p1, P2 p2) : ScopeGuardImplBase(active), 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(true, fun, p1, p2); } template inline ScopeGuardImpl2 MakeGuardIF(bool active, F fun, P1 p1, P2 p2) { return ScopeGuardImpl2::MakeGuard(active, fun, p1, p2); } template class ScopeGuardImpl3 : public ScopeGuardImplBase { public: static ScopeGuardImpl3 MakeGuard(bool active, F fun, P1 p1, P2 p2, P3 p3) { return ScopeGuardImpl3(active, fun, p1, p2, p3); } ~ScopeGuardImpl3() throw() { SafeExecute(*this); } void Execute() { fun_(p1_, p2_, p3_); } protected: ScopeGuardImpl3(bool active, F fun, P1 p1, P2 p2, P3 p3) : ScopeGuardImplBase(active), 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(true, fun, p1, p2, p3); } template inline ScopeGuardImpl3 MakeGuardIF(bool active, F fun, P1 p1, P2 p2, P3 p3) { return ScopeGuardImpl3::MakeGuard(active, fun, p1, p2, p3); } //************************************************************ template class ObjScopeGuardImpl0 : public ScopeGuardImplBase { public: static ObjScopeGuardImpl0 MakeObjGuard(bool active, Obj& obj, MemFun memFun) { return ObjScopeGuardImpl0(active, obj, memFun); } ~ObjScopeGuardImpl0() throw() { SafeExecute(*this); } void Execute() { (obj_.*memFun_)(); } protected: ObjScopeGuardImpl0(bool active, Obj& obj, MemFun memFun) : ScopeGuardImplBase(active), obj_(obj), memFun_(memFun) {} Obj& obj_; MemFun memFun_; }; template inline ObjScopeGuardImpl0 MakeObjGuard(Obj& obj, MemFun memFun) { return ObjScopeGuardImpl0::MakeObjGuard(true, obj, memFun); } template inline ObjScopeGuardImpl0 MakeObjGuardIF(bool active, Obj& obj, MemFun memFun) { return ObjScopeGuardImpl0::MakeObjGuard(active, obj, memFun); } template class ObjScopeGuardImpl1 : public ScopeGuardImplBase { public: static ObjScopeGuardImpl1 MakeObjGuard(bool active, Obj& obj, MemFun memFun, P1 p1) { return ObjScopeGuardImpl1(active, obj, memFun, p1); } ~ObjScopeGuardImpl1() throw() { SafeExecute(*this); } void Execute() { (obj_.*memFun_)(p1_); } protected: ObjScopeGuardImpl1(bool active, Obj& obj, MemFun memFun, P1 p1) : ScopeGuardImplBase(active), 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(true, obj, memFun, p1); } template inline ObjScopeGuardImpl1 MakeObjGuardIF(bool active, Obj& obj, MemFun memFun, P1 p1) { return ObjScopeGuardImpl1::MakeObjGuard(active, obj, memFun, p1); } template class ObjScopeGuardImpl2 : public ScopeGuardImplBase { public: static ObjScopeGuardImpl2 MakeObjGuard(bool active, Obj& obj, MemFun memFun, P1 p1, P2 p2) { return ObjScopeGuardImpl2(active, obj, memFun, p1, p2); } ~ObjScopeGuardImpl2() throw() { SafeExecute(*this); } void Execute() { (obj_.*memFun_)(p1_, p2_); } protected: ObjScopeGuardImpl2(bool active, Obj& obj, MemFun memFun, P1 p1, P2 p2) : ScopeGuardImplBase(active), 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(true, obj, memFun, p1, p2); } template inline ObjScopeGuardImpl2 MakeObjGuardIF(bool active, Obj& obj, MemFun memFun, P1 p1, P2 p2) { return ObjScopeGuardImpl2::MakeObjGuard(active, 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 #define ON_BLOCK_EXIT_IF ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeGuardIF #define ON_BLOCK_EXIT_OBJ_IF ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuardIF #endif //SCOPEGUARD_H_