• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)79 producer( future & f )
80     {
81     f.set_exception (boost::copy_exception (err () << answer(42)));
82     }
83 
84 void
consumer()85 consumer()
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()103 consume()
104     {
105     for( int i=0; i!=100; ++i )
106         consumer();
107     }
108 
109 void
thread_test()110 thread_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()119 simple_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()139 main()
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