/src/mongo/util/scopeguard.h
https://github.com/matulef/mongo · C Header · 432 lines · 294 code · 79 blank · 59 comment · 1 complexity · dc97ce2559772726fc2fa7cd26785d06 MD5 · raw file
- ////////////////////////////////////////////////////////////////////////////////
- // 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__)
- #ifdef __GNUC__
- #define ON_BLOCK_EXIT ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) __attribute__ ((unused)) = MakeGuard
- #define ON_BLOCK_EXIT_OBJ ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) __attribute__ ((unused)) = MakeObjGuard
- #else
- #define ON_BLOCK_EXIT ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard
- #define ON_BLOCK_EXIT_OBJ ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard
- #endif
- #endif //LOKI_SCOPEGUARD_H_