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/exception_ptr.hpp> 7 #include <boost/exception/get_error_info.hpp> 8 #include <boost/thread.hpp> 9 #include <boost/detail/atomic_count.hpp> 10 #include <boost/detail/lightweight_test.hpp> 11 12 typedef boost::error_info<struct tag_answer,int> answer; 13 14 boost::detail::atomic_count exc_count(0); 15 16 struct 17 err: 18 virtual boost::exception, 19 virtual std::exception 20 { errerr21 err() 22 { 23 ++exc_count; 24 } 25 errerr26 err( err const & ) 27 { 28 ++exc_count; 29 } 30 31 virtual ~errerr32 ~err() BOOST_NOEXCEPT_OR_NOTHROW 33 { 34 --exc_count; 35 } 36 37 private: 38 39 err & operator=( err const & ); 40 }; 41 42 class 43 future 44 { 45 public: 46 future()47 future (): 48 ready_ (false) 49 { 50 } 51 52 void set_exception(boost::exception_ptr const & e)53 set_exception( boost::exception_ptr const & e ) 54 { 55 boost::unique_lock<boost::mutex> lck (mux_); 56 exc_ = e; 57 ready_ = true; 58 cond_.notify_all(); 59 } 60 61 void get_exception() const62 get_exception() const 63 { 64 boost::unique_lock<boost::mutex> lck (mux_); 65 while (! ready_) 66 cond_.wait (lck); 67 rethrow_exception (exc_); 68 } 69 70 private: 71 72 bool ready_; 73 boost::exception_ptr exc_; 74 mutable boost::mutex mux_; 75 mutable boost::condition_variable cond_; 76 }; 77 78 void producer(future & f)79producer( future & f ) 80 { 81 f.set_exception (boost::copy_exception (err () << answer(42))); 82 } 83 84 void consumer()85consumer() 86 { 87 future f; 88 boost::thread thr (boost::bind (&producer, boost::ref (f))); 89 try 90 { 91 f.get_exception (); 92 } 93 catch( 94 err & e ) 95 { 96 int const * ans=boost::get_error_info<answer>(e); 97 BOOST_TEST(ans && *ans==42); 98 } 99 thr.join(); 100 } 101 102 void consume()103consume() 104 { 105 for( int i=0; i!=100; ++i ) 106 consumer(); 107 } 108 109 void thread_test()110thread_test() 111 { 112 boost::thread_group grp; 113 for( int i=0; i!=50; ++i ) 114 grp.create_thread(&consume); 115 grp.join_all (); 116 } 117 118 void simple_test()119simple_test() 120 { 121 boost::exception_ptr p = boost::copy_exception(err()); 122 try 123 { 124 rethrow_exception(p); 125 BOOST_TEST(false); 126 } 127 catch( 128 err & ) 129 { 130 } 131 catch( 132 ... ) 133 { 134 BOOST_TEST(false); 135 } 136 } 137 138 int main()139main() 140 { 141 BOOST_TEST(++exc_count==1); 142 simple_test(); 143 thread_test(); 144 BOOST_TEST(!--exc_count); 145 return boost::report_errors(); 146 } 147