1 //Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. 2 3 //Distributed under the Boost Software License, Version 1.0. (See accompanying 4 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #include <boost/config.hpp> 7 8 #if defined( BOOST_NO_EXCEPTIONS ) 9 # error This program requires exception handling. 10 #endif 11 12 #include <boost/exception_ptr.hpp> 13 #include <boost/exception/get_error_info.hpp> 14 #include <boost/thread.hpp> 15 #include <boost/detail/atomic_count.hpp> 16 #include <boost/detail/lightweight_test.hpp> 17 18 typedef boost::error_info<struct tag_answer,int> answer; 19 20 int const thread_count = 100; 21 22 boost::detail::atomic_count exc_count(0); 23 24 struct 25 err: 26 virtual boost::exception, 27 virtual std::exception 28 { errerr29 err() 30 { 31 ++exc_count; 32 } 33 errerr34 err( err const & ) 35 { 36 ++exc_count; 37 } 38 39 virtual ~errerr40 ~err() BOOST_NOEXCEPT_OR_NOTHROW 41 { 42 --exc_count; 43 } 44 45 private: 46 47 err & operator=( err const & ); 48 }; 49 50 51 class 52 future 53 { 54 public: 55 future()56 future(): 57 ready_(false) 58 { 59 } 60 61 void set_exception(boost::exception_ptr const & e)62 set_exception( boost::exception_ptr const & e ) 63 { 64 boost::unique_lock<boost::mutex> lck(mux_); 65 exc_ = e; 66 ready_ = true; 67 cond_.notify_all(); 68 } 69 70 void get_exception() const71 get_exception() const 72 { 73 boost::unique_lock<boost::mutex> lck(mux_); 74 while( !ready_ ) 75 cond_.wait(lck); 76 rethrow_exception(exc_); 77 } 78 79 private: 80 81 bool ready_; 82 boost::exception_ptr exc_; 83 mutable boost::mutex mux_; 84 mutable boost::condition_variable cond_; 85 }; 86 87 void producer(future & f)88producer( future & f ) 89 { 90 f.set_exception(boost::copy_exception(err() << answer(42))); 91 } 92 93 void consumer()94consumer() 95 { 96 future f; 97 boost::thread thr(boost::bind(&producer, boost::ref(f))); 98 try 99 { 100 f.get_exception(); 101 } 102 catch( 103 err & e ) 104 { 105 int const * ans=boost::get_error_info<answer>(e); 106 BOOST_TEST(ans && *ans==42); 107 } 108 thr.join(); 109 } 110 111 void consume()112consume() 113 { 114 for( int i=0; i!=thread_count; ++i ) 115 consumer(); 116 } 117 118 void thread_test()119thread_test() 120 { 121 boost::thread_group grp; 122 for( int i=0; i!=thread_count; ++i ) 123 grp.create_thread(&consume); 124 grp.join_all(); 125 } 126 127 void simple_test()128simple_test() 129 { 130 boost::exception_ptr p = boost::copy_exception(err() << answer(42)); 131 try 132 { 133 rethrow_exception(p); 134 BOOST_TEST(false); 135 } 136 catch( 137 err & ) 138 { 139 } 140 catch( 141 ... ) 142 { 143 BOOST_TEST(false); 144 } 145 } 146 147 int main()148main() 149 { 150 BOOST_TEST(++exc_count==1); 151 simple_test(); 152 thread_test(); 153 BOOST_TEST(!--exc_count); 154 return boost::report_errors(); 155 } 156