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