/src/mongo/util/scopeguard.h

https://github.com/matulef/mongo · C Header · 432 lines · 294 code · 79 blank · 59 comment · 1 complexity · dc97ce2559772726fc2fa7cd26785d06 MD5 · raw file

  1. ////////////////////////////////////////////////////////////////////////////////
  2. // The Loki Library
  3. // Copyright (c) 2000 Andrei Alexandrescu
  4. // Copyright (c) 2000 Petru Marginean
  5. // Copyright (c) 2005 Joshua Lehrer
  6. //
  7. // Permission to use, copy, modify, distribute and sell this software for any
  8. // purpose is hereby granted without fee, provided that the above copyright
  9. // notice appear in all copies and that both that copyright notice and this
  10. // permission notice appear in supporting documentation.
  11. // The author makes no representations about the
  12. // suitability of this software for any purpose. It is provided "as is"
  13. // without express or implied warranty.
  14. ////////////////////////////////////////////////////////////////////////////////
  15. #ifndef LOKI_SCOPEGUARD_H_
  16. #define LOKI_SCOPEGUARD_H_
  17. namespace mongo
  18. {
  19. ////////////////////////////////////////////////////////////////////////////////
  20. /// \class RefToValue
  21. ///
  22. /// Transports a reference as a value
  23. /// Serves to implement the Colvin/Gibbons trick for SmartPtr/ScopeGuard
  24. ////////////////////////////////////////////////////////////////////////////////
  25. template <class T>
  26. class RefToValue
  27. {
  28. public:
  29. RefToValue(T& ref) : ref_(ref)
  30. {}
  31. RefToValue(const RefToValue& rhs) : ref_(rhs.ref_)
  32. {}
  33. operator T& () const
  34. {
  35. return ref_;
  36. }
  37. private:
  38. // Disable - not implemented
  39. RefToValue();
  40. RefToValue& operator=(const RefToValue&);
  41. T& ref_;
  42. };
  43. ////////////////////////////////////////////////////////////////////////////////
  44. /// RefToValue creator.
  45. ////////////////////////////////////////////////////////////////////////////////
  46. template <class T>
  47. inline RefToValue<T> ByRef(T& t)
  48. {
  49. return RefToValue<T>(t);
  50. }
  51. ////////////////////////////////////////////
  52. /// ScopeGuard
  53. /*
  54. Trivial example for use:
  55. FILE* f = fopen("myfile.txt", "w+");
  56. if (!f)
  57. return error;
  58. ON_BLOCK_EXIT(fclose, f);
  59. More complicated example:
  60. ScopeGuard guard = MakeGuard(my_rollback_func, myparam);
  61. ...
  62. if (successful) {
  63. guard.Dismiss();
  64. return;
  65. }
  66. // guard is still active here and will fire at scope exit
  67. ...
  68. */
  69. class ScopeGuardImplBase
  70. {
  71. ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
  72. protected:
  73. ~ScopeGuardImplBase()
  74. {}
  75. ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
  76. : dismissed_(other.dismissed_)
  77. {
  78. other.Dismiss();
  79. }
  80. template <typename J>
  81. static void SafeExecute(J& j) throw()
  82. {
  83. if (!j.dismissed_)
  84. try
  85. {
  86. j.Execute();
  87. }
  88. catch(...)
  89. {}
  90. }
  91. mutable bool dismissed_;
  92. public:
  93. ScopeGuardImplBase() throw() : dismissed_(false)
  94. {}
  95. void Dismiss() const throw()
  96. {
  97. dismissed_ = true;
  98. }
  99. };
  100. ////////////////////////////////////////////////////////////////
  101. ///
  102. /// \typedef typedef const ScopeGuardImplBase& ScopeGuard
  103. ///
  104. /// See Andrei's and Petru Marginean's CUJ article
  105. /// http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm
  106. ///
  107. /// Changes to the original code by Joshua Lehrer:
  108. /// http://www.lehrerfamily.com/scopeguard.html
  109. ////////////////////////////////////////////////////////////////
  110. typedef const ScopeGuardImplBase& ScopeGuard;
  111. template <typename F>
  112. class ScopeGuardImpl0 : public ScopeGuardImplBase
  113. {
  114. public:
  115. static ScopeGuardImpl0<F> MakeGuard(F fun)
  116. {
  117. return ScopeGuardImpl0<F>(fun);
  118. }
  119. ~ScopeGuardImpl0() throw()
  120. {
  121. SafeExecute(*this);
  122. }
  123. void Execute()
  124. {
  125. fun_();
  126. }
  127. protected:
  128. ScopeGuardImpl0(F fun) : fun_(fun)
  129. {}
  130. F fun_;
  131. };
  132. template <typename F>
  133. inline ScopeGuardImpl0<F> MakeGuard(F fun)
  134. {
  135. return ScopeGuardImpl0<F>::MakeGuard(fun);
  136. }
  137. template <typename F, typename P1>
  138. class ScopeGuardImpl1 : public ScopeGuardImplBase
  139. {
  140. public:
  141. static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
  142. {
  143. return ScopeGuardImpl1<F, P1>(fun, p1);
  144. }
  145. ~ScopeGuardImpl1() throw()
  146. {
  147. SafeExecute(*this);
  148. }
  149. void Execute()
  150. {
  151. fun_(p1_);
  152. }
  153. protected:
  154. ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
  155. {}
  156. F fun_;
  157. const P1 p1_;
  158. };
  159. template <typename F, typename P1>
  160. inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
  161. {
  162. return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
  163. }
  164. template <typename F, typename P1, typename P2>
  165. class ScopeGuardImpl2: public ScopeGuardImplBase
  166. {
  167. public:
  168. static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
  169. {
  170. return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
  171. }
  172. ~ScopeGuardImpl2() throw()
  173. {
  174. SafeExecute(*this);
  175. }
  176. void Execute()
  177. {
  178. fun_(p1_, p2_);
  179. }
  180. protected:
  181. ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2)
  182. {}
  183. F fun_;
  184. const P1 p1_;
  185. const P2 p2_;
  186. };
  187. template <typename F, typename P1, typename P2>
  188. inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
  189. {
  190. return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
  191. }
  192. template <typename F, typename P1, typename P2, typename P3>
  193. class ScopeGuardImpl3 : public ScopeGuardImplBase
  194. {
  195. public:
  196. static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
  197. {
  198. return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
  199. }
  200. ~ScopeGuardImpl3() throw()
  201. {
  202. SafeExecute(*this);
  203. }
  204. void Execute()
  205. {
  206. fun_(p1_, p2_, p3_);
  207. }
  208. protected:
  209. ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3)
  210. {}
  211. F fun_;
  212. const P1 p1_;
  213. const P2 p2_;
  214. const P3 p3_;
  215. };
  216. template <typename F, typename P1, typename P2, typename P3>
  217. inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
  218. {
  219. return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
  220. }
  221. //************************************************************
  222. template <class Obj, typename MemFun>
  223. class ObjScopeGuardImpl0 : public ScopeGuardImplBase
  224. {
  225. public:
  226. static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
  227. {
  228. return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
  229. }
  230. ~ObjScopeGuardImpl0() throw()
  231. {
  232. SafeExecute(*this);
  233. }
  234. void Execute()
  235. {
  236. (obj_.*memFun_)();
  237. }
  238. protected:
  239. ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun)
  240. {}
  241. Obj& obj_;
  242. MemFun memFun_;
  243. };
  244. template <class Obj, typename MemFun>
  245. inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
  246. {
  247. return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
  248. }
  249. template <typename Ret, class Obj1, class Obj2>
  250. inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj)
  251. {
  252. return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(obj,memFun);
  253. }
  254. template <typename Ret, class Obj1, class Obj2>
  255. inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj)
  256. {
  257. return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(*obj,memFun);
  258. }
  259. template <class Obj, typename MemFun, typename P1>
  260. class ObjScopeGuardImpl1 : public ScopeGuardImplBase
  261. {
  262. public:
  263. static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
  264. {
  265. return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
  266. }
  267. ~ObjScopeGuardImpl1() throw()
  268. {
  269. SafeExecute(*this);
  270. }
  271. void Execute()
  272. {
  273. (obj_.*memFun_)(p1_);
  274. }
  275. protected:
  276. ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1)
  277. {}
  278. Obj& obj_;
  279. MemFun memFun_;
  280. const P1 p1_;
  281. };
  282. template <class Obj, typename MemFun, typename P1>
  283. inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
  284. {
  285. return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
  286. }
  287. template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
  288. inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1)
  289. {
  290. return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(obj,memFun,p1);
  291. }
  292. template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
  293. inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1)
  294. {
  295. return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1);
  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 memFun, 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) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2)
  315. {}
  316. Obj& obj_;
  317. MemFun memFun_;
  318. const P1 p1_;
  319. const P2 p2_;
  320. };
  321. template <class Obj, typename MemFun, typename P1, typename P2>
  322. inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
  323. {
  324. return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
  325. }
  326. template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
  327. inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2)
  328. {
  329. return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2);
  330. }
  331. template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
  332. inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2)
  333. {
  334. return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2);
  335. }
  336. } // namespace Loki
  337. #define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2
  338. #define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2)
  339. #define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__)
  340. #ifdef __GNUC__
  341. #define ON_BLOCK_EXIT ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) __attribute__ ((unused)) = MakeGuard
  342. #define ON_BLOCK_EXIT_OBJ ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) __attribute__ ((unused)) = MakeObjGuard
  343. #else
  344. #define ON_BLOCK_EXIT ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard
  345. #define ON_BLOCK_EXIT_OBJ ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard
  346. #endif
  347. #endif //LOKI_SCOPEGUARD_H_