Boost Exception

In other libraries, watch for compile error referring to throw_exception_assert_compatibility in boost::throw_exception. Resolve by throwing an exception that derives from std::exception. This is not a new requirement but it is being enforced now.

[SVN r46818]
This commit is contained in:
Emil Dotchevski
2008-06-28 18:29:40 +00:00
parent 12029f86ba
commit a1c08eb8e0
100 changed files with 16134 additions and 7 deletions

15
example/Jamfile Normal file
View File

@ -0,0 +1,15 @@
# Boost Exception Library example Jamfile
#
# Copyright (c) 2006-2008 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)
exe example_io : example_io.cpp ;
obj error_info_1 : error_info_1.cpp ;
obj error_info_2 : error_info_2.cpp ;
obj cloning_1 : cloning_1.cpp ;
obj cloning_2 : cloning_2.cpp ;
obj info_tuple : info_tuple.cpp ;
obj enable_error_info : enable_error_info.cpp ;
obj logging : logging.cpp ;

23
example/cloning_1.cpp Normal file
View File

@ -0,0 +1,23 @@
//Copyright (c) 2006-2008 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)
//This example shows how to enable cloning when throwing a boost::exception.
#include <boost/exception/enable_current_exception.hpp>
#include <boost/exception/info.hpp>
#include <stdio.h>
#include <errno.h>
typedef boost::error_info<struct tag_errno,int> errno_info;
class file_read_error: public boost::exception { };
void
file_read( FILE * f, void * buffer, size_t size )
{
if( size!=fread(buffer,1,size,f) )
throw boost::enable_current_exception(file_read_error()) <<
errno_info(errno);
}

39
example/cloning_2.cpp Normal file
View File

@ -0,0 +1,39 @@
//Copyright (c) 2006-2008 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)
//This example shows how to transport cloning-enabled boost::exceptions between threads.
#include <boost/exception_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
void do_work(); //throws cloning-enabled boost::exceptions
void
worker_thread( boost::exception_ptr & error )
{
try
{
do_work();
error = boost::exception_ptr();
}
catch(
... )
{
error = boost::current_exception();
}
}
// ...continued
void
work()
{
boost::exception_ptr error;
boost::thread t( boost::bind(worker_thread,boost::ref(error)) );
t.join();
if( error )
boost::rethrow_exception(error);
}

View File

@ -0,0 +1,35 @@
//Copyright (c) 2006-2008 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)
//This example shows how to throw exception objects that support
//transporting of arbitrary data to the catch site, even for types
//that do not derive from boost::exception.
#include <boost/exception.hpp>
#include <stdexcept>
typedef boost::error_info<struct tag_std_range_min,size_t> std_range_min;
typedef boost::error_info<struct tag_std_range_max,size_t> std_range_max;
typedef boost::error_info<struct tag_std_range_index,size_t> std_range_index;
template <class T>
class
my_container
{
public:
size_t size() const;
T const &
operator[]( size_t i ) const
{
if( i > size() )
throw boost::enable_error_info(std::range_error("Index out of range")) <<
std_range_min(0) <<
std_range_max(size()) <<
std_range_index(i);
//....
}
};

36
example/error_info_1.cpp Normal file
View File

@ -0,0 +1,36 @@
//Copyright (c) 2006-2008 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)
//This example shows how to add data to boost::exception objects at the
//point of the throw, and how to retrieve that data at the point of the catch.
#include <boost/exception.hpp>
#include <errno.h>
#include <iostream>
typedef boost::error_info<struct tag_errno,int> errno_info; //(1)
class my_error: public boost::exception, public std::exception { }; //(2)
void
f()
{
throw my_error() << errno_info(errno); //(3)
}
void
g()
{
try
{
f();
}
catch(
my_error & x )
{
if( boost::shared_ptr<int const> err=boost::get_error_info<errno_info>(x) )
std::cerr << "Error code: " << *err;
}
}

49
example/error_info_2.cpp Normal file
View File

