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
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00047 #ifndef BLOCXX_SCOPE_GUARD_HPP_INCLUDE_GUARD_
00048 #define BLOCXX_SCOPE_GUARD_HPP_INCLUDE_GUARD_
00049
00050 #include "blocxx/BLOCXX_config.h"
00051 #include "blocxx/RefToValue.hpp"
00052
00053 namespace BLOCXX_NAMESPACE
00054 {
00055
00056 class ScopeGuardImplBase
00057 {
00058 ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
00059
00060 protected:
00061
00062 ~ScopeGuardImplBase()
00063 {}
00064
00065 ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
00066 : m_dismissed(other.m_dismissed)
00067 {
00068 other.dismiss();
00069 }
00070
00071 template <typename J>
00072 static void safeExecute(J& j) throw()
00073 {
00074 if (!j.m_dismissed)
00075 try
00076 {
00077 j.execute();
00078 }
00079 catch(...)
00080 {}
00081 }
00082
00083 mutable bool m_dismissed;
00084
00085 public:
00086 ScopeGuardImplBase() throw() : m_dismissed(false)
00087 {}
00088
00089 void dismiss() const throw()
00090 {
00091 m_dismissed = true;
00092 }
00093 };
00094
00105
00106 typedef const ScopeGuardImplBase& ScopeGuard;
00107
00108 template <typename F>
00109 class ScopeGuardImpl0 : public ScopeGuardImplBase
00110 {
00111 public:
00112 static ScopeGuardImpl0<F> makeGuard(F fun)
00113 {
00114 return ScopeGuardImpl0<F>(fun);
00115 }
00116
00117 ~ScopeGuardImpl0() throw()
00118 {
00119 safeExecute(*this);
00120 }
00121
00122 void execute()
00123 {
00124 m_fun();
00125 }
00126
00127 protected:
00128 ScopeGuardImpl0(F fun) : m_fun(fun)
00129 {}
00130
00131 F m_fun;
00132 };
00133
00134 template <typename F>
00135 inline ScopeGuardImpl0<F> makeGuard(F fun)
00136 {
00137 return ScopeGuardImpl0<F>::makeGuard(fun);
00138 }
00139
00140 template <typename F, typename P1>
00141 class ScopeGuardImpl1 : public ScopeGuardImplBase
00142 {
00143 public:
00144 static ScopeGuardImpl1<F, P1> makeGuard(F fun, P1 p1)
00145 {
00146 return ScopeGuardImpl1<F, P1>(fun, p1);
00147 }
00148
00149 ~ScopeGuardImpl1() throw()
00150 {
00151 safeExecute(*this);
00152 }
00153
00154 void execute()
00155 {
00156 m_fun(m_p1);
00157 }
00158
00159 protected:
00160 ScopeGuardImpl1(F fun, P1 p1) : m_fun(fun), m_p1(p1)
00161 {}
00162
00163 F m_fun;
00164 const P1 m_p1;
00165 };
00166
00167 template <typename F, typename P1>
00168 inline ScopeGuardImpl1<F, P1> makeGuard(F fun, P1 p1)
00169 {
00170 return ScopeGuardImpl1<F, P1>::makeGuard(fun, p1);
00171 }
00172
00173 template <typename F, typename P1, typename P2>
00174 class ScopeGuardImpl2: public ScopeGuardImplBase
00175 {
00176 public:
00177 static ScopeGuardImpl2<F, P1, P2> makeGuard(F fun, P1 p1, P2 p2)
00178 {
00179 return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
00180 }
00181
00182 ~ScopeGuardImpl2() throw()
00183 {
00184 safeExecute(*this);
00185 }
00186
00187 void execute()
00188 {
00189 m_fun(m_p1, m_p2);
00190 }
00191
00192 protected:
00193 ScopeGuardImpl2(F fun, P1 p1, P2 p2) : m_fun(fun), m_p1(p1), m_p2(p2)
00194 {}
00195
00196 F m_fun;
00197 const P1 m_p1;
00198 const P2 m_p2;
00199 };
00200
00201 template <typename F, typename P1, typename P2>
00202 inline ScopeGuardImpl2<F, P1, P2> makeGuard(F fun, P1 p1, P2 p2)
00203 {
00204 return ScopeGuardImpl2<F, P1, P2>::makeGuard(fun, p1, p2);
00205 }
00206
00207 template <typename F, typename P1, typename P2, typename P3>
00208 class ScopeGuardImpl3 : public ScopeGuardImplBase
00209 {
00210 public:
00211 static ScopeGuardImpl3<F, P1, P2, P3> makeGuard(F fun, P1 p1, P2 p2, P3 p3)
00212 {
00213 return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
00214 }
00215
00216 ~ScopeGuardImpl3() throw()
00217 {
00218 safeExecute(*this);
00219 }
00220
00221 void execute()
00222 {
00223 m_fun(m_p1, m_p2, m_p3);
00224 }
00225
00226 protected:
00227 ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : m_fun(fun), m_p1(p1), m_p2(p2), m_p3(p3)
00228 {}
00229
00230 F m_fun;
00231 const P1 m_p1;
00232 const P2 m_p2;
00233 const P3 m_p3;
00234 };
00235
00236 template <typename F, typename P1, typename P2, typename P3>
00237 inline ScopeGuardImpl3<F, P1, P2, P3> makeGuard(F fun, P1 p1, P2 p2, P3 p3)
00238 {
00239 return ScopeGuardImpl3<F, P1, P2, P3>::makeGuard(fun, p1, p2, p3);
00240 }
00241
00242
00243
00244 template <class Obj, typename MemFun>
00245 class ObjScopeGuardImpl0 : public ScopeGuardImplBase
00246 {
00247 public:
00248 static ObjScopeGuardImpl0<Obj, MemFun> makeObjGuard(Obj& obj, MemFun memFun)
00249 {
00250 return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
00251 }
00252
00253 ~ObjScopeGuardImpl0() throw()
00254 {
00255 safeExecute(*this);
00256 }
00257
00258 void execute()
00259 {
00260 (m_obj.*m_memFun)();
00261 }
00262
00263 protected:
00264 ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : m_obj(obj), m_memFun(memFun)
00265 {}
00266
00267 Obj& m_obj;
00268 MemFun m_memFun;
00269 };
00270
00271 template <class Obj, typename MemFun>
00272 inline ObjScopeGuardImpl0<Obj, MemFun> makeObjGuard(Obj& obj, MemFun memFun)
00273 {
00274 return ObjScopeGuardImpl0<Obj, MemFun>::makeObjGuard(obj, memFun);
00275 }
00276
00277 template <typename Ret, class Obj1, class Obj2>
00278 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> makeGuard(Ret(Obj2::*memFun)(), Obj1 &obj)
00279 {
00280 return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::makeObjGuard(obj,memFun);
00281 }
00282
00283 template <typename Ret, class Obj1, class Obj2>
00284 inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> makeGuard(Ret(Obj2::*memFun)(), Obj1 *obj)
00285 {
00286 return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::makeObjGuard(*obj,memFun);
00287 }
00288
00289 template <class Obj, typename MemFun, typename P1>
00290 class ObjScopeGuardImpl1 : public ScopeGuardImplBase
00291 {
00292 public:
00293 static ObjScopeGuardImpl1<Obj, MemFun, P1> makeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00294 {
00295 return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
00296 }
00297
00298 ~ObjScopeGuardImpl1() throw()
00299 {
00300 safeExecute(*this);
00301 }
00302
00303 void execute()
00304 {
00305 (m_obj.*m_memFun)(m_p1);
00306 }
00307
00308 protected:
00309 ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : m_obj(obj), m_memFun(memFun), m_p1(p1)
00310 {}
00311
00312 Obj& m_obj;
00313 MemFun m_memFun;
00314 const P1 m_p1;
00315 };
00316
00317 template <class Obj, typename MemFun, typename P1>
00318 inline ObjScopeGuardImpl1<Obj, MemFun, P1> makeObjGuard(Obj& obj, MemFun memFun, P1 p1)
00319 {
00320 return ObjScopeGuardImpl1<Obj, MemFun, P1>::makeObjGuard(obj, memFun, p1);
00321 }
00322
00323 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
00324 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> makeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1)
00325 {
00326 return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::makeObjGuard(obj,memFun,p1);
00327 }
00328
00329 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
00330 inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> makeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1)
00331 {
00332 return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::makeObjGuard(*obj,memFun,p1);
00333 }
00334
00335 template <class Obj, typename MemFun, typename P1, typename P2>
00336 class ObjScopeGuardImpl2 : public ScopeGuardImplBase
00337 {
00338 public:
00339 static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00340 {
00341 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
00342 }
00343
00344 ~ObjScopeGuardImpl2() throw()
00345 {
00346 safeExecute(*this);
00347 }
00348
00349 void execute()
00350 {
00351 (m_obj.*m_memFun)(m_p1, m_p2);
00352 }
00353
00354 protected:
00355 ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : m_obj(obj), m_memFun(memFun), m_p1(p1), m_p2(p2)
00356 {}
00357
00358 Obj& m_obj;
00359 MemFun m_memFun;
00360 const P1 m_p1;
00361 const P2 m_p2;
00362 };
00363
00364 template <class Obj, typename MemFun, typename P1, typename P2>
00365 inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> makeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
00366 {
00367 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::makeObjGuard(obj, memFun, p1, p2);
00368 }
00369
00370 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
00371 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> makeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2)
00372 {
00373 return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::makeObjGuard(obj,memFun,p1,p2);
00374 }
00375
00376 template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
00377 inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> makeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2)
00378 {
00379 return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::makeObjGuard(*obj,memFun,p1,p2);
00380 }
00381
00382 }
00383
00384 #define BLOCXX_CONCATENATE_DIRECT(s1, s2) s1##s2
00385 #define BLOCXX_CONCATENATE(s1, s2) BLOCXX_CONCATENATE_DIRECT(s1, s2)
00386 #define BLOCXX_ANONYMOUS_VARIABLE(str) BLOCXX_CONCATENATE(str, __LINE__)
00387
00388 #define BLOCXX_ON_BLOCK_EXIT blocxx::ScopeGuard BLOCXX_ANONYMOUS_VARIABLE(scopeGuard) = blocxx::makeGuard
00389 #define BLOCXX_ON_BLOCK_EXIT_OBJ blocxx::ScopeGuard BLOCXX_ANONYMOUS_VARIABLE(scopeGuard) = blocxx::makeObjGuard
00390
00391 #endif
00392