diff options
Diffstat (limited to 'src/mongo/util/scopeguard.h')
-rw-r--r-- | src/mongo/util/scopeguard.h | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/src/mongo/util/scopeguard.h b/src/mongo/util/scopeguard.h new file mode 100644 index 00000000000..b87a4b51871 --- /dev/null +++ b/src/mongo/util/scopeguard.h @@ -0,0 +1,427 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2000 Andrei Alexandrescu +// 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 notice appear in supporting documentation. +// 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_H_ +#define LOKI_SCOPEGUARD_H_ + +namespace mongo +{ + + //////////////////////////////////////////////////////////////////////////////// + /// \class RefToValue + /// + /// Transports a reference as a value + /// Serves to implement the Colvin/Gibbons trick for SmartPtr/ScopeGuard + //////////////////////////////////////////////////////////////////////////////// + + template <class T> + class RefToValue + { + public: + + RefToValue(T& ref) : ref_(ref) + {} + + RefToValue(const RefToValue& rhs) : ref_(rhs.ref_) + {} + + operator T& () const + { + return ref_; + } + + private: + // Disable - not implemented + RefToValue(); + RefToValue& operator=(const RefToValue&); + + T& ref_; + }; + + + //////////////////////////////////////////////////////////////////////////////// + /// RefToValue creator. + //////////////////////////////////////////////////////////////////////////////// + + template <class T> + inline RefToValue<T> ByRef(T& t) + { + return RefToValue<T>(t); + } + + + + + //////////////////////////////////////////// + /// ScopeGuard + /* + Trivial example for use: + + FILE* f = fopen("myfile.txt", "w+"); + if (!f) + return error; + ON_BLOCK_EXIT(fclose, f); + + + More complicated example: + + ScopeGuard guard = MakeGuard(my_rollback_func, myparam); + ... + if (successful) { + guard.Dismiss(); + return; + } + // guard is still active here and will fire at scope exit + ... + + + */ + + + class ScopeGuardImplBase + { + ScopeGuardImplBase& operator =(const ScopeGuardImplBase&); + + protected: + + ~ScopeGuardImplBase() + {} + + ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() + : dismissed_(other.dismissed_) + { + other.Dismiss(); + } + + template <typename J> + 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 typedef const ScopeGuardImplBase& ScopeGuard + /// + /// See Andrei's and Petru Marginean's CUJ article + /// http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm + /// + /// Changes to the original code by Joshua Lehrer: + /// http://www.lehrerfamily.com/scopeguard.html + //////////////////////////////////////////////////////////////// + + typedef const ScopeGuardImplBase& ScopeGuard; + + template <typename F> + class ScopeGuardImpl0 : public ScopeGuardImplBase + { + public: + static ScopeGuardImpl0<F> MakeGuard(F fun) + { + return ScopeGuardImpl0<F>(fun); + } + + ~ScopeGuardImpl0() throw() + { + SafeExecute(*this); + } + + void Execute() + { + fun_(); + } + + protected: + ScopeGuardImpl0(F fun) : fun_(fun) + {} + + F fun_; + }; + + template <typename F> + inline ScopeGuardImpl0<F> MakeGuard(F fun) + { + return ScopeGuardImpl0<F>::MakeGuard(fun); + } + + template <typename F, typename P1> + class ScopeGuardImpl1 : public ScopeGuardImplBase + { + public: + static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1) + { + return ScopeGuardImpl1<F, P1>(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 <typename F, typename P1> + inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1) + { + return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1); + } + + template <typename F, typename P1, typename P2> + class ScopeGuardImpl2: public ScopeGuardImplBase + { + public: + static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2) + { + return ScopeGuardImpl2<F, P1, P2>(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 <typename F, typename P1, typename P2> + inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2) + { + return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2); + } + + template <typename F, typename P1, typename P2, typename P3> + class ScopeGuardImpl3 : public ScopeGuardImplBase + { + public: + static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3) + { + return ScopeGuardImpl3<F, P1, P2, P3>(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 <typename F, typename P1, typename P2, typename P3> + inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3) + { + return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3); + } + + //************************************************************ + + template <class Obj, typename MemFun> + class ObjScopeGuardImpl0 : public ScopeGuardImplBase + { + public: + static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun) + { + return ObjScopeGuardImpl0<Obj, MemFun>(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 <class Obj, typename MemFun> + inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun) + { + return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun); + } + + template <typename Ret, class Obj1, class Obj2> + inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj) + { + return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(obj,memFun); + } + + template <typename Ret, class Obj1, class Obj2> + inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj) + { + return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(*obj,memFun); + } + + template <class Obj, typename MemFun, typename P1> + class ObjScopeGuardImpl1 : public ScopeGuardImplBase + { + public: + static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) + { + return ObjScopeGuardImpl1<Obj, MemFun, P1>(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 <class Obj, typename MemFun, typename P1> + inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) + { + return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1); + } + + template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b> + inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) + { + return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(obj,memFun,p1); + } + + template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b> + inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) + { + return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1); + } + + template <class Obj, typename MemFun, typename P1, typename P2> + class ObjScopeGuardImpl2 : public ScopeGuardImplBase + { + public: + static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) + { + return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(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 <class Obj, typename MemFun, typename P1, typename P2> + inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) + { + return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2); + } + + template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b> + inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2) + { + return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2); + } + + template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b> + inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2) + { + return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2); + } + +} // namespace Loki + +#define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2 +#define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2) +#define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__) + +#define ON_BLOCK_EXIT ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard +#define ON_BLOCK_EXIT_OBJ ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard + +#endif //LOKI_SCOPEGUARD_H_ |