exception_ptr.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. //Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
  2. //Distributed under the Boost Software License, Version 1.0. (See accompanying
  3. //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. #ifndef UUID_FA5836A2CADA11DC8CD47C8555D89593
  5. #define UUID_FA5836A2CADA11DC8CD47C8555D89593
  6. #include <boost/config.hpp>
  7. #ifdef BOOST_NO_EXCEPTIONS
  8. #error This header requires exception handling to be enabled.
  9. #endif
  10. #include <boost/exception/exception.hpp>
  11. #include <boost/exception/info.hpp>
  12. #include <boost/exception/diagnostic_information.hpp>
  13. #include <boost/exception/detail/type_info.hpp>
  14. #include <boost/shared_ptr.hpp>
  15. #include <stdexcept>
  16. #include <new>
  17. #include <ios>
  18. namespace
  19. boost
  20. {
  21. #ifndef BOOST_NO_RTTI
  22. typedef error_info<struct tag_original_exception_type,std::type_info const *> original_exception_type;
  23. inline
  24. std::string
  25. to_string( original_exception_type const & x )
  26. {
  27. return x.value()->name();
  28. }
  29. #endif
  30. class exception_ptr;
  31. exception_ptr current_exception();
  32. void rethrow_exception( exception_ptr const & );
  33. class
  34. exception_ptr:
  35. public exception_detail::exception_ptr_base
  36. {
  37. typedef bool exception_ptr::*unspecified_bool_type;
  38. friend exception_ptr current_exception();
  39. friend void rethrow_exception( exception_ptr const & );
  40. shared_ptr<exception_detail::clone_base const> c_;
  41. bool bad_alloc_;
  42. struct
  43. bad_alloc_tag
  44. {
  45. };
  46. explicit
  47. exception_ptr( bad_alloc_tag ):
  48. bad_alloc_(true)
  49. {
  50. }
  51. explicit
  52. exception_ptr( shared_ptr<exception_detail::clone_base const> const & c ):
  53. c_(c),
  54. bad_alloc_(false)
  55. {
  56. BOOST_ASSERT(c);
  57. }
  58. void
  59. _rethrow() const
  60. {
  61. BOOST_ASSERT(*this);
  62. if( bad_alloc_ )
  63. throw enable_current_exception(std::bad_alloc());
  64. else
  65. c_->rethrow();
  66. }
  67. bool
  68. _empty() const
  69. {
  70. return !bad_alloc_ && !c_;
  71. }
  72. public:
  73. exception_ptr():
  74. bad_alloc_(false)
  75. {
  76. }
  77. operator unspecified_bool_type() const
  78. {
  79. return _empty() ? 0 : &exception_ptr::bad_alloc_;
  80. }
  81. friend
  82. bool
  83. operator==( exception_ptr const & a, exception_ptr const & b )
  84. {
  85. return a.c_==b.c_ && a.bad_alloc_==b.bad_alloc_;
  86. }
  87. friend
  88. bool
  89. operator!=( exception_ptr const & a, exception_ptr const & b )
  90. {
  91. return !(a==b);
  92. }
  93. };
  94. class
  95. unknown_exception:
  96. public exception,
  97. public std::exception,
  98. public exception_detail::clone_base
  99. {
  100. public:
  101. unknown_exception()
  102. {
  103. }
  104. explicit
  105. unknown_exception( std::exception const & e )
  106. {
  107. add_original_type(e);
  108. }
  109. explicit
  110. unknown_exception( boost::exception const & e ):
  111. boost::exception(e)
  112. {
  113. add_original_type(e);
  114. }
  115. ~unknown_exception() throw()
  116. {
  117. }
  118. private:
  119. exception_detail::clone_base const *
  120. clone() const
  121. {
  122. return new unknown_exception(*this);
  123. }
  124. void
  125. rethrow() const
  126. {
  127. throw*this;
  128. }
  129. template <class E>
  130. void
  131. add_original_type( E const & e )
  132. {
  133. #ifndef BOOST_NO_RTTI
  134. (*this) << original_exception_type(&typeid(e));
  135. #endif
  136. }
  137. };
  138. namespace
  139. exception_detail
  140. {
  141. template <class T>
  142. class
  143. current_exception_std_exception_wrapper:
  144. public T,
  145. public boost::exception,
  146. public clone_base
  147. {
  148. public:
  149. explicit
  150. current_exception_std_exception_wrapper( T const & e1 ):
  151. T(e1)
  152. {
  153. add_original_type(e1);
  154. }
  155. current_exception_std_exception_wrapper( T const & e1, boost::exception const & e2 ):
  156. T(e1),
  157. boost::exception(e2)
  158. {
  159. add_original_type(e1);
  160. }
  161. ~current_exception_std_exception_wrapper() throw()
  162. {
  163. }
  164. private:
  165. clone_base const *
  166. clone() const
  167. {
  168. return new current_exception_std_exception_wrapper(*this);
  169. }
  170. void
  171. rethrow() const
  172. {
  173. throw *this;
  174. }
  175. template <class E>
  176. void
  177. add_original_type( E const & e )
  178. {
  179. #ifndef BOOST_NO_RTTI
  180. (*this) << original_exception_type(&typeid(e));
  181. #endif
  182. }
  183. };
  184. #ifdef BOOST_NO_RTTI
  185. template <class T>
  186. exception const *
  187. get_boost_exception( T const * )
  188. {
  189. try
  190. {
  191. throw;
  192. }
  193. catch(
  194. exception & x )
  195. {
  196. return &x;
  197. }
  198. catch(...)
  199. {
  200. return 0;
  201. }
  202. }
  203. #else
  204. template <class T>
  205. exception const *
  206. get_boost_exception( T const * x )
  207. {
  208. return dynamic_cast<exception const *>(x);
  209. }
  210. #endif
  211. template <class T>
  212. inline
  213. shared_ptr<clone_base const>
  214. current_exception_std_exception( T const & e1 )
  215. {
  216. if( boost::exception const * e2 = get_boost_exception(&e1) )
  217. return shared_ptr<current_exception_std_exception_wrapper<T> const>(new current_exception_std_exception_wrapper<T>(e1,*e2));
  218. else
  219. return shared_ptr<current_exception_std_exception_wrapper<T> const>(new current_exception_std_exception_wrapper<T>(e1));
  220. }
  221. inline
  222. shared_ptr<clone_base const>
  223. current_exception_unknown_exception()
  224. {
  225. return shared_ptr<unknown_exception const>(new unknown_exception());
  226. }
  227. inline
  228. shared_ptr<clone_base const>
  229. current_exception_unknown_boost_exception( boost::exception const & e )
  230. {
  231. return shared_ptr<unknown_exception const>(new unknown_exception(e));
  232. }
  233. inline
  234. shared_ptr<clone_base const>
  235. current_exception_unknown_std_exception( std::exception const & e )
  236. {
  237. if( boost::exception const * be = get_boost_exception(&e) )
  238. return current_exception_unknown_boost_exception(*be);
  239. else
  240. return shared_ptr<unknown_exception const>(new unknown_exception(e));
  241. }
  242. inline
  243. shared_ptr<clone_base const>
  244. current_exception_impl()
  245. {
  246. try
  247. {
  248. throw;
  249. }
  250. catch(
  251. exception_detail::clone_base & e )
  252. {
  253. return shared_ptr<exception_detail::clone_base const>(e.clone());
  254. }
  255. catch(
  256. std::domain_error & e )
  257. {
  258. return exception_detail::current_exception_std_exception(e);
  259. }
  260. catch(
  261. std::invalid_argument & e )
  262. {
  263. return exception_detail::current_exception_std_exception(e);
  264. }
  265. catch(
  266. std::length_error & e )
  267. {
  268. return exception_detail::current_exception_std_exception(e);
  269. }
  270. catch(
  271. std::out_of_range & e )
  272. {
  273. return exception_detail::current_exception_std_exception(e);
  274. }
  275. catch(
  276. std::logic_error & e )
  277. {
  278. return exception_detail::current_exception_std_exception(e);
  279. }
  280. catch(
  281. std::range_error & e )
  282. {
  283. return exception_detail::current_exception_std_exception(e);
  284. }
  285. catch(
  286. std::overflow_error & e )
  287. {
  288. return exception_detail::current_exception_std_exception(e);
  289. }
  290. catch(
  291. std::underflow_error & e )
  292. {
  293. return exception_detail::current_exception_std_exception(e);
  294. }
  295. catch(
  296. std::ios_base::failure & e )
  297. {
  298. return exception_detail::current_exception_std_exception(e);
  299. }
  300. catch(
  301. std::runtime_error & e )
  302. {
  303. return exception_detail::current_exception_std_exception(e);
  304. }
  305. catch(
  306. std::bad_alloc & e )
  307. {
  308. return exception_detail::current_exception_std_exception(e);
  309. }
  310. #ifndef BOOST_NO_TYPEID
  311. catch(
  312. std::bad_cast & e )
  313. {
  314. return exception_detail::current_exception_std_exception(e);
  315. }
  316. catch(
  317. std::bad_typeid & e )
  318. {
  319. return exception_detail::current_exception_std_exception(e);
  320. }
  321. #endif
  322. catch(
  323. std::bad_exception & e )
  324. {
  325. return exception_detail::current_exception_std_exception(e);
  326. }
  327. catch(
  328. std::exception & e )
  329. {
  330. return exception_detail::current_exception_unknown_std_exception(e);
  331. }
  332. catch(
  333. boost::exception & e )
  334. {
  335. return exception_detail::current_exception_unknown_boost_exception(e);
  336. }
  337. catch(
  338. ... )
  339. {
  340. return exception_detail::current_exception_unknown_exception();
  341. }
  342. }
  343. }
  344. inline
  345. exception_ptr
  346. current_exception()
  347. {
  348. try
  349. {
  350. return exception_ptr(exception_detail::current_exception_impl());
  351. }
  352. catch(
  353. std::bad_alloc & )
  354. {
  355. }
  356. catch(
  357. ... )
  358. {
  359. try
  360. {
  361. return exception_ptr(exception_detail::current_exception_std_exception(std::bad_exception()));
  362. }
  363. catch(
  364. std::bad_alloc & )
  365. {
  366. }
  367. catch(
  368. ... )
  369. {
  370. BOOST_ASSERT(0);
  371. }
  372. }
  373. return exception_ptr(exception_ptr::bad_alloc_tag());
  374. }
  375. template <class T>
  376. inline
  377. exception_ptr
  378. copy_exception( T const & e )
  379. {
  380. try
  381. {
  382. throw enable_current_exception(e);
  383. }
  384. catch(
  385. ... )
  386. {
  387. return current_exception();
  388. }
  389. }
  390. inline
  391. void
  392. rethrow_exception( exception_ptr const & p )
  393. {
  394. p._rethrow();
  395. }
  396. inline
  397. std::string
  398. to_string( exception_ptr const & p )
  399. {
  400. std::string s='\n'+diagnostic_information(p);
  401. std::string padding(" ");
  402. std::string r;
  403. bool f=false;
  404. for( std::string::const_iterator i=s.begin(),e=s.end(); i!=e; ++i )
  405. {
  406. if( f )
  407. r+=padding;
  408. char c=*i;
  409. r+=c;
  410. f=(c=='\n');
  411. }
  412. return r;
  413. }
  414. }
  415. #endif