• 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/config.hpp>
7 
8 #if defined( BOOST_NO_EXCEPTIONS )
9 #   error This program requires exception handling.
10 #endif
11 
12 #include <boost/exception_ptr.hpp>
13 #include <boost/exception/get_error_info.hpp>
14 #include <boost/thread.hpp>
15 #include <boost/detail/atomic_count.hpp>
16 #include <boost/detail/lightweight_test.hpp>
17 
18 typedef boost::error_info<struct tag_answer,int> answer;
19 
20 int const thread_count = 100;
21 
22 boost::detail::atomic_count exc_count(0);
23 
24 struct
25 err:
26     virtual boost::exception,
27     virtual std::exception
28     {
errerr29     err()
30         {
31         ++exc_count;
32         }
33 
errerr34     err( err const & )
35         {
36         ++exc_count;
37         }
38 
39     virtual
~errerr40     ~err() BOOST_NOEXCEPT_OR_NOTHROW
41         {
42         --exc_count;
43         }
44 
45     private:
46 
47     err & operator=( err const & );
48     };
49 
50 
51 class
52 future
53     {
54     public:
55 
future()56     future():
57         ready_(false)
58         {
59         }
60 
61     void
set_exception(boost::exception_ptr const & e)62     set_exception( boost::exception_ptr const & e )
63         {
64         boost::unique_lock<boost::mutex> lck(mux_);
65         exc_ = e;
66         ready_ = true;
67         cond_.notify_all();
68         }
69 
70     void
get_exception() const71     get_exception() const
72         {
73         boost::unique_lock<boost::mutex> lck(mux_);
74         while( !ready_ )
75             cond_.wait(lck);
76         rethrow_exception(exc_);
77         }
78 
79     private:
80 
81     bool ready_;
82     boost::exception_ptr exc_;
83     mutable boost::mutex mux_;
84     mutable boost::condition_variable cond_;
85     };
86 
87 void
producer(future & f)88 producer( future & f )
89     {
90     f.set_exception(boost::copy_exception(err() << answer(42)));
91     }
92 
93 void
consumer()94 consumer()
95     {
96     future f;
97     boost::thread thr(boost::bind(&producer, boost::ref(f)));
98     try
99         {
100         f.get_exception();
101         }
102     catch(
103     err & e )
104         {
105         int const * ans=boost::get_error_info<answer>(e);
106         BOOST_TEST(ans && *ans==42);
107         }
108     thr.join();
109     }
110 
111 void
consume()112 consume()
113     {
114     for( int i=0; i!=thread_count; ++i )
115         consumer();
116     }
117 
118 void
thread_test()119 thread_test()
120     {
121     boost::thread_group grp;
122     for( int i=0; i!=thread_count; ++i )
123         grp.create_thread(&consume);
124     grp.join_all();
125     }
126 
127 void
simple_test()128 simple_test()
129     {
130     boost::exception_ptr p = boost::copy_exception(err() << answer(42));
131     try
132         {
133         rethrow_exception(p);
134         BOOST_TEST(false);
135         }
136     catch(
137     err & )
138         {
139         }
140     catch(
141     ... )
142         {
143         BOOST_TEST(false);
144         }
145     }
146 
147 int
main()148 main()
149     {
150     BOOST_TEST(++exc_count==1);
151     simple_test();
152     thread_test();
153     BOOST_TEST(!--exc_count);
154     return boost::report_errors();
155     }
156