| 1 | #include <boost/exception.hpp>
|
|---|
| 2 | #include <boost/thread.hpp>
|
|---|
| 3 | #include <string>
|
|---|
| 4 |
|
|---|
| 5 | typedef boost::error_info<struct tag_throw_string, std::string> err_info;
|
|---|
| 6 |
|
|---|
| 7 | class err
|
|---|
| 8 | : public boost::exception
|
|---|
| 9 | , public std::exception
|
|---|
| 10 | {
|
|---|
| 11 | };
|
|---|
| 12 |
|
|---|
| 13 | // transferres exception_ptr from producer to consumer thread
|
|---|
| 14 | class future
|
|---|
| 15 | {
|
|---|
| 16 | public:
|
|---|
| 17 | future () : ready_ (false) {}
|
|---|
| 18 |
|
|---|
| 19 | // called in producer thread, gets exception_ptr
|
|---|
| 20 | void set_exception (boost::exception_ptr const& e)
|
|---|
| 21 | {
|
|---|
| 22 | boost::unique_lock<boost::mutex> lck (mux_);
|
|---|
| 23 | exc_ = e;
|
|---|
| 24 | ready_ = true;
|
|---|
| 25 | cond_.notify_all();
|
|---|
| 26 | }
|
|---|
| 27 |
|
|---|
| 28 | // called in consumer thread, returns exception_ptr
|
|---|
| 29 | boost::exception_ptr get_exception () const
|
|---|
| 30 | {
|
|---|
| 31 | boost::unique_lock<boost::mutex> lck (mux_);
|
|---|
| 32 | while (! ready_)
|
|---|
| 33 | cond_.wait (lck);
|
|---|
| 34 | return exc_; // was: rethrow_exception (exc_);
|
|---|
| 35 | }
|
|---|
| 36 |
|
|---|
| 37 | private:
|
|---|
| 38 | bool ready_;
|
|---|
| 39 | boost::exception_ptr exc_;
|
|---|
| 40 | mutable boost::mutex mux_;
|
|---|
| 41 | mutable boost::condition_variable cond_;
|
|---|
| 42 | };
|
|---|
| 43 |
|
|---|
| 44 | void producer (future& f, boost::barrier& b)
|
|---|
| 45 | {
|
|---|
| 46 | b.wait ();
|
|---|
| 47 |
|
|---|
| 48 | // 1. create temp boost::exception object
|
|---|
| 49 | // 2. take exception_ptr to it
|
|---|
| 50 | f.set_exception (boost::copy_exception (err () << err_info ("stub")));
|
|---|
| 51 | // 3. destroying temp boost::exception object
|
|---|
| 52 | }
|
|---|
| 53 |
|
|---|
| 54 | void consumer ()
|
|---|
| 55 | {
|
|---|
| 56 | // barrier used to increase probablity to get a fault
|
|---|
| 57 | boost::barrier b (2);
|
|---|
| 58 |
|
|---|
| 59 | future f;
|
|---|
| 60 | boost::thread thr (boost::bind (&producer, boost::ref (f), boost::ref (b)));
|
|---|
| 61 |
|
|---|
| 62 | b.wait ();
|
|---|
| 63 |
|
|---|
| 64 | if (boost::exception_ptr e=f.get_exception() )
|
|---|
| 65 | {
|
|---|
| 66 | try { rethrow_exception (e); }
|
|---|
| 67 | catch (err const& e) {}
|
|---|
| 68 | }
|
|---|
| 69 |
|
|---|
| 70 | thr.join ();
|
|---|
| 71 | }
|
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 | void consume ()
|
|---|
| 75 | {
|
|---|
| 76 | for (int i=0;i<100;++i)
|
|---|
| 77 | consumer ();
|
|---|
| 78 | }
|
|---|
| 79 |
|
|---|
| 80 | int main ()
|
|---|
| 81 | {
|
|---|
| 82 | boost::thread_group grp;
|
|---|
| 83 | for (int i=0; i<50; ++i)
|
|---|
| 84 | grp.create_thread (&consume);
|
|---|
| 85 |
|
|---|
| 86 | grp.join_all ();
|
|---|
| 87 | }
|
|---|