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