| OLD | NEW |
| (Empty) |
| 1 // | |
| 2 // Author: Andrei Alexandrescu - andrei@metalanguage.com | |
| 3 // | |
| 4 // The code below is based on the following article published in | |
| 5 // C/C++ Users Journal by Andrei Alexandrescu: | |
| 6 // | |
| 7 // http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm | |
| 8 // | |
| 9 // ScopeGuard is useful when you need to perform automatic cleanup of resources. | |
| 10 // This idiom is important when you want to assemble an operation out of several | |
| 11 // atomic operations, each of which could fail. | |
| 12 // | |
| 13 // Usage | |
| 14 // ------ | |
| 15 // Scope guard for objects: | |
| 16 // void f(T& t) { | |
| 17 // std::vector<T> v; | |
| 18 // v.push_back(t); | |
| 19 // ScopeGuard guard = MakeObjGuard(v, &std::vector<T>v::pop_back); | |
| 20 // if (!Commit()) { | |
| 21 // return; | |
| 22 // } | |
| 23 // guard.Dismiss(); // removes the t from the vector in the case Commit fa
ils | |
| 24 // } | |
| 25 // | |
| 26 // Scope guard for functions: | |
| 27 // void open(); | |
| 28 // void close(int i); | |
| 29 // void g(int i) { | |
| 30 // open(); | |
| 31 // ScopeGuard guard = MakeGuard(close, 0); | |
| 32 // if (!read()) { | |
| 33 // return; | |
| 34 // } | |
| 35 // if (!write()) { | |
| 36 // return; | |
| 37 // } | |
| 38 // } | |
| 39 // | |
| 40 // Using the macros: | |
| 41 // void g(int i) { | |
| 42 // open(); | |
| 43 // ON_SCOPE_EXIT(close, 0); | |
| 44 // if (!read()) { | |
| 45 // return; | |
| 46 // } | |
| 47 // if (!write()) { | |
| 48 // return; | |
| 49 // } | |
| 50 // } | |
| 51 | |
| 52 // TODO(omaha): provide support to run with or without exceptions enabled. | |
| 53 // For now it assumes that the code is not throwing exceptions. | |
| 54 #ifndef SCOPEGUARD_H_ | |
| 55 #define SCOPEGUARD_H_ | |
| 56 | |
| 57 namespace omaha { | |
| 58 | |
| 59 template <class T> | |
| 60 class RefHolder | |
| 61 { | |
| 62 T& ref_; | |
| 63 public: | |
| 64 RefHolder(T& ref) : ref_(ref) {} | |
| 65 operator T& () const | |
| 66 { | |
| 67 return ref_; | |
| 68 } | |
| 69 private: | |
| 70 // Disable assignment - not implemented | |
| 71 RefHolder& operator=(const RefHolder&); | |
| 72 }; | |
| 73 | |
| 74 template <class T> | |
| 75 inline RefHolder<T> ByRef(T& t) | |
| 76 { | |
| 77 return RefHolder<T>(t); | |
| 78 } | |
| 79 | |
| 80 class ScopeGuardImplBase | |
| 81 { | |
| 82 ScopeGuardImplBase& operator =(const ScopeGuardImplBase&); | |
| 83 protected: | |
| 84 ~ScopeGuardImplBase() | |
| 85 { | |
| 86 } | |
| 87 ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() | |
| 88 : dismissed_(other.dismissed_) | |
| 89 { | |
| 90 other.Dismiss(); | |
| 91 } | |
| 92 template <typename J> | |
| 93 static void SafeExecute(J& j) throw() | |
| 94 { | |
| 95 if (!j.dismissed_) | |
| 96 { | |
| 97 // TODO(omaha): assume this does not throw | |
| 98 j.Execute(); | |
| 99 } | |
| 100 } | |
| 101 | |
| 102 mutable bool dismissed_; | |
| 103 public: | |
| 104 ScopeGuardImplBase() throw() : dismissed_(false) | |
| 105 { | |
| 106 } | |
| 107 void Dismiss() const throw() | |
| 108 { | |
| 109 dismissed_ = true; | |
| 110 } | |
| 111 }; | |
| 112 | |
| 113 typedef const ScopeGuardImplBase& ScopeGuard; | |
| 114 | |
| 115 template <typename F> | |
| 116 class ScopeGuardImpl0 : public ScopeGuardImplBase | |
| 117 { | |
| 118 public: | |
| 119 static ScopeGuardImpl0<F> MakeGuard(F fun) | |
| 120 { | |
| 121 return ScopeGuardImpl0<F>(fun); | |
| 122 } | |
| 123 ~ScopeGuardImpl0() throw() | |
| 124 { | |
| 125 SafeExecute(*this); | |
| 126 } | |
| 127 void Execute() | |
| 128 { | |
| 129 fun_(); | |
| 130 } | |
| 131 protected: | |
| 132 ScopeGuardImpl0(F fun) : fun_(fun) | |
| 133 { | |
| 134 } | |
| 135 F fun_; | |
| 136 }; | |
| 137 | |
| 138 template <typename F> | |
| 139 inline ScopeGuardImpl0<F> MakeGuard(F fun) | |
| 140 { | |
| 141 return ScopeGuardImpl0<F>::MakeGuard(fun); | |
| 142 } | |
| 143 | |
| 144 template <typename F, typename P1> | |
| 145 class ScopeGuardImpl1 : public ScopeGuardImplBase | |
| 146 { | |
| 147 public: | |
| 148 static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1) | |
| 149 { | |
| 150 return ScopeGuardImpl1<F, P1>(fun, p1); | |
| 151 } | |
| 152 ~ScopeGuardImpl1() throw() | |
| 153 { | |
| 154 SafeExecute(*this); | |
| 155 } | |
| 156 void Execute() | |
| 157 { | |
| 158 fun_(p1_); | |
| 159 } | |
| 160 protected: | |
| 161 ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) | |
| 162 { | |
| 163 } | |
| 164 F fun_; | |
| 165 const P1 p1_; | |
| 166 }; | |
| 167 | |
| 168 template <typename F, typename P1> | |
| 169 inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1) | |
| 170 { | |
| 171 return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1); | |
| 172 } | |
| 173 | |
| 174 template <typename F, typename P1, typename P2> | |
| 175 class ScopeGuardImpl2: public ScopeGuardImplBase | |
| 176 { | |
| 177 public: | |
| 178 static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2) | |
| 179 { | |
| 180 return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2); | |
| 181 } | |
| 182 ~ScopeGuardImpl2() throw() | |
| 183 { | |
| 184 SafeExecute(*this); | |
| 185 } | |
| 186 void Execute() | |
| 187 { | |
| 188 fun_(p1_, p2_); | |
| 189 } | |
| 190 protected: | |
| 191 ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) | |
| 192 { | |
| 193 } | |
| 194 F fun_; | |
| 195 const P1 p1_; | |
| 196 const P2 p2_; | |
| 197 }; | |
| 198 | |
| 199 template <typename F, typename P1, typename P2> | |
| 200 inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2) | |
| 201 { | |
| 202 return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2); | |
| 203 } | |
| 204 | |
| 205 template <typename F, typename P1, typename P2, typename P3> | |
| 206 class ScopeGuardImpl3 : public ScopeGuardImplBase | |
| 207 { | |
| 208 public: | |
| 209 static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3) | |
| 210 { | |
| 211 return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3); | |
| 212 } | |
| 213 ~ScopeGuardImpl3() throw() | |
| 214 { | |
| 215 SafeExecute(*this); | |
| 216 } | |
| 217 void Execute() | |
| 218 { | |
| 219 fun_(p1_, p2_, p3_); | |
| 220 } | |
| 221 protected: | |
| 222 ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_
(p3) | |
| 223 { | |
| 224 } | |
| 225 F fun_; | |
| 226 const P1 p1_; | |
| 227 const P2 p2_; | |
| 228 const P3 p3_; | |
| 229 }; | |
| 230 | |
| 231 template <typename F, typename P1, typename P2, typename P3> | |
| 232 inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3) | |
| 233 { | |
| 234 return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3); | |
| 235 } | |
| 236 | |
| 237 | |
| 238 template <class Obj, typename MemFun> | |
| 239 class ObjScopeGuardImpl0 : public ScopeGuardImplBase | |
| 240 { | |
| 241 public: | |
| 242 static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun) | |
| 243 { | |
| 244 return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun); | |
| 245 } | |
| 246 ~ObjScopeGuardImpl0() throw() | |
| 247 { | |
| 248 SafeExecute(*this); | |
| 249 } | |
| 250 void Execute() | |
| 251 { | |
| 252 (obj_.*memFun_)(); | |
| 253 } | |
| 254 protected: | |
| 255 ObjScopeGuardImpl0(Obj& obj, MemFun memFun) | |
| 256 : obj_(obj), memFun_(memFun) {} | |
| 257 Obj& obj_; | |
| 258 MemFun memFun_; | |
| 259 }; | |
| 260 | |
| 261 template <class Obj, typename MemFun> | |
| 262 inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun) | |
| 263 { | |
| 264 return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun); | |
| 265 } | |
| 266 | |
| 267 template <class Obj, typename MemFun, typename P1> | |
| 268 class ObjScopeGuardImpl1 : public ScopeGuardImplBase | |
| 269 { | |
| 270 public: | |
| 271 static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFu
n, P1 p1) | |
| 272 { | |
| 273 return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1); | |
| 274 } | |
| 275 ~ObjScopeGuardImpl1() throw() | |
| 276 { | |
| 277 SafeExecute(*this); | |
| 278 } | |
| 279 void Execute() | |
| 280 { | |
| 281 (obj_.*memFun_)(p1_); | |
| 282 } | |
| 283 protected: | |
| 284 ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) | |
| 285 : obj_(obj), memFun_(memFun), p1_(p1) {} | |
| 286 Obj& obj_; | |
| 287 MemFun memFun_; | |
| 288 const P1 p1_; | |
| 289 }; | |
| 290 | |
| 291 template <class Obj, typename MemFun, typename P1> | |
| 292 inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun,
P1 p1) | |
| 293 { | |
| 294 return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1); | |
| 295 } | |
| 296 | |
| 297 template <class Obj, typename MemFun, typename P1, typename P2> | |
| 298 class ObjScopeGuardImpl2 : public ScopeGuardImplBase | |
| 299 { | |
| 300 public: | |
| 301 static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun m
emFun, P1 p1, P2 p2) | |
| 302 { | |
| 303 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2); | |
| 304 } | |
| 305 ~ObjScopeGuardImpl2() throw() | |
| 306 { | |
| 307 SafeExecute(*this); | |
| 308 } | |
| 309 void Execute() | |
| 310 { | |
| 311 (obj_.*memFun_)(p1_, p2_); | |
| 312 } | |
| 313 protected: | |
| 314 ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) | |
| 315 : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {} | |
| 316 Obj& obj_; | |
| 317 MemFun memFun_; | |
| 318 const P1 p1_; | |
| 319 const P2 p2_; | |
| 320 }; | |
| 321 | |
| 322 template <class Obj, typename MemFun, typename P1, typename P2> | |
| 323 inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun mem
Fun, P1 p1, P2 p2) | |
| 324 { | |
| 325 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1,
p2); | |
| 326 } | |
| 327 | |
| 328 template <class Obj, typename MemFun, typename P1, typename P2, typename P3> | |
| 329 class ObjScopeGuardImpl3 : public ScopeGuardImplBase | |
| 330 { | |
| 331 public: | |
| 332 static ObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3> MakeObjGuard(Obj& obj, MemF
un memFun, P1 p1, P2 p2, P3 p3) | |
| 333 { | |
| 334 return ObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>(obj, memFun, p1, p2, p3); | |
| 335 } | |
| 336 ~ObjScopeGuardImpl3() throw() | |
| 337 { | |
| 338 SafeExecute(*this); | |
| 339 } | |
| 340 void Execute() | |
| 341 { | |
| 342 (obj_.*memFun_)(p1_, p2_, p3_); | |
| 343 } | |
| 344 protected: | |
| 345 ObjScopeGuardImpl3(Obj& obj, MemFun memFun, P1 p1, P2 p2, P3 p3) | |
| 346 : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2), p3_(p3) {} | |
| 347 Obj& obj_; | |
| 348 MemFun memFun_; | |
| 349 const P1 p1_; | |
| 350 const P2 p2_; | |
| 351 const P3 p3_; | |
| 352 }; | |
| 353 | |
| 354 template <class Obj, typename MemFun, typename P1, typename P2, typename P3> | |
| 355 inline ObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3> MakeObjGuard(Obj& obj, MemFun
memFun, P1 p1, P2 p2, P3 p3) | |
| 356 { | |
| 357 return ObjScopeGuardImpl3<Obj, MemFun, P1, P2, P3>::MakeObjGuard(obj, memFun,
p1, p2, p3); | |
| 358 } | |
| 359 | |
| 360 #define CONCATENATE_DIRECT(s1, s2) s1##s2 | |
| 361 #define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2) | |
| 362 #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__) | |
| 363 | |
| 364 #define ON_SCOPE_EXIT ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard | |
| 365 #define ON_SCOPE_EXIT_OBJ ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGua
rd | |
| 366 | |
| 367 } // namespace omaha | |
| 368 | |
| 369 #endif //SCOPEGUARD_H_ | |
| OLD | NEW |