00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #ifndef BLOCXX_SCOPEGUARD_HPP_
00044 #define BLOCXX_SCOPEGUARD_HPP_
00045
00046 namespace BLOCXX_NAMESPACE
00047 {
00048
00050 template <class T>
00051 class RefHolder
00052 {
00053 T& ref_;
00054 public:
00055 RefHolder(T& ref) : ref_(ref) {}
00056 operator T& () const
00057 {
00058 return ref_;
00059 }
00060 private:
00061
00062 RefHolder& operator=(const RefHolder&);
00063 };
00064
00065 template <class T>
00066 inline RefHolder<T>
00067 byRef(T& t)
00068 {
00069 return RefHolder<T>(t);
00070 }
00071
00073 class ScopeGuardImplBase
00074 {
00075 ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
00076 protected:
00077 ~ScopeGuardImplBase()
00078 {
00079 }
00080 ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
00081 : m_dismissed(other.m_dismissed)
00082 {
00083 other.dismiss();
00084 }
00085 template <typename J>
00086 static void safeExecute(J& j) throw()
00087 {
00088 if (!j.m_dismissed)
00089 try
00090 {
00091 j.execute();
00092 }
00093 catch(...)
00094 {
00095 }
00096 }
00097
00098 mutable bool m_dismissed;
00099 public:
00100 ScopeGuardImplBase() throw() : m_dismissed(false)
00101 {
00102 }
00103 void dismiss() const throw()
00104 {
00105 m_dismissed = true;
00106 }
00107 };
00108
00109 typedef const ScopeGuardImplBase& ScopeGuard;
00110
00112 template <typename F>
00113 class ScopeGuardImpl0 : public ScopeGuardImplBase
00114 {
00115 public:
00116 static ScopeGuardImpl0<F> makeGuard(F fun)
00117 {
00118 return ScopeGuardImpl0<F>(fun);
00119 }
00120 ~ScopeGuardImpl0() throw()
00121 {
00122 safeExecute(*this);
00123 }
00124 void execute()
00125 {
00126 fun_();
00127 }
00128 protected:
00129 ScopeGuardImpl0(F fun) : fun_(fun)
00130 {
00131 }
00132 F fun_;
00133 };
00134
00135 template <typename F>
00136 inline ScopeGuardImpl0<F>
00137 makeGuard(F fun)
00138 {
00139 return ScopeGuardImpl0<F>::makeGuard(fun);
00140 }
00141
00143 template <typename F, typename P1>
00144 class ScopeGuardImpl1 : public ScopeGuardImplBase
00145 {
00146 public:
00147 static ScopeGuardImpl1<F, P1> makeGuard(F fun, P1 p1)
00148 {
00149 return ScopeGuardImpl1<F, P1>(fun, p1);
00150 }
00151 ~ScopeGuardImpl1() throw()
00152 {
00153 safeExecute(*this);
00154 }
00155 void execute()
00156 {
00157 fun_(m_p1);
00158 }
00159 protected:
00160 ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), m_p1(p1)
00161 {
00162 }
00163 F fun_;
00164 const P1 m_p1;
00165 };
00166
00167 template <typename F, typename P1>
00168 inline ScopeGuardImpl1<F, P1>
00169 makeGuard(F fun, P1 p1)
00170 {
00171 return ScopeGuardImpl1<F, P1>::makeGuard(fun, p1);
00172 }
00173
00175 template <typename F, typename P1, typename P2>
00176 class ScopeGuardImpl2: public ScopeGuardImplBase
00177 {
00178 public:
00179 static ScopeGuardImpl2<F, P1, P2> makeGuard(F fun, P1 p1, P2 p2)
00180 {
00181 return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
00182 }
00183 ~ScopeGuardImpl2() throw()
00184 {
00185 safeExecute(*this);
00186 }
00187 void execute()
00188 {
00189 fun_(m_p1, m_p2);
00190 }
00191 protected:
00192 ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), m_p1(p1), m_p2(p2)
00193 {
00194 }
00195 F fun_;
00196 const P1 m_p1;
00197 const P2 m_p2;
00198 };
00199
00200 template <typename F, typename P1, typename P2>
00201 inline ScopeGuardImpl2<F, P1, P2>
00202 makeGuard(F fun, P1 p1, P2 p2)
00203 {
00204 return ScopeGuardImpl2<F, P1, P2>::makeGuard(fun, p1, p2);
00205 }
00206
00208 template <typename F, typename P1, typename P2, typename P3>
00209 class ScopeGuardImpl3 : public ScopeGuardImplBase
00210 {
00211 public:
00212 static ScopeGuardImpl3<F, P1, P2, P3> makeGuard(F fun, P1 p1, P2 p2, P3 p3)
00213 {
00214 return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
00215 }
00216 ~ScopeGuardImpl3() throw()
00217 {
00218 safeExecute(*this);
00219 }
00220 void execute()
00221 {
00222 fun_(m_p1, m_p2, m_p3);
00223 }
00224 protected:
00225 ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), m_p1(p1), m_p2(p2), m_p3(p3)
00226 {
00227 }
00228 F fun_;
00229 const P1 m_p1;
00230 const P2 m_p2;
00231 const P3 m_p3;
00232 };
00233
00234 template <typename F, typename P1, typename P2, typename P3>
00235 inline ScopeGuardImpl3<F, P1, P2, P3>
00236 makeGuard(F fun, P1 p1, P2 p2, P3 p3)
00237 {
00238 return ScopeGuardImpl3<F, P1, P2, P3>::makeGuard(fun, p1, p2, p3);
00239 }
00240
00242 template <class Obj, typename MemFun>
00243 class ObjScopeGuardImpl0 : public ScopeGuardImplBase
00244 {
00245 public:
00246 static ObjScopeGuardImpl0<Obj, MemFun> makeObjGuard(Obj& obj, MemFun memFun)
00247 {
00248 return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
00249 }
00250 ~ObjScopeGuardImpl0() throw()
00251 {
00252 safeExecute(*this);
00253 }
00254 void execute()
00255 {
00256 (m_obj.*m_memFun)();
00257 }
00258 protected:
00259 ObjScopeGuardImpl0(Obj& obj, MemFun memFun)
00260 : m_obj(obj), m_memFun(memFun) {}
00261 Obj& m_obj;
00262 MemFun m_memFun;
00263 };
00264
00265 template <class Obj, typename MemFun>
00266 inline ObjScopeGuardImpl0<Obj, MemFun>
00267 makeObjGuard(Obj& obj, MemFun memFun)
00268 {
00269 return ObjScopeGuardImpl0<Obj, MemFun>::makeObjGuard(obj, memFun);
00270 }
00271
00273 template <class Obj, typename MemFun, typename P1>
00274 class ObjScopeGuardImpl1 : public ScopeGuardImplBase
00275 {
00276 public:
00277 static ObjScopeGuardImpl1<Obj, MemFun, P1> makeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00278 {
00279 return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
00280 }
00281 ~ObjScopeGuardImpl1() throw()
00282 {
00283 safeExecute(*this);
00284 }
00285 void execute()
00286 {
00287 (m_obj.*m_memFun)(m_p1);
00288 }
00289 protected:
00290 ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1)
00291 : m_obj(obj), m_memFun(memFun), m_p1(p1) {}
00292 Obj& m_obj;
00293 MemFun m_memFun;
00294 const P1 m_p1;
00295 };
00296
00297 template <class Obj, typename MemFun, typename P1>
00298 inline ObjScopeGuardImpl1<Obj, MemFun, P1>
00299 makeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00300 {
00301 return ObjScopeGuardImpl1<Obj, MemFun, P1>::makeObjGuard(obj, memFun, p1);
00302 }
00303
00305 template <class Obj, typename MemFun, typename P1, typename P2>
00306 class ObjScopeGuardImpl2 : public ScopeGuardImplBase
00307 {
00308 public:
00309 static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00310 {
00311 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
00312 }
00313 ~ObjScopeGuardImpl2() throw()
00314 {
00315 safeExecute(*this);
00316 }
00317 void execute()
00318 {
00319 (m_obj.*m_memFun)(m_p1, m_p2);
00320 }
00321 protected:
00322 ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00323 : m_obj(obj), m_memFun(memFun), m_p1(p1), m_p2(p2) {}
00324 Obj& m_obj;
00325 MemFun m_memFun;
00326 const P1 m_p1;
00327 const P2 m_p2;
00328 };
00329
00330 template <class Obj, typename MemFun, typename P1, typename P2>
00331 inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2>
00332 makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00333 {
00334 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::makeObjGuard(obj, memFun, p1, p2);
00335 }
00336
00337 #define CONCATENATE_DIRECT(s1, s2) s1##s2
00338 #define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2)
00339 #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
00340
00341 #define ON_BLOCK_EXIT ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = makeGuard
00342 #define ON_BLOCK_EXIT_OBJ ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = makeObjGuard
00343
00344 }
00345
00346 #endif //SCOPEGUARD_H_