exception_ptr_test.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. #include <boost/exception_ptr.hpp>
  5. #include <boost/exception/info.hpp>
  6. #include <boost/exception/get_error_info.hpp>
  7. #include <boost/exception/diagnostic_information.hpp>
  8. #include <boost/function.hpp>
  9. #include <boost/bind.hpp>
  10. #include <boost/thread.hpp>
  11. #include <boost/detail/atomic_count.hpp>
  12. #include <boost/detail/lightweight_test.hpp>
  13. #include <iostream>
  14. class thread_handle;
  15. boost::shared_ptr<thread_handle> create_thread( boost::function<void()> const & f );
  16. void join( thread_handle & t );
  17. class
  18. thread_handle
  19. {
  20. thread_handle( thread_handle const & );
  21. thread_handle & operator=( thread_handle const & );
  22. boost::exception_ptr err_;
  23. boost::thread t_;
  24. static
  25. void
  26. thread_wrapper( boost::function<void()> const & f, boost::exception_ptr & ep )
  27. {
  28. BOOST_ASSERT(!ep);
  29. try
  30. {
  31. f();
  32. }
  33. catch(...)
  34. {
  35. ep = boost::current_exception();
  36. }
  37. }
  38. explicit
  39. thread_handle( boost::function<void()> const & f ):
  40. t_(boost::bind(thread_wrapper,f,boost::ref(err_)))
  41. {
  42. }
  43. friend boost::shared_ptr<thread_handle> create_thread( boost::function<void()> const & f );
  44. friend void join( thread_handle & t );
  45. };
  46. boost::shared_ptr<thread_handle>
  47. create_thread( boost::function<void()> const & f )
  48. {
  49. boost::shared_ptr<thread_handle> t( new thread_handle(f) );
  50. return t;
  51. }
  52. void
  53. join( thread_handle & t )
  54. {
  55. t.t_.join();
  56. assert(t.err_);
  57. rethrow_exception(t.err_);
  58. }
  59. boost::detail::atomic_count exc_count(0);
  60. struct
  61. exc:
  62. virtual boost::exception,
  63. virtual std::exception
  64. {
  65. exc()
  66. {
  67. ++exc_count;
  68. }
  69. exc( exc const & e ):
  70. boost::exception(e),
  71. std::exception(e)
  72. {
  73. ++exc_count;
  74. }
  75. virtual
  76. ~exc() BOOST_NOEXCEPT_OR_NOTHROW
  77. {
  78. --exc_count;
  79. }
  80. private:
  81. exc & operator=( exc const & );
  82. };
  83. typedef boost::error_info<struct answer_,int> answer;
  84. void
  85. thread_func()
  86. {
  87. BOOST_THROW_EXCEPTION(exc() << answer(42));
  88. }
  89. void
  90. check( boost::shared_ptr<thread_handle> const & t )
  91. {
  92. try
  93. {
  94. join(*t);
  95. BOOST_TEST(false);
  96. }
  97. catch(
  98. exc & e )
  99. {
  100. int const * a = boost::get_error_info<answer>(e);
  101. BOOST_TEST(a && *a==42);
  102. }
  103. }
  104. void
  105. test_deep_copy()
  106. {
  107. int const * p1=0;
  108. boost::exception_ptr p;
  109. try
  110. {
  111. BOOST_THROW_EXCEPTION(exc() << answer(42));
  112. BOOST_ERROR("BOOST_THROW_EXCEPTION didn't throw");
  113. }
  114. catch(
  115. exc & e )
  116. {
  117. p1=boost::get_error_info<answer>(e);
  118. p=boost::current_exception();
  119. }
  120. BOOST_TEST(p1!=0);
  121. BOOST_TEST(p);
  122. try
  123. {
  124. boost::rethrow_exception(p);
  125. BOOST_ERROR("rethrow_exception didn't throw");
  126. }
  127. catch(
  128. exc & e )
  129. {
  130. int const * p2=boost::get_error_info<answer>(e);
  131. BOOST_TEST(p2!=0 && *p2==42);
  132. BOOST_TEST(p2!=p1);
  133. }
  134. }
  135. int
  136. main()
  137. {
  138. test_deep_copy();
  139. BOOST_TEST(++exc_count==1);
  140. try
  141. {
  142. std::vector< boost::shared_ptr<thread_handle> > threads;
  143. std::generate_n(std::inserter(threads,threads.end()),1,boost::bind(create_thread,thread_func));
  144. std::for_each(threads.begin(),threads.end(),check);
  145. return boost::report_errors();
  146. }
  147. catch(
  148. ... )
  149. {
  150. std::cerr <<
  151. "Caught unexpected exception.\n"
  152. "Output from current_exception_diagnostic_information:\n" <<
  153. boost::current_exception_diagnostic_information() << std::endl;
  154. return 42;
  155. }
  156. BOOST_TEST(!--exc_count);
  157. }