scope_exit.hpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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 with a modification suggested by Kim Barrett
  26. namespace boost { namespace scope_exit { namespace aux {
  27. // Type of a local boost_scope_exit_args variable.
  28. // First use in a local scope will declare the boost_scope_exit_args
  29. // variable, subsequent uses will be resolved as two comparisons
  30. // (cmp1 with 0 and cmp2 with boost_scope_exit_args).
  31. template<int Dummy = 0>
  32. struct declared
  33. {
  34. void* value;
  35. static int const cmp2 = 0;
  36. friend void operator>(int, declared const&) {}
  37. };
  38. struct undeclared { declared<> dummy[2]; };
  39. template<int> struct resolve;
  40. template<>
  41. struct resolve<sizeof(declared<>)>
  42. {
  43. static const int cmp1 = 0;
  44. };
  45. template<>
  46. struct resolve<sizeof(undeclared)>
  47. {
  48. template<int>
  49. struct cmp1
  50. {
  51. static int const cmp2 = 0;
  52. };
  53. };
  54. } } }
  55. extern boost::scope_exit::aux::undeclared boost_scope_exit_args; // undefined
  56. namespace boost { namespace scope_exit { namespace aux {
  57. typedef void (*ref_tag)(int&);
  58. typedef void (*val_tag)(int );
  59. template<class T, class Tag> struct member;
  60. template<class T>
  61. struct member<T,ref_tag>
  62. {
  63. T& value;
  64. #ifndef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
  65. member(T& ref) : value(ref) {}
  66. #endif
  67. };
  68. template<class T>
  69. struct member<T,val_tag>
  70. {
  71. T value;
  72. #ifndef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
  73. member(T& val) : value(val) {}
  74. #endif
  75. };
  76. template<class T> inline T& deref(T* p, ref_tag) { return *p; }
  77. template<class T> inline T& deref(T& r, val_tag) { return r; }
  78. template<class T>
  79. struct wrapper
  80. {
  81. typedef T type;
  82. };
  83. template<class T> wrapper<T> wrap(T&);
  84. } } }
  85. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  86. BOOST_TYPEOF_REGISTER_TEMPLATE(boost::scope_exit::aux::wrapper, 1)
  87. #define BOOST_SCOPE_EXIT_AUX_GUARD(id) BOOST_PP_CAT(boost_se_guard_, id)
  88. #define BOOST_SCOPE_EXIT_AUX_GUARD_T(id) BOOST_PP_CAT(boost_se_guard_t_, id)
  89. #define BOOST_SCOPE_EXIT_AUX_PARAMS(id) BOOST_PP_CAT(boost_se_params_, id)
  90. #define BOOST_SCOPE_EXIT_AUX_PARAMS_T(id) BOOST_PP_CAT(boost_se_params_t_, id)
  91. #define BOOST_SCOPE_EXIT_AUX_TAG(id, i) \
  92. BOOST_PP_SEQ_CAT( (boost_se_tag_)(i)(_)(id) )
  93. #define BOOST_SCOPE_EXIT_AUX_PARAM(id, i, var) \
  94. BOOST_PP_SEQ_CAT( (boost_se_param_)(i)(_)(id) )
  95. #define BOOST_SCOPE_EXIT_AUX_PARAM_T(id, i, var) \
  96. BOOST_PP_SEQ_CAT( (boost_se_param_t_)(i)(_)(id) )
  97. #define BOOST_SCOPE_EXIT_AUX_CAPTURE_T(id, i, var) \
  98. BOOST_PP_SEQ_CAT( (boost_se_capture_t_)(i)(_)(id) )
  99. #define BOOST_SCOPE_EXIT_AUX_WRAPPED(id, i) \
  100. BOOST_PP_SEQ_CAT( (boost_se_wrapped_t_)(i)(_)(id) )
  101. #define BOOST_SCOPE_EXIT_AUX_DEREF(id, i, var) \
  102. boost::scope_exit::aux::deref(var, (BOOST_SCOPE_EXIT_AUX_TAG(id,i))0)
  103. #define BOOST_SCOPE_EXIT_AUX_MEMBER(r, id, i, var) \
  104. boost::scope_exit::aux::member< \
  105. BOOST_SCOPE_EXIT_AUX_PARAM_T(id,i,var), \
  106. BOOST_SCOPE_EXIT_AUX_TAG(id,i) \
  107. > BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var);
  108. // idty is (id,typename) or (id,BOOST_PP_EMPTY())
  109. #define BOOST_SCOPE_EXIT_AUX_ARG_DECL(r, idty, i, var) \
  110. BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2,1,idty) \
  111. BOOST_SCOPE_EXIT_AUX_PARAMS_T(BOOST_PP_TUPLE_ELEM(2,0,idty)):: \
  112. BOOST_SCOPE_EXIT_AUX_PARAM_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var) var
  113. #define BOOST_SCOPE_EXIT_AUX_ARG(r, id, i, var) BOOST_PP_COMMA_IF(i) \
  114. boost_se_params_->BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var).value
  115. #define BOOST_SCOPE_EXIT_AUX_TAG_DECL(r, id, i, var) \
  116. typedef void (*BOOST_SCOPE_EXIT_AUX_TAG(id,i))(int var);
  117. #ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
  118. #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq)
  119. #define BOOST_SCOPE_EXIT_AUX_PARAM_INIT(r, id, i, var) \
  120. BOOST_PP_COMMA_IF(i) { BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var) }
  121. #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq) \
  122. = { BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_INIT, id, seq) };
  123. #else
  124. #define BOOST_SCOPE_EXIT_AUX_CTOR_ARG(r, id, i, var) BOOST_PP_COMMA_IF(i) \
  125. BOOST_SCOPE_EXIT_AUX_PARAM_T(id,i,var) & BOOST_PP_CAT(a,i)
  126. #define BOOST_SCOPE_EXIT_AUX_MEMBER_INIT(r, id, i, var) BOOST_PP_COMMA_IF(i) \
  127. BOOST_SCOPE_EXIT_AUX_PARAM(id,i,var) ( BOOST_PP_CAT(a,i) )
  128. #define BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq) \
  129. BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)( \
  130. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CTOR_ARG, id, seq ) ) \
  131. : BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER_INIT, id, seq) {}
  132. #define BOOST_SCOPE_EXIT_AUX_PARAM_INIT(r, id, i, var) \
  133. BOOST_PP_COMMA_IF(i) BOOST_SCOPE_EXIT_AUX_DEREF(id,i,var)
  134. #define BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id, seq) \
  135. ( BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_INIT, id, seq) );
  136. #endif
  137. #if defined(BOOST_TYPEOF_EMULATION)
  138. #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
  139. struct BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i) \
  140. : BOOST_TYPEOF(boost::scope_exit::aux::wrap( \
  141. BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var))) \
  142. {}; typedef BOOST_PP_TUPLE_ELEM(2,1,idty) \
  143. BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i)::type \
  144. BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
  145. #elif defined(BOOST_INTEL)
  146. #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
  147. typedef BOOST_TYPEOF_KEYWORD( \
  148. BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var)) \
  149. BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
  150. #else
  151. #define BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL(r, idty, i, var) \
  152. typedef BOOST_TYPEOF(boost::scope_exit::aux::wrap( \
  153. BOOST_SCOPE_EXIT_AUX_DEREF(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var))) \
  154. BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i); \
  155. typedef BOOST_PP_TUPLE_ELEM(2,1,idty) \
  156. BOOST_SCOPE_EXIT_AUX_WRAPPED(BOOST_PP_TUPLE_ELEM(2,0,idty), i)::type \
  157. BOOST_SCOPE_EXIT_AUX_CAPTURE_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
  158. #endif
  159. #define BOOST_SCOPE_EXIT_AUX_PARAM_DECL(r, idty, i, var) \
  160. typedef BOOST_SCOPE_EXIT_AUX_CAPTURE_T( \
  161. BOOST_PP_TUPLE_ELEM(2,0,idty), i, var) \
  162. BOOST_SCOPE_EXIT_AUX_PARAM_T(BOOST_PP_TUPLE_ELEM(2,0,idty), i, var);
  163. #define BOOST_SCOPE_EXIT_AUX_IMPL(id, seq, ty) \
  164. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_TAG_DECL, id, seq) \
  165. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_CAPTURE_DECL, (id,ty), seq) \
  166. struct BOOST_SCOPE_EXIT_AUX_PARAMS_T(id) { \
  167. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_PARAM_DECL, (id,ty), seq) \
  168. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_MEMBER, id, seq) \
  169. BOOST_SCOPE_EXIT_AUX_PARAMS_T_CTOR(id, seq) \
  170. } BOOST_SCOPE_EXIT_AUX_PARAMS(id) BOOST_SCOPE_EXIT_AUX_PARAMS_INIT(id,seq) \
  171. boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve< \
  172. sizeof(boost_scope_exit_args)>::cmp1<0>::cmp2 > boost_scope_exit_args; \
  173. boost_scope_exit_args.value = &BOOST_SCOPE_EXIT_AUX_PARAMS(id); \
  174. struct BOOST_SCOPE_EXIT_AUX_GUARD_T(id) { \
  175. BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)* boost_se_params_; \
  176. BOOST_SCOPE_EXIT_AUX_GUARD_T(id) (void* boost_se_params) \
  177. : boost_se_params_( \
  178. (BOOST_SCOPE_EXIT_AUX_PARAMS_T(id)*)boost_se_params) \
  179. {} \
  180. ~BOOST_SCOPE_EXIT_AUX_GUARD_T(id)() { boost_se_body( \
  181. BOOST_PP_SEQ_FOR_EACH_I(BOOST_SCOPE_EXIT_AUX_ARG, id, seq) ); } \
  182. static void boost_se_body(BOOST_PP_SEQ_FOR_EACH_I( \
  183. BOOST_SCOPE_EXIT_AUX_ARG_DECL, (id,ty), seq) )
  184. #if defined(BOOST_MSVC)
  185. #define BOOST_SCOPE_EXIT_END } BOOST_SCOPE_EXIT_AUX_GUARD(__COUNTER__) ( \
  186. boost_scope_exit_args.value);
  187. #define BOOST_SCOPE_EXIT(seq) \
  188. BOOST_SCOPE_EXIT_AUX_IMPL(__COUNTER__, seq, BOOST_PP_EMPTY())
  189. #else
  190. #define BOOST_SCOPE_EXIT_END } BOOST_SCOPE_EXIT_AUX_GUARD(__LINE__) ( \
  191. boost_scope_exit_args.value);
  192. #define BOOST_SCOPE_EXIT(seq) \
  193. BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, BOOST_PP_EMPTY())
  194. #endif
  195. #ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
  196. #define BOOST_SCOPE_EXIT_TPL(seq) \
  197. BOOST_SCOPE_EXIT_AUX_IMPL(__LINE__, seq, typename)
  198. #else
  199. #define BOOST_SCOPE_EXIT_TPL(seq) BOOST_SCOPE_EXIT(seq)
  200. #endif
  201. #endif // #ifndef FILE_boost_scope_exit_hpp_INCLUDED