Imported Upstream version 1.49.0
[platform/upstream/boost.git] / libs / exception / test / exception_ptr_test.cpp
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,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     if( 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 & )
83         {
84         ++exc_count;
85         }
86
87     virtual
88     ~exc() throw()
89         {
90         --exc_count;
91         }
92
93     private:
94
95     exc & operator=( exc const & );
96     };
97
98 typedef boost::error_info<struct answer_,int> answer;
99
100 void
101 thread_func()
102     {
103     BOOST_THROW_EXCEPTION(exc() << answer(42));
104     }
105
106 void
107 check( boost::shared_ptr<thread_handle> const & t )
108     {
109     try
110         {
111         join(*t);
112         }
113     catch(
114     exc & e )
115         {
116         int const * a = boost::get_error_info<answer>(e);
117         BOOST_TEST(a && *a==42);
118         }
119     }
120
121 int
122 main()
123     {
124     BOOST_TEST(++exc_count==1);
125     try
126         {
127         std::vector< boost::shared_ptr<thread_handle> > threads;
128         std::generate_n(std::inserter(threads,threads.end()),256,boost::bind(create_thread,thread_func));
129         std::for_each(threads.begin(),threads.end(),check);
130         return boost::report_errors();
131         }
132     catch(
133     ... )
134         {
135         std::cerr <<
136             "Caught unexpected exception.\n"
137             "Output from current_exception_diagnostic_information:\n" <<
138             boost::current_exception_diagnostic_information() << std::endl;
139         return 42;
140         }
141     BOOST_TEST(!--exc_count);
142     }