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