00001 #ifndef SCOPEGUARD_H_
00002 #define SCOPEGUARD_H_
00003
00005 template <class T>
00006 class RefHolder
00007 {
00008 T& ref_;
00009 public:
00010 RefHolder(T& ref) : ref_(ref) {}
00011 operator T& () const
00012 {
00013 return ref_;
00014 }
00015 private:
00016
00017 RefHolder& operator=(const RefHolder&);
00018 };
00019
00020 template <class T>
00021 inline RefHolder<T> ByRef(T& t)
00022 {
00023 return RefHolder<T>(t);
00024 }
00025
00027 class ScopeGuardImplBase
00028 {
00029 ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
00030 protected:
00031 ~ScopeGuardImplBase()
00032 {
00033 }
00034 public:
00035 ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
00036 : dismissed_(other.dismissed_)
00037 {
00038 other.Dismiss();
00039 }
00040 protected:
00041 template <typename J>
00042 static void SafeExecute(J& j) throw()
00043 {
00044 if (!j.dismissed_)
00045 try
00046 {
00047 j.Execute();
00048 }
00049 catch(...)
00050 {
00051 }
00052 }
00053
00054 mutable bool dismissed_;
00055 public:
00056 ScopeGuardImplBase() throw() : dismissed_(false)
00057 {
00058 }
00059 void Dismiss() const throw()
00060 {
00061 dismissed_ = true;
00062 }
00063 };
00064
00065 typedef const ScopeGuardImplBase& ScopeGuard;
00066
00068 template <typename F>
00069 class ScopeGuardImpl0 : public ScopeGuardImplBase
00070 {
00071 public:
00072 static ScopeGuardImpl0<F> MakeGuard(F fun)
00073 {
00074 return ScopeGuardImpl0<F>(fun);
00075 }
00076 ~ScopeGuardImpl0() throw()
00077 {
00078 SafeExecute(*this);
00079 }
00080 void Execute()
00081 {
00082 fun_();
00083 }
00084 protected:
00085 ScopeGuardImpl0(F fun) : fun_(fun)
00086 {
00087 }
00088 F fun_;
00089 };
00090
00092 template <typename F>
00093 inline ScopeGuardImpl0<F> MakeGuard(F fun)
00094 {
00095 return ScopeGuardImpl0<F>::MakeGuard(fun);
00096 }
00097
00099 template <typename F, typename P1>
00100 class ScopeGuardImpl1 : public ScopeGuardImplBase
00101 {
00102 public:
00103 static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
00104 {
00105 return ScopeGuardImpl1<F, P1>(fun, p1);
00106 }
00107 ~ScopeGuardImpl1() throw()
00108 {
00109 SafeExecute(*this);
00110 }
00111 void Execute()
00112 {
00113 fun_(p1_);
00114 }
00115 protected:
00116 ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
00117 {
00118 }
00119 F fun_;
00120 const P1 p1_;
00121 };
00122
00124 template <typename F, typename P1>
00125 inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
00126 {
00127 return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
00128 }
00129
00131 template <typename F, typename P1, typename P2>
00132 class ScopeGuardImpl2: public ScopeGuardImplBase
00133 {
00134 public:
00135 static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
00136 {
00137 return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
00138 }
00139 ~ScopeGuardImpl2() throw()
00140 {
00141 SafeExecute(*this);
00142 }
00143 void Execute()
00144 {
00145 fun_(p1_, p2_);
00146 }
00147 protected:
00148 ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2)
00149 {
00150 }
00151 F fun_;
00152 const P1 p1_;
00153 const P2 p2_;
00154 };
00155
00157 template <typename F, typename P1, typename P2>
00158 inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
00159 {
00160 return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
00161 }
00162
00164 template <typename F, typename P1, typename P2, typename P3>
00165 class ScopeGuardImpl3 : public ScopeGuardImplBase
00166 {
00167 public:
00168 static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
00169 {
00170 return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
00171 }
00172 ~ScopeGuardImpl3() throw()
00173 {
00174 SafeExecute(*this);
00175 }
00176 void Execute()
00177 {
00178 fun_(p1_, p2_, p3_);
00179 }
00180 protected:
00181 ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3)
00182 {
00183 }
00184 F fun_;
00185 const P1 p1_;
00186 const P2 p2_;
00187 const P3 p3_;
00188 };
00189
00190 template <typename F, typename P1, typename P2, typename P3>
00191 inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
00192 {
00193 return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
00194 }
00195
00196
00197
00199 template <class Obj, typename MemFun>
00200 class ObjScopeGuardImpl0 : public ScopeGuardImplBase
00201 {
00202 public:
00203 static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
00204 {
00205 return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
00206 }
00207 ~ObjScopeGuardImpl0() throw()
00208 {
00209 SafeExecute(*this);
00210 }
00211 void Execute()
00212 {
00213 (obj_.*memFun_)();
00214 }
00215 protected:
00216 ObjScopeGuardImpl0(Obj& obj, MemFun memFun)
00217 : obj_(obj), memFun_(memFun) {}
00218 Obj& obj_;
00219 MemFun memFun_;
00220 };
00221
00222 template <class Obj, typename MemFun>
00223 inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
00224 {
00225 return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
00226 }
00227
00229 template <class Obj, typename MemFun, typename P1>
00230 class ObjScopeGuardImpl1 : public ScopeGuardImplBase
00231 {
00232 public:
00233 static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00234 {
00235 return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
00236 }
00237 ~ObjScopeGuardImpl1() throw()
00238 {
00239 SafeExecute(*this);
00240 }
00241 void Execute()
00242 {
00243 (obj_.*memFun_)(p1_);
00244 }
00245 protected:
00246 ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1)
00247 : obj_(obj), memFun_(memFun), p1_(p1) {}
00248 Obj& obj_;
00249 MemFun memFun_;
00250 const P1 p1_;
00251 };
00252
00253 template <class Obj, typename MemFun, typename P1>
00254 inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00255 {
00256 return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
00257 }
00258
00260 template <class Obj, typename MemFun, typename P1, typename P2>
00261 class ObjScopeGuardImpl2 : public ScopeGuardImplBase
00262 {
00263 public:
00264 static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00265 {
00266 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
00267 }
00268 ~ObjScopeGuardImpl2() throw()
00269 {
00270 SafeExecute(*this);
00271 }
00272 void Execute()
00273 {
00274 (obj_.*memFun_)(p1_, p2_);
00275 }
00276 protected:
00277 ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00278 : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {}
00279 Obj& obj_;
00280 MemFun memFun_;
00281 const P1 p1_;
00282 const P2 p2_;
00283 };
00284
00285 template <class Obj, typename MemFun, typename P1, typename P2>
00286 inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00287 {
00288 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
00289 }
00290
00291 #define CONCATENATE_DIRECT(s1, s2) s1##s2
00292 #define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2)
00293 #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
00294
00295 #ifdef __GNUC__
00296 # define UNUSED_VARIABLE __attribute__((unused))
00297 #else
00298 # define UNUSED_VARIABLE
00299 #endif
00300
00301 #define ON_BLOCK_EXIT ScopeGuard UNUSED_VARIABLE ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard
00302 #define ON_BLOCK_EXIT_OBJ ScopeGuard UNUSED_VARIABLE ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard
00303
00304 #endif //SCOPEGUARD_H_
00305
00306