Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
6.0 KiB

  1. // No Copyright here
  2. // Based on Nov 2000 CUJ Experts articole by
  3. // Andrei Alexandrescu and Petru Marginean
  4. #ifndef SCOPEGUARD_H_
  5. #define SCOPEGUARD_H_
  6. template <class T>
  7. class RefHolder
  8. {
  9. T& ref_;
  10. public:
  11. RefHolder(T& ref) : ref_(ref) {}
  12. operator T& () const
  13. {
  14. return ref_;
  15. }
  16. };
  17. template <class T>
  18. inline RefHolder<T> ByRef(T& t)
  19. {
  20. return RefHolder<T>(t);
  21. }
  22. class ScopeGuardImplBase
  23. {
  24. ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
  25. protected:
  26. ~ScopeGuardImplBase()
  27. {
  28. }
  29. ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
  30. : dismissed_(other.dismissed_)
  31. {
  32. other.Dismiss();
  33. }
  34. template <typename J>
  35. static void SafeExecute(J& j) throw()
  36. {
  37. if (!j.dismissed_)
  38. try
  39. {
  40. j.Execute();
  41. }
  42. catch(...)
  43. {
  44. }
  45. }
  46. mutable bool dismissed_;
  47. public:
  48. ScopeGuardImplBase() throw() : dismissed_(false)
  49. {
  50. }
  51. void Dismiss() const throw()
  52. {
  53. dismissed_ = true;
  54. }
  55. };
  56. typedef const ScopeGuardImplBase& ScopeGuard;
  57. template <typename F>
  58. class ScopeGuardImpl0 : public ScopeGuardImplBase
  59. {
  60. public:
  61. static ScopeGuardImpl0<F> MakeGuard(F fun)
  62. {
  63. return ScopeGuardImpl0<F>(fun);
  64. }
  65. ~ScopeGuardImpl0() throw()
  66. {
  67. SafeExecute(*this);
  68. }
  69. void Execute()
  70. {
  71. fun_();
  72. }
  73. protected:
  74. ScopeGuardImpl0(F fun) : fun_(fun)
  75. {
  76. }
  77. F fun_;
  78. };
  79. template <typename F>
  80. inline ScopeGuardImpl0<F> MakeGuard(F fun)
  81. {
  82. return ScopeGuardImpl0<F>::MakeGuard(fun);
  83. }
  84. template <typename F, typename P1>
  85. class ScopeGuardImpl1 : public ScopeGuardImplBase
  86. {
  87. public:
  88. static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
  89. {
  90. return ScopeGuardImpl1<F, P1>(fun, p1);
  91. }
  92. ~ScopeGuardImpl1() throw()
  93. {
  94. SafeExecute(*this);
  95. }
  96. void Execute()
  97. {
  98. fun_(p1_);
  99. }
  100. protected:
  101. ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
  102. {
  103. }
  104. F fun_;
  105. const P1 p1_;
  106. };
  107. template <typename F, typename P1>
  108. inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
  109. {
  110. return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
  111. }
  112. template <typename F, typename P1, typename P2>
  113. class ScopeGuardImpl2: public ScopeGuardImplBase
  114. {
  115. public:
  116. static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
  117. {
  118. return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
  119. }
  120. ~ScopeGuardImpl2() throw()
  121. {
  122. SafeExecute(*this);
  123. }
  124. void Execute()
  125. {
  126. fun_(p1_, p2_);
  127. }
  128. protected:
  129. ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2)
  130. {
  131. }
  132. F fun_;
  133. const P1 p1_;
  134. const P2 p2_;
  135. };
  136. template <typename F, typename P1, typename P2>
  137. inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
  138. {
  139. return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
  140. }
  141. template <typename F, typename P1, typename P2, typename P3>
  142. class ScopeGuardImpl3 : public ScopeGuardImplBase
  143. {
  144. public:
  145. static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
  146. {
  147. return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
  148. }
  149. ~ScopeGuardImpl3() throw()
  150. {
  151. SafeExecute(*this);
  152. }
  153. void Execute()
  154. {
  155. fun_(p1_, p2_, p3_);
  156. }
  157. protected:
  158. ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3)
  159. {
  160. }
  161. F fun_;
  162. const P1 p1_;
  163. const P2 p2_;
  164. const P3 p3_;
  165. };
  166. template <typename F, typename P1, typename P2, typename P3>
  167. inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
  168. {
  169. return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
  170. }
  171. //************************************************************
  172. template <class Obj, typename MemFun>
  173. class ObjScopeGuardImpl0 : public ScopeGuardImplBase
  174. {
  175. public:
  176. static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
  177. {
  178. return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
  179. }
  180. ~ObjScopeGuardImpl0() throw()
  181. {
  182. SafeExecute(*this);
  183. }
  184. void Execute()
  185. {
  186. (obj_.*memFun_)();
  187. }
  188. protected:
  189. ObjScopeGuardImpl0(Obj& obj, MemFun memFun)
  190. : obj_(obj), memFun_(memFun) {}
  191. Obj& obj_;
  192. MemFun memFun_;
  193. };
  194. template <class Obj, typename MemFun>
  195. inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
  196. {
  197. return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
  198. }
  199. template <class Obj, typename MemFun, typename P1>
  200. class ObjScopeGuardImpl1 : public ScopeGuardImplBase
  201. {
  202. public:
  203. static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
  204. {
  205. return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
  206. }
  207. ~ObjScopeGuardImpl1() throw()
  208. {
  209. SafeExecute(*this);
  210. }
  211. void Execute()
  212. {
  213. (obj_.*memFun_)(p1_);
  214. }
  215. protected:
  216. ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1)
  217. : obj_(obj), memFun_(memFun), p1_(p1) {}
  218. Obj& obj_;
  219. MemFun memFun_;
  220. const P1 p1_;
  221. };
  222. template <class Obj, typename MemFun, typename P1>
  223. inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
  224. {
  225. return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
  226. }
  227. template <class Obj, typename MemFun, typename P1, typename P2>
  228. class ObjScopeGuardImpl2 : public ScopeGuardImplBase
  229. {
  230. public:
  231. static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
  232. {
  233. return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
  234. }
  235. ~ObjScopeGuardImpl2() throw()
  236. {
  237. SafeExecute(*this);
  238. }
  239. void Execute()
  240. {
  241. (obj_.*memFun_)(p1_, p2_);
  242. }
  243. protected:
  244. ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2)
  245. : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {}
  246. Obj& obj_;
  247. MemFun memFun_;
  248. const P1 p1_;
  249. const P2 p2_;
  250. };
  251. template <class Obj, typename MemFun, typename P1, typename P2>
  252. inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
  253. {
  254. return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
  255. }
  256. // Rollback helper functions
  257. template<typename T>
  258. void deletePtr(const T* p)
  259. {
  260. delete p;
  261. }
  262. template<typename T>
  263. void deleteArray(T* p)
  264. {
  265. delete[] p;
  266. }
  267. #define CONCATENATE_DIRECT(s1, s2) s1##s2
  268. #define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2)
  269. #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
  270. #define ON_BLOCK_EXIT ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard
  271. #define ON_BLOCK_EXIT_OBJ ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard
  272. #endif //SCOPEGUARD_H_