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