fork(6) download
  1. // Scroll down to line 85 for example of usage
  2. // _________________[uncaught_exception_count.hpp]_____________________ //
  3.  
  4. // Copyright Evgeny Panasyuk 2012.
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://w...content-available-to-author-only...t.org/LICENSE_1_0.txt)
  8.  
  9. // e-mail: E?????[dot]P???????[at]gmail.???
  10.  
  11. #ifndef BOOST_UNCAUGHT_EXCEPTION_COUNT_HPP_39A1E90FC11647e08D5F6ED16CD34B34
  12. #define BOOST_UNCAUGHT_EXCEPTION_COUNT_HPP_39A1E90FC11647e08D5F6ED16CD34B34
  13.  
  14. #if defined(_MSC_VER) || defined(__GNUG__) || defined(__CLANG__)
  15. #define BOOST_UNCAUGHT_EXCEPTION_COUNT_SUPPORTED 1
  16. #endif
  17.  
  18. namespace boost
  19. {
  20. namespace exception_detail
  21. {
  22. template<typename To> inline
  23. To *unrelated_pointer_cast(void *from)
  24. {
  25. return static_cast<To*>(from);
  26. }
  27. }
  28.  
  29. // uncaught_exception_count is a function similar to std::uncaught_exception from standard library,
  30. // but instead of boolean result it returns unsigned int showing current count of uncaught exceptions.
  31.  
  32. #if defined(_MSC_VER)
  33. namespace exception_detail
  34. {
  35. extern "C" char * __cdecl _getptd();
  36. }
  37. inline unsigned uncaught_exception_count()
  38. {
  39. // MSVC specific. Tested on {MSVC2005SP1,MSVC2008SP1,MSVC2010SP1,MSVC2012}x{x32,x64}.
  40. return *exception_detail::unrelated_pointer_cast<unsigned>
  41. (
  42. exception_detail::_getptd() + (sizeof(void*)==8 ? 0x100 : 0x90)
  43. );
  44. }
  45. #elif defined(__GNUG__) || defined(__CLANG__)
  46. namespace exception_detail
  47. {
  48. extern "C" char * __cxa_get_globals();
  49. }
  50. inline unsigned uncaught_exception_count()
  51. {
  52. // Tested on {Clang 3.2,GCC 3.4.6,GCC 4.1.2,GCC 4.4.6,GCC 4.4.7}x{x32,x64}
  53. return *exception_detail::unrelated_pointer_cast<unsigned>
  54. (
  55. exception_detail::__cxa_get_globals() + (sizeof(void*)==8 ? 0x8 : 0x4)
  56. );
  57. }
  58. #endif
  59.  
  60. // Within one scope uncaught_exception_count can be changed only by +1.
  61. // uncaught_exception_count_latch is primitive which helps to determine such transition.
  62. // Internally it stores and compares only last bit of uncaught_exception_count value
  63. #ifdef BOOST_UNCAUGHT_EXCEPTION_COUNT_SUPPORTED
  64. class uncaught_exception_count_latch
  65. {
  66. unsigned char enter_state;
  67. public:
  68. uncaught_exception_count_latch()
  69. : enter_state(static_cast<unsigned char>( uncaught_exception_count() & 1 ))
  70. {
  71. }
  72. bool transitioned() const
  73. {
  74. return enter_state != ( uncaught_exception_count() & 1 );
  75. }
  76. };
  77. #endif
  78.  
  79. }
  80.  
  81. #endif
  82.  
  83. // ______________[end of uncaught_exception_count.hpp]_________________ //
  84.  
  85. #include <iostream>
  86. #include <ostream>
  87.  
  88. using namespace std;
  89.  
  90. void success()
  91. {
  92. cout << "\tsuccess()" << endl;
  93. }
  94. void failure()
  95. {
  96. cout << "\tfailure()" << endl;
  97. }
  98.  
  99. class ScopeGuard
  100. {
  101. bool commited;
  102. public:
  103. ScopeGuard() : commited(false) {}
  104. bool commit()
  105. {
  106. commited = true;
  107. }
  108. ~ScopeGuard()
  109. {
  110. if(commited)
  111. success();
  112. else
  113. failure();
  114. }
  115. };
  116.  
  117. class ScopeAction
  118. {
  119. boost::uncaught_exception_count_latch exception_state;
  120. public:
  121. ~ScopeAction()
  122. {
  123. if(exception_state.transitioned())
  124. failure();
  125. else
  126. success();
  127. }
  128. };
  129.  
  130. int main()
  131. {
  132. {
  133. cout << "ScopeGuard:" << endl;
  134. try
  135. {
  136. ScopeGuard guard;
  137. throw 1;
  138. guard.commit();
  139. }
  140. catch(int) {}
  141. {
  142. ScopeGuard guard;
  143. // ...
  144. guard.commit();
  145. }
  146. }
  147. {
  148. cout << "ScopeAction:" << endl;
  149. try
  150. {
  151. ScopeAction guard;
  152. throw 1;
  153. }
  154. catch(int) {}
  155. {
  156. ScopeAction guard;
  157. // ...
  158. }
  159. }
  160. }
Success #stdin #stdout 0s 2984KB
stdin
Standard input is empty
stdout
ScopeGuard:
	failure()
	success()
ScopeAction:
	failure()
	success()