@ -0,0 +1,49 @@
//Copyright (c) 2006-2008 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)
//This example shows how to add arbitrary data to active exception objects.
#include <boost/exception.hpp>
#include <boost/shared_ptr.hpp>
#include <stdio.h>
#include <errno.h>
//
typedef boost::error_info<struct tag_errno,int> errno_info;
class file_read_error: public boost::exception { };
void
file_read( FILE * f, void * buffer, size_t size )
{
if( size!=fread(buffer,1,size,f) )
throw file_read_error() << errno_info(errno);
}
//
typedef boost::error_info<struct tag_file_name,std::string> file_name_info;
boost::shared_ptr<FILE> file_open( char const * file_name, char const * mode );
void file_read( FILE * f, void * buffer, size_t size );
void
parse_file( char const * file_name )
{
boost::shared_ptr<FILE> f = file_open(file_name,"rb");
assert(f);
try
{
char buf[1024];
file_read( f.get(), buf, sizeof(buf) );
}
catch(
boost::exception & e )
{
e << file_name_info(file_name);
throw;
}
}

215
example/example_io.cpp Normal file
View File

@ -0,0 +1,215 @@
//Copyright (c) 2006-2008 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)
//This program simulates errors on copying simple data files.
//It demonstrates how the proposed Boost exception library can be used.
//
//The documentation for boost::exception can be found at:
//
// http://www.revergestudios.com/boost-exception/boost-exception.htm.
//
//The output from this program can vary depending on the compiler/OS combination.
#include <boost/exception.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <stdio.h>
#include <errno.h>
#include <string>
#include <iostream>
typedef boost::error_info<struct tag_errno,int> errno_info;
typedef boost::error_info<struct tag_file_stream,boost::weak_ptr<FILE> > file_stream_info;
typedef boost::error_info<struct tag_open_mode,std::string> open_mode_info; //The open mode of a failed fopen request.
typedef boost::error_info<struct tag_file_name,std::string> file_name_info; //The file name of a failed file operation.
typedef boost::error_info<struct tag_file_name_src,std::string> file_name_src_info; //The source file name of a failed copy operation.
typedef boost::error_info<struct tag_file_name_dst,std::string> file_name_dst_info; //The destination file name of a failed copy operation.
typedef boost::error_info<struct tag_function,std::string> function_info; //The name of the C function which reported the failure.
char const data[] = "example";
size_t const data_size = sizeof(data);
class
error: //Base for all exception objects we throw.
public std::exception,
public boost::exception
{
public:
char const *
what() const throw()
{
return boost::exception::diagnostic_information();
}
protected:
~error() throw()
{
}
};
class open_error: public error { };
class read_error: public error { };
class write_error: public error { };
class fopen_error: public open_error { };
class fread_error: public read_error { };
class fwrite_error: public write_error { };
boost::shared_ptr<FILE>
my_fopen( char const * name, char const * mode )
{
if( FILE * f = ::fopen(name,mode) )
return boost::shared_ptr<FILE>(f,fclose);
else
throw fopen_error() << BOOST_ERROR_INFO <<
errno_info(errno) <<
file_name_info(name) <<
open_mode_info(mode) <<
function_info("fopen");
}
void
my_fread( void * buffer, size_t size, size_t count, boost::shared_ptr<FILE> const & stream )
{
assert(stream);
if( count!=fread(buffer,size,count,stream.get()) || ferror(stream.get()) )
throw fread_error() << BOOST_ERROR_INFO <<
function_info("fread") <<
errno_info(errno) <<
file_stream_info(boost::weak_ptr<FILE>(stream));
}
void
my_fwrite( void const * buffer, size_t size, size_t count, boost::shared_ptr<FILE> const & stream )
{
assert(stream);
if( count!=fwrite(buffer,size,count,stream.get()) || ferror(stream.get()) )
throw fwrite_error() << BOOST_ERROR_INFO <<
function_info("fwrite") <<
errno_info(errno) <<
file_stream_info(boost::weak_ptr<FILE>(stream));
}
void
reset_file( char const * file_name )
{
(void) my_fopen(file_name,"wb");
}
void
create_data( char const * file_name )
{
boost::shared_ptr<FILE> f = my_fopen(file_name,"wb");
my_fwrite( data, 1, data_size, f );
}
void
copy_data( char const * src_file_name, char const * dst_file_name )
{
boost::shared_ptr<FILE> src = my_fopen(src_file_name,"rb");
boost::shared_ptr<FILE> dst = my_fopen(dst_file_name,"wb");
try
{
char buffer[data_size];
my_fread( buffer, 1, data_size, src );
my_fwrite( buffer, 1, data_size, dst );
}
catch(
boost::exception & x )
{
if( boost::shared_ptr<boost::weak_ptr<FILE> const> f=boost::get_error_info<file_stream_info>(x) )
if( boost::shared_ptr<FILE> fs = f->lock() )
{
if( fs==src )
x << file_name_info(src_file_name);
else if( fs==dst )
x << file_name_info(dst_file_name);
}
x <<
file_name_src_info(src_file_name) <<
file_name_dst_info(dst_file_name);
throw;
}
}
void
dump_copy_info( boost::exception const & x )
{
if( boost::shared_ptr<std::string const> src = boost::get_error_info<file_name_src_info>(x) )
std::cout << "Source file name: " << *src << "\n";
if( boost::shared_ptr<std::string const> dst = boost::get_error_info<file_name_dst_info>(x) )
std::cout << "Destination file name: " << *dst << "\n";
}
void
dump_file_info( boost::exception const & x )
{
if( boost::shared_ptr<std::string const> fn = boost::get_error_info<file_name_info>(x) )
std::cout << "Source file name: " << *fn << "\n";
}
void
dump_clib_info( boost::exception const & x )
{
if( boost::shared_ptr<int const> err=boost::get_error_info<errno_info>(x) )
std::cout << "OS error: " << *err << "\n";
if( boost::shared_ptr<std::string const> fn=boost::get_error_info<function_info>(x) )
std::cout << "Failed function: " << *fn << "\n";
}
void
dump_all_info( boost::exception const & x )
{
std::cout << "-------------------------------------------------\n";
dump_copy_info(x);
dump_file_info(x);
dump_clib_info(x);
std::cout << "\nOutput from diagnostic_information():\n";
std::cout << x.diagnostic_information();
}
int
main()
{
try
{
create_data( "tmp1.txt" );
copy_data( "tmp1.txt", "tmp2.txt" ); //This should succeed.
reset_file( "tmp1.txt" ); //Creates empty file.
try
{
copy_data( "tmp1.txt", "tmp2.txt" ); //This should fail, tmp1.txt is empty.
}
catch(
read_error & x )
{
std::cout << "\nCaught 'read_error' exception.\n";
dump_all_info(x);
}
remove( "tmp1.txt" );
remove( "tmp2.txt" );
try
{
copy_data( "tmp1.txt", "tmp2.txt" ); //This should fail, tmp1.txt does not exist.
}
catch(
open_error & x )
{
std::cout << "\nCaught 'open_error' exception.\n";
dump_all_info(x);
}
}
catch(
boost::exception & x )
{
std::cout << "\nCaught unexpected boost::exception!\n";
dump_all_info(x);
}
}

