scope_exit.hpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. // Copyright Alexander Nasonov 2006-2009
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef FILE_boost_scope_exit_hpp_INCLUDED
  7. #define FILE_boost_scope_exit_hpp_INCLUDED
  8. #include <boost/config.hpp>
  9. #include <boost/detail/workaround.hpp>
  10. #include <boost/preprocessor/cat.hpp>
  11. #include <boost/preprocessor/facilities/empty.hpp>
  12. #include <boost/preprocessor/punctuation/comma_if.hpp>
  13. #include <boost/preprocessor/seq/cat.hpp>
  14. #include <boost/preprocessor/seq/for_each_i.hpp>
  15. #include <boost/preprocessor/tuple/elem.hpp>
  16. #include <boost/typeof/typeof.hpp>
  17. #if defined(__GNUC__) && !defined(BOOST_INTEL)
  18. # define BOOST_SCOPE_EXIT_AUX_GCC (__GNUC__ * 100 + __GNUC_MINOR__)
  19. #else
  20. # define BOOST_SCOPE_EXIT_AUX_GCC 0
  21. #endif
  22. #if BOOST_WORKAROUND(BOOST_SCOPE_EXIT_AUX_GCC, BOOST_TESTED_AT(413))
  23. #define BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
  24. #endif
  25. // Steven Watanabe's trick
  26. namespace boost { namespace scope_exit { namespace aux {
  27. template<int> struct declare;
  28. typedef void* declared;
  29. struct undeclared { declared dummy[2]; };
  30. template<>
  31. struct declare<sizeof(undeclared)>
  32. {
  33. template<int>
  34. struct apply
  35. {
  36. declared value;
  37. friend void operator>(bool, const apply&) {}
  38. };
  39. };
  40. template<>
  41. struct declare<sizeof(declared)>
  42. {
  43. static const int apply = 0;
  44. };
  45. } } }
  46. extern boost::scope_exit::aux::undeclared boost_scope_exit_args; // undefined
  47. namespace boost { namespace scope_exit { namespace aux {
  48. typedef void (*ref_tag)(int&);
  49. typedef void (*val_tag)(int );
  50. template<class T, class Tag> struct member;
  51. template<class T>
  52. struct member<T,ref_tag>
  53. {
  54. T& value;
  55. #ifndef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
  56. member(T& ref) : value(ref) {}
  57. #endif
  58. };
  59. template<class T>
  60. struct member<T,val_tag>
  61. {
  62. T value;
  63. #ifndef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
  64. member(T& val) : value(val) {}
  65. #endif
  66. };
  67. template<class T> inline T& deref(T* p, ref_tag) { return *p; }
  68. template<class T> inline T& deref(T& r, val_tag) { return r; }
  69. template<class T>
  70. struct wrapper
  71. {
  72. typedef T type;
  73. };
  74. template<class T> wrapper<T> wrap(T&);
  75. } } }
  76. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  77. BOOST_TYPEOF_REGISTER_TEMPLATE(boost::scope_exit::aux::wrapper, 1)
  78. #define BOOST_SCOPE_EXIT_AUX_GUARD(id) BOOST_PP_CAT(boost_se_guard_, id)
  79. #define BOOST_SCOPE_EXIT_AUX_GUARD_T(id) BOOST_PP_CAT(boost_se_guard_t_, id)
  80. #define BOOST_SCOPE_EXIT_AUX_PARAMS(id) BOOST_PP_CAT(boost_se_params_, id)
  81. #define BOOST_SCOPE_EXIT_AUX_PARAMS_T(id) BOOST_PP_CAT(boost_se_params_t_, id)
  82. #define BOOST_SCOPE_EXIT_AUX_TAG(id, i) \
  83. BOOST_PP_SEQ_CAT( (boost_se_tag_)(i)(_)(id) )
  84. #define BOOST_SCOPE_EXIT_AUX_PARAM(id, i, var) \
  85. BOOST_PP_SEQ_CAT( (boost_se_param_)(i)(_)(id) )
  86. #define BOOST_SCOPE_EXIT_AUX_PARAM_T(id, i, var) \
  87. BOOST_PP_SEQ_CAT( (boost_se_param_t_)(i)(_)(id) )
  88. #define BOOST_SCOPE_EXIT_AUX_CAPTURE_T(id, i, var) \
  89. BOOST_PP_SEQ_CAT( (boost_se_capture_t_)(i)(_)(id) )
  90. #define BOOST_SCOPE_EXIT_AUX_WRAPPED(id, i) \
  91. BOOST_PP_SEQ_CAT( (boost_se_wrapped_t_)(i)(_)(id) )
  92. #define BOOST_SCOPE_EXIT_AUX_DEREF(id, i, var) \
  93. boost::scope_exit::aux::deref(var, (BOOST_SCOPE_EXIT_AUX_TAG(id,i))0)
  94. #define BOOST_SCOPE_EXIT_AUX_MEMBER(r, id, i, var) \
  95. boost::scope_exit::aux::member< \
  96. BOOST_SCOPE_EXIT_AUX_PARAM_T(id,i,var), \
  97. BOOST_SCOPE_EXIT_AUX_TAG(id,i) \
  98. > BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var);
  99. // idty is (id,typename) or (id,BOOST_PP_EMPTY())
  100. #define BOOST_SCOPE_EXIT_AUX_ARG_DECL(r, idty, i, var) \
  101. BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2,1,idty) \
  102. BOOST_SCOPE_EXIT_AUX_PARAMS_T(BOOST_PP_TUPLE_ELEM(2,0,idty)):: \
  103. BOOST_SCOPE_EXIT_AUX_PARAM_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var) var
  104. #define BOOST_SCOPE_EXIT_AUX_ARG(r, id, i, var) BOOST_PP_COMMA_IF(i) \
  105. boost_se_params_->BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var).value
  106. #define BOOST_SCOPE_EXIT_AUX_TAG_DECL(r, id, i, var) \
  107. typedef void (*BOOST_SCOPE_EXIT_AUX_TAG(id,i))(int var);
  108. #ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
  109. #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq)
  110. #define BOOST_SCOPE_EXIT_AUX_PARAM_INIT(r, id, i, var) \
  111. BOOST_PP_COMMA_IF(i) { BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var) }
  112. #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq) \
  113. = { BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_INIT, id, seq) };
  114. #else
  115. #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG(r, id, i, var) BOOST_PP_COMMA_IF(i) \
  116. BOOST_SCOPE_EXIT_AUX_PARAM_T(id,i,var) & BOOST_PP_CAT(a,i)
  117. #define BOOST_SCOPE_EXIT_AUX_MEMBER_INIT(r, id, i, var) BOOST_PP_COMMA_IF(i) \
  118. BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var) ( BOOST_PP_CAT(a,i) )
  119. #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq) \
  120. BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)( \
  121. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CTOR_ARG, id, seq ) ) \
  122. : BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER_INIT, id, seq) {}
  123. #define BOOST_SCOPE_EXIT_AUX_PARAM_INIT(r, id, i, var) \
  124. BOOST_PP_COMMA_IF(i) BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var)
  125. #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq) \
  126. ( BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_INIT, id, seq) );
  127. #endif
  128. #if defined(BOOST_TYPEOF_EMULATION)
  129. #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
  130. struct BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i) \
  131. : BOOST_TYPEOF(boost::scope_exit::aux::wrap( \
  132. BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var))) \
  133. {}; typedef BOOST_PP_TUPLE_ELEM(2,1,idty) \
  134. BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i)::type \
  135. BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
  136. #elif defined(BOOST_INTEL)
  137. #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
  138. typedef BOOST_TYPEOF_KEYWORD( \
  139. BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var)) \
  140. BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
  141. #else
  142. #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
  143. typedef BOOST_TYPEOF(boost::scope_exit::aux::wrap( \
  144. BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var))) \
  145. BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i); \
  146. typedef BOOST_PP_TUPLE_ELEM(2,1,idty) \
  147. BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i)::type \
  148. BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
  149. #endif
  150. #define BOOST_SCOPE_EXIT_AUX_PARAM_DECL(r, idty, i, var) \
  151. typedef BOOST_SCOPE_EXIT_AUX_CAPTURE_T( \
  152. BOOST_PP_TUPLE_ELEM(2,0,idty), i, var) \
  153. BOOST_SCOPE_EXIT_AUX_PARAM_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
  154. #define BOOST_SCOPE_EXIT_AUX_IMPL(id, seq, ty) \
  155. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_TAG_DECL, id, seq) \
  156. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL, (id,ty), seq) \
  157. struct BOOST_SCOPE_EXIT_AUX_PARAMS_T(id) { \
  158. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_DECL, (id,ty), seq)\
  159. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER, id, seq) \
  160. BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq) \
  161. } BOOST_SCOPE_EXIT_AUX_PARAMS(id) BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq)\
  162. boost::scope_exit::aux::declare<sizeof(boost_scope_exit_args)> \
  163. ::apply<0> boost_scope_exit_args; \
  164. boost_scope_exit_args.value = &BOOST_SCOPE_EXIT_AUX_PARAMS(id); \
  165. struct BOOST_SCOPE_EXIT_AUX_GUARD_T(id) { \
  166. BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)* boost_se_params_; \
  167. BOOST_SCOPE_EXIT_AUX_GUARD_T(id) (void* boost_se_params) \
  168. : boost_se_params_( \
  169. (BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)*)boost_se_params) \
  170. {} \
  171. ~BOOST_SCOPE_EXIT_AUX_GUARD_T(id)() { boost_se_body( \
  172. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_ARG, id, seq) ); } \
  173. static void boost_se_body(BOOST_PP_SEQ_FOR_EACH_I( \
  174. BOOST_SCOPE_EXIT_AUX_ARG_DECL, (id,ty), seq) )
  175. #if defined(BOOST_MSVC)
  176. #define BOOST_SCOPE_EXIT_END } BOOST_SCOPE_EXIT_AUX_GUARD(__COUNTER__) ( \
  177. boost_scope_exit_args.value);
  178. #define BOOST_SCOPE_EXIT(seq) \
  179. BOOST_SCOPE_EXIT_AUX_IMPL(__COUNTER__, seq, BOOST_PP_EMPTY())
  180. #else
  181. #define BOOST_SCOPE_EXIT_END } BOOST_SCOPE_EXIT_AUX_GUARD(__LINE__) ( \
  182. boost_scope_exit_args.value);
  183. #define BOOST_SCOPE_EXIT(seq) \
  184. BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, BOOST_PP_EMPTY())
  185. #endif
  186. #ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
  187. #define BOOST_SCOPE_EXIT_TPL(seq) \
  188. BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, typename)
  189. #else
  190. #define BOOST_SCOPE_EXIT_TPL(seq) BOOST_SCOPE_EXIT(seq)
  191. #endif
  192. #endif // #ifndef FILE_boost_scope_exit_hpp_INCLUDED