31
example/info_tuple.cpp Normal file
View File

@ -0,0 +1,31 @@
//Copyright (c) 2006-2008 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)
//This example shows how boost::error_info_group can be used to bundle
//the name of the function that fails together with the reported errno.
#include <boost/exception/info_tuple.hpp>
#include <boost/shared_ptr.hpp>
#include <stdio.h>
#include <string>
#include <errno.h>
typedef boost::error_info<struct tag_file_name,std::string> file_name_info;
typedef boost::error_info<struct tag_function,char const *> function_info;
typedef boost::error_info<struct tag_errno,int> errno_info;
typedef boost::tuple<function_info,errno_info> clib_failure;
class file_open_error: public boost::exception { };
boost::shared_ptr<FILE>
file_open( char const * name, char const * mode )
{
if( FILE * f=fopen(name,mode) )
return boost::shared_ptr<FILE>(f,fclose);
else
throw file_open_error() <<
file_name_info(name) <<
clib_failure("fopen",errno);
}

25
example/logging.cpp Normal file
View File

@ -0,0 +1,25 @@
//Copyright (c) 2006-2008 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)
//This example shows to print all data contained in a boost::exception.
#include <boost/exception.hpp>
#include <iostream>
void f(); //throws unknown types that derive from boost::exception.
void
g()
{
try
{
f();
}
catch(
boost::exception & e )
{
std::cerr << e.diagnostic_information();
}
}