forked from boostorg/exception
non-intrusive exception_ptr support for msvc 7.1 and 8.0 (for now) thanks Anthony Williams
[SVN r65159]
This commit is contained in:
11
build/Jamfile.v2
Normal file
11
build/Jamfile.v2
Normal file
@ -0,0 +1,11 @@
|
||||
# Boost Exception Library build Jamfile
|
||||
#
|
||||
# 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)
|
||||
|
||||
lib boost_exception ;
|
||||
lib boost_exception : ../src/clone_current_exception_msvc.cpp : <toolset>msvc ;
|
||||
|
||||
boost-install boost_exception ;
|
44
include/boost/exception/detail/clone_current_exception.hpp
Normal file
44
include/boost/exception/detail/clone_current_exception.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
//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)
|
||||
|
||||
#ifndef UUID_81522C0EB56511DFAB613DB0DFD72085
|
||||
#define UUID_81522C0EB56511DFAB613DB0DFD72085
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
#error This header requires exception handling to be enabled.
|
||||
#endif
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
namespace
|
||||
clone_current_exception_result
|
||||
{
|
||||
int const success=0;
|
||||
int const bad_alloc=1;
|
||||
int const not_supported=2;
|
||||
}
|
||||
|
||||
class clone_base;
|
||||
int clone_current_exception_msvc( clone_base const * & cloned );
|
||||
|
||||
inline
|
||||
int
|
||||
clone_current_exception( clone_base const * & cloned )
|
||||
{
|
||||
#ifdef BOOST_ENABLE_NON_INTRUSIVE_EXCEPTION_PTR
|
||||
#ifdef _MSC_VER
|
||||
return clone_current_exception_msvc(cloned);
|
||||
#endif
|
||||
#endif
|
||||
return clone_current_exception_result::not_supported;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -20,6 +20,7 @@
|
||||
#include <boost/exception/info.hpp>
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <boost/exception/detail/type_info.hpp>
|
||||
#include <boost/exception/detail/clone_current_exception.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <stdexcept>
|
||||
#include <new>
|
||||
@ -244,101 +245,125 @@ boost
|
||||
exception_ptr
|
||||
current_exception_impl()
|
||||
{
|
||||
try
|
||||
exception_detail::clone_base const * e=0;
|
||||
switch(
|
||||
exception_detail::clone_current_exception(e) )
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch(
|
||||
exception_detail::clone_base & e )
|
||||
{
|
||||
return exception_ptr(e.clone());
|
||||
}
|
||||
catch(
|
||||
std::domain_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::invalid_argument & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::length_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::out_of_range & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::logic_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::range_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::overflow_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::underflow_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::ios_base::failure & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::runtime_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::bad_alloc & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
case exception_detail::clone_current_exception_result::
|
||||
success:
|
||||
{
|
||||
BOOST_ASSERT(e!=0);
|
||||
return exception_ptr(e);
|
||||
}
|
||||
case exception_detail::clone_current_exception_result::
|
||||
bad_alloc:
|
||||
{
|
||||
BOOST_ASSERT(!e);
|
||||
return exception_detail::exception_ptr_bad_alloc<42>::e;
|
||||
}
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
case exception_detail::clone_current_exception_result::
|
||||
not_supported:
|
||||
{
|
||||
BOOST_ASSERT(!e);
|
||||
try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch(
|
||||
exception_detail::clone_base & e )
|
||||
{
|
||||
return exception_ptr(e.clone());
|
||||
}
|
||||
catch(
|
||||
std::domain_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::invalid_argument & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::length_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::out_of_range & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::logic_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::range_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::overflow_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::underflow_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::ios_base::failure & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::runtime_error & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::bad_alloc & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
#ifndef BOOST_NO_TYPEID
|
||||
catch(
|
||||
std::bad_cast & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::bad_typeid & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::bad_cast & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::bad_typeid & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
#endif
|
||||
catch(
|
||||
std::bad_exception & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::exception & e )
|
||||
{
|
||||
return exception_detail::current_exception_unknown_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
boost::exception & e )
|
||||
{
|
||||
return exception_detail::current_exception_unknown_boost_exception(e);
|
||||
}
|
||||
catch(
|
||||
... )
|
||||
{
|
||||
return exception_detail::current_exception_unknown_exception();
|
||||
catch(
|
||||
std::bad_exception & e )
|
||||
{
|
||||
return exception_detail::current_exception_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
std::exception & e )
|
||||
{
|
||||
return exception_detail::current_exception_unknown_std_exception(e);
|
||||
}
|
||||
catch(
|
||||
boost::exception & e )
|
||||
{
|
||||
return exception_detail::current_exception_unknown_boost_exception(e);
|
||||
}
|
||||
catch(
|
||||
... )
|
||||
{
|
||||
return exception_detail::current_exception_unknown_exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -348,7 +373,6 @@ boost
|
||||
current_exception()
|
||||
{
|
||||
exception_ptr ret;
|
||||
BOOST_ASSERT(!ret);
|
||||
try
|
||||
{
|
||||
ret=exception_detail::current_exception_impl();
|
||||
|
525
src/clone_current_exception_msvc.cpp
Normal file
525
src/clone_current_exception_msvc.cpp
Normal file
@ -0,0 +1,525 @@
|
||||
//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)
|
||||
|
||||
//Based on an exception_ptr implementation by Anthony Williams.
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
#error This file requires exception handling to be enabled.
|
||||
#endif
|
||||
|
||||
#include <boost/exception/detail/clone_current_exception.hpp>
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
unsigned const exception_maximum_parameters=15;
|
||||
unsigned const exception_noncontinuable=1;
|
||||
|
||||
#if _MSC_VER==1310
|
||||
int const exception_info_offset=0x74;
|
||||
#elif _MSC_VER==1400
|
||||
int const exception_info_offset=0x80;
|
||||
#else
|
||||
int const exception_info_offset=-1;
|
||||
#endif
|
||||
|
||||
struct
|
||||
exception_record
|
||||
{
|
||||
unsigned long ExceptionCode;
|
||||
unsigned long ExceptionFlags;
|
||||
exception_record * ExceptionRecord;
|
||||
void * ExceptionAddress;
|
||||
unsigned long NumberParameters;
|
||||
ULONG_PTR ExceptionInformation[exception_maximum_parameters];
|
||||
};
|
||||
|
||||
struct
|
||||
exception_pointers
|
||||
{
|
||||
exception_record * ExceptionRecord;
|
||||
void * ContextRecord;
|
||||
};
|
||||
|
||||
unsigned const cpp_exception_code=0xE06D7363;
|
||||
unsigned const cpp_exception_magic_flag=0x19930520;
|
||||
unsigned const cpp_exception_parameter_count=3;
|
||||
|
||||
struct
|
||||
dummy_exception_type
|
||||
{
|
||||
};
|
||||
|
||||
typedef int(dummy_exception_type::*normal_copy_constructor_ptr)(void * src);
|
||||
typedef int(dummy_exception_type::*copy_constructor_with_virtual_base_ptr)(void * src,void * dest);
|
||||
typedef void (dummy_exception_type::*destructor_ptr)();
|
||||
|
||||
union
|
||||
cpp_copy_constructor
|
||||
{
|
||||
normal_copy_constructor_ptr normal_copy_constructor;
|
||||
copy_constructor_with_virtual_base_ptr copy_constructor_with_virtual_base;
|
||||
};
|
||||
|
||||
enum
|
||||
cpp_type_flags
|
||||
{
|
||||
class_is_simple_type=1,
|
||||
class_has_virtual_base=4
|
||||
};
|
||||
|
||||
struct cpp_type_info
|
||||
{
|
||||
unsigned flags;
|
||||
void const * type_info; //std::type_info * type_info;
|
||||
int this_offset;
|
||||
int vbase_descr;
|
||||
int vbase_offset;
|
||||
unsigned long size;
|
||||
cpp_copy_constructor copy_constructor;
|
||||
};
|
||||
|
||||
struct
|
||||
cpp_type_info_table
|
||||
{
|
||||
unsigned count;
|
||||
const cpp_type_info * info[1];
|
||||
};
|
||||
|
||||
struct
|
||||
cpp_exception_type
|
||||
{
|
||||
unsigned flags;
|
||||
destructor_ptr destructor;
|
||||
void(*custom_handler)();
|
||||
cpp_type_info_table const * type_info_table;
|
||||
};
|
||||
|
||||
struct
|
||||
exception_object_deleter
|
||||
{
|
||||
cpp_exception_type const * exception_type_;
|
||||
|
||||
exception_object_deleter( cpp_exception_type const * exception_type ):
|
||||
exception_type_(exception_type)
|
||||
{
|
||||
BOOST_ASSERT(exception_type_!=0);
|
||||
}
|
||||
|
||||
void
|
||||
operator()( void * exception_object )
|
||||
{
|
||||
BOOST_ASSERT(exception_object!=0);
|
||||
dummy_exception_type * dummy_exception_ptr=reinterpret_cast<dummy_exception_type *>(exception_object);
|
||||
(dummy_exception_ptr->*(exception_type_->destructor))();
|
||||
free(exception_object);
|
||||
}
|
||||
};
|
||||
|
||||
boost::shared_ptr<void>
|
||||
copy_msvc_exception( void * source_object, cpp_exception_type const * exception_type )
|
||||
{
|
||||
void * exception_object = malloc(exception_type->type_info_table->info[0]->size);
|
||||
if( !exception_object )
|
||||
throw std::bad_alloc();
|
||||
cpp_type_info const * type = exception_type->type_info_table->info[0];
|
||||
if( !(type->flags & class_is_simple_type) && type->copy_constructor.normal_copy_constructor )
|
||||
{
|
||||
dummy_exception_type * dummy_exception_ptr = reinterpret_cast<dummy_exception_type *>(exception_object);
|
||||
if( type->flags & class_has_virtual_base )
|
||||
(dummy_exception_ptr->*(type->copy_constructor.copy_constructor_with_virtual_base))(source_object,exception_object);
|
||||
else
|
||||
(dummy_exception_ptr->*(type->copy_constructor.normal_copy_constructor))(source_object);
|
||||
}
|
||||
else
|
||||
memmove(exception_object,source_object,type->size);
|
||||
return boost::shared_ptr<void>(exception_object,exception_object_deleter(exception_type));
|
||||
}
|
||||
|
||||
class
|
||||
cloned_exception:
|
||||
public boost::exception_detail::clone_base
|
||||
{
|
||||
cloned_exception( cloned_exception const & );
|
||||
cloned_exception & operator=( cloned_exception const & );
|
||||
|
||||
cpp_exception_type const * exception_type_;
|
||||
boost::shared_ptr<void> exception_object_;
|
||||
|
||||
public:
|
||||
|
||||
cloned_exception( void * source_object, cpp_exception_type const * exception_type ):
|
||||
exception_type_(exception_type),
|
||||
exception_object_(copy_msvc_exception(source_object,exception_type_))
|
||||
{
|
||||
}
|
||||
|
||||
~cloned_exception() throw()
|
||||
{
|
||||
}
|
||||
|
||||
boost::exception_detail::clone_base const *
|
||||
clone() const
|
||||
{
|
||||
return new cloned_exception(exception_object_.get(),exception_type_);
|
||||
}
|
||||
|
||||
void
|
||||
rethrow() const
|
||||
{
|
||||
boost::shared_ptr<void const> clone=copy_msvc_exception(exception_object_.get(),exception_type_);
|
||||
ULONG_PTR args[cpp_exception_parameter_count];
|
||||
args[0]=cpp_exception_magic_flag;
|
||||
args[1]=reinterpret_cast<ULONG_PTR>(clone.get());
|
||||
args[2]=reinterpret_cast<ULONG_PTR>(exception_type_);
|
||||
RaiseException(cpp_exception_code,EXCEPTION_NONCONTINUABLE,cpp_exception_parameter_count,args);
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
is_cpp_exception( EXCEPTION_RECORD * record )
|
||||
{
|
||||
return record &&
|
||||
(record->ExceptionCode==cpp_exception_code) &&
|
||||
(record->NumberParameters==cpp_exception_parameter_count) &&
|
||||
(record->ExceptionInformation[0]==cpp_exception_magic_flag);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
exception_cloning_filter( boost::exception_detail::clone_base const * * ptr, void * info_ )
|
||||
{
|
||||
BOOST_ASSERT(ptr!=0);
|
||||
BOOST_ASSERT(!*ptr);
|
||||
BOOST_ASSERT(info_!=0);
|
||||
EXCEPTION_POINTERS * info=reinterpret_cast<EXCEPTION_POINTERS *>(info_);
|
||||
EXCEPTION_RECORD * record=info->ExceptionRecord;
|
||||
if( is_cpp_exception(record) )
|
||||
{
|
||||
if( !record->ExceptionInformation[2] )
|
||||
{
|
||||
record = *reinterpret_cast<EXCEPTION_RECORD * *>(reinterpret_cast<char *>(_errno())+exception_info_offset);
|
||||
}
|
||||
if( is_cpp_exception(record) && record->ExceptionInformation[2] )
|
||||
try
|
||||
{
|
||||
*ptr = new cloned_exception(
|
||||
reinterpret_cast<void *>(record->ExceptionInformation[1]),
|
||||
reinterpret_cast<cpp_exception_type const *>(record->ExceptionInformation[2]));
|
||||
}
|
||||
catch(
|
||||
std::bad_alloc & )
|
||||
{
|
||||
BOOST_ASSERT(!*ptr);
|
||||
}
|
||||
catch(
|
||||
... )
|
||||
{
|
||||
BOOST_ASSERT(0);
|
||||
}
|
||||
}
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
int
|
||||
clone_current_exception_msvc( clone_base const * & cloned )
|
||||
{
|
||||
BOOST_ASSERT(!cloned);
|
||||
if( exception_info_offset<0 )
|
||||
return clone_current_exception_result::not_supported;
|
||||
clone_base const * res=0;
|
||||
__try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
__except(exception_cloning_filter(&res,GetExceptionInformation()))
|
||||
{
|
||||
}
|
||||
if( !res )
|
||||
return clone_current_exception_result::bad_alloc;
|
||||
else
|
||||
{
|
||||
cloned=res;
|
||||
return clone_current_exception_result::success;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
//This is the original Anthony Williams implementation
|
||||
#ifndef EXCEPTION_PTR_HPP
|
||||
#define EXCEPTION_PTR_HPP
|
||||
#include <typeinfo>
|
||||
#include "thread_heap_alloc.hpp"
|
||||
#include <string.h>
|
||||
#include "thread_primitives.hpp"
|
||||
#include <excpt.h>
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
namespace
|
||||
win32
|
||||
{
|
||||
unsigned const exception_maximum_parameters=15;
|
||||
unsigned const exception_noncontinuable=1;
|
||||
|
||||
struct
|
||||
exception_record
|
||||
{
|
||||
unsigned long ExceptionCode;
|
||||
unsigned long ExceptionFlags;
|
||||
exception_record *ExceptionRecord;
|
||||
void* ExceptionAddress;
|
||||
unsigned long NumberParameters;
|
||||
ulong_ptr ExceptionInformation[exception_maximum_parameters];
|
||||
};
|
||||
|
||||
struct
|
||||
exception_pointers
|
||||
{
|
||||
exception_record* ExceptionRecord;
|
||||
void* ContextRecord;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) void __stdcall RaiseException(unsigned long,unsigned long,unsigned long,ulong_ptr*);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned const cpp_exception_code=0xE06D7363;
|
||||
unsigned const cpp_exception_magic_flag=0x19930520;
|
||||
unsigned const cpp_exception_parameter_count=3;
|
||||
|
||||
struct
|
||||
dummy_exception_type
|
||||
{
|
||||
};
|
||||
|
||||
typedef int(dummy_exception_type::*normal_copy_constructor_ptr)(void * src);
|
||||
typedef int(dummy_exception_type::*copy_constructor_with_virtual_base_ptr)(void * src,void * dest);
|
||||
typedef void (dummy_exception_type::*destructor_ptr)();
|
||||
|
||||
union
|
||||
cpp_copy_constructor
|
||||
{
|
||||
normal_copy_constructor_ptr normal_copy_constructor;
|
||||
copy_constructor_with_virtual_base_ptr copy_constructor_with_virtual_base;
|
||||
};
|
||||
|
||||
enum
|
||||
cpp_type_flags
|
||||
{
|
||||
class_is_simple_type=1,
|
||||
class_has_virtual_base=4
|
||||
};
|
||||
|
||||
struct cpp_type_info
|
||||
{
|
||||
unsigned flags;
|
||||
void const * type_info; //std::type_info * type_info;
|
||||
int this_offset;
|
||||
int vbase_descr;
|
||||
int vbase_offset;
|
||||
unsigned long size;
|
||||
cpp_copy_constructor copy_constructor;
|
||||
};
|
||||
|
||||
struct
|
||||
cpp_type_info_table
|
||||
{
|
||||
unsigned count;
|
||||
const cpp_type_info * info[1];
|
||||
};
|
||||
|
||||
struct
|
||||
cpp_exception_type
|
||||
{
|
||||
unsigned flags;
|
||||
destructor_ptr destructor;
|
||||
void(*custom_handler)();
|
||||
cpp_type_info_table const * type_info_table;
|
||||
};
|
||||
|
||||
class
|
||||
msvc_cloned_exception:
|
||||
clone_base
|
||||
{
|
||||
cpp_exception_type const * exception_type;
|
||||
void * exception_object;
|
||||
bool run_destructor;
|
||||
|
||||
void
|
||||
copy( void * source_object )
|
||||
{
|
||||
BOOST_ASSERT(!exception_object);
|
||||
exception_object = malloc(exception_type->type_info_table->info[0]->size);
|
||||
if( exception_object )
|
||||
{
|
||||
cpp_type_info const * type = exception_type->type_info_table->info[0];
|
||||
if( !(type->flags & class_is_simple_type) && type->copy_constructor.normal_copy_constructor )
|
||||
{
|
||||
dummy_exception_type * dummy_exception_ptr = reinterpret_cast<dummy_exception_type *>(exception_object);
|
||||
if( type->flags & class_has_virtual_base )
|
||||
(dummy_exception_ptr->*(type->copy_constructor.copy_constructor_with_virtual_base))(source_object,exception_object);
|
||||
else
|
||||
(dummy_exception_ptr->*(type->copy_constructor.normal_copy_constructor))(source_object);
|
||||
}
|
||||
else
|
||||
memmove(exception_object,source_object,type->size);
|
||||
run_destructor=true;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
msvc_cloned_exception( void * source_object, cpp_exception_type const * exception_type_ ):
|
||||
exception_type(exception_type_),
|
||||
exception_object(0),
|
||||
run_destructor(false)
|
||||
{
|
||||
copy(source_object);
|
||||
}
|
||||
|
||||
msvc_cloned_exception( msvc_cloned_exception const & other ):
|
||||
exception_type(other.exception_type),
|
||||
exception_object(0),
|
||||
run_destructor(false)
|
||||
{
|
||||
copy(other.exception_object);
|
||||
}
|
||||
|
||||
~msvc_cloned_exception()
|
||||
{
|
||||
if( exception_object )
|
||||
{
|
||||
if( run_destructor )
|
||||
{
|
||||
dummy_exception_type * dummy_exception_ptr=reinterpret_cast<dummy_exception_type *>(exception_object);
|
||||
(dummy_exception_ptr->*(exception_type->destructor))();
|
||||
}
|
||||
free(exception_object);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rethrow()
|
||||
{
|
||||
msvc_cloned_exception temp(*this);
|
||||
|
||||
detail::win32::ulong_ptr args[detail::cpp_exception_parameter_count];
|
||||
args[0]=detail::cpp_exception_magic_flag;
|
||||
args[1]=reinterpret_cast<detail::win32::ulong_ptr>(temp.exception_object);
|
||||
args[2]=reinterpret_cast<detail::win32::ulong_ptr>(temp.exception_type);
|
||||
|
||||
temp.run_destructor=false;
|
||||
|
||||
detail::win32::RaiseException(detail::cpp_exception_code,detail::win32::exception_noncontinuable,detail::cpp_exception_parameter_count,args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
typedef boost::intrusive_ptr<detail::msvc_cloned_exception> exception_ptr;
|
||||
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
extern "C" int * _errno();
|
||||
|
||||
bool
|
||||
is_cpp_exception( win32::exception_record * record )
|
||||
{
|
||||
return record &&
|
||||
(record->ExceptionCode==cpp_exception_code) &&
|
||||
(record->NumberParameters==cpp_exception_parameter_count) &&
|
||||
(record->ExceptionInformation[0]==cpp_exception_magic_flag);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
exception_cloning_filter( exception_ptr * ptr, void * info_ )
|
||||
{
|
||||
win32::exception_pointers * info=reinterpret_cast<win32::exception_pointers *>(info_);
|
||||
win32::exception_record * record=info->ExceptionRecord;
|
||||
if( is_cpp_exception(record) )
|
||||
{
|
||||
if( !record->ExceptionInformation[2] )
|
||||
{
|
||||
#if _MSC_VER==1310
|
||||
unsigned const exception_info_offset=0x74;
|
||||
#elif _MSC_VER==1400
|
||||
unsigned const exception_info_offset=0x80;
|
||||
#endif
|
||||
record = *reinterpret_cast<win32::exception_record * *>(reinterpret_cast<char *>(_errno())+exception_info_offset);
|
||||
}
|
||||
if( is_cpp_exception(record) && record->ExceptionInformation[2] )
|
||||
*ptr = detail::heap_new<msvc_cloned_exception>(reinterpret_cast<void *>(record->ExceptionInformation[1]),
|
||||
reinterpret_cast<cpp_exception_type const *>(record->ExceptionInformation[2]));
|
||||
}
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
void
|
||||
clone_current_exception( exception_ptr * res )
|
||||
{
|
||||
__try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
__except(exception_cloning_filter(res,GetExceptionInformation()))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
exception_ptr
|
||||
current_exception()
|
||||
{
|
||||
exception_ptr res;
|
||||
clone_current_exception(&res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
rethrow_exception(exception_ptr p)
|
||||
{
|
||||
if(p)
|
||||
p->rethrow();
|
||||
else
|
||||
throw "no exception stored";
|
||||
}
|
||||
|
||||
template<class E>
|
||||
exception_ptr
|
||||
copy_exception(E e)
|
||||
{
|
||||
try
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return current_exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
@ -7,7 +7,7 @@
|
||||
|
||||
import testing ;
|
||||
|
||||
project : requirements <exception-handling>on ;
|
||||
project : requirements <exception-handling>on <define>BOOST_ENABLE_NON_INTRUSIVE_EXCEPTION_PTR ;
|
||||
|
||||
#to_string
|
||||
|
||||
@ -36,7 +36,8 @@ run refcount_ptr_test.cpp ;
|
||||
run current_exception_cast_test.cpp ;
|
||||
run no_exceptions_test.cpp : : : <exception-handling>off ;
|
||||
run errinfos_test.cpp ;
|
||||
run exception_ptr_test.cpp /boost//thread : : : <threading>multi ;
|
||||
run exception_ptr_test.cpp /boost//thread /boost//exception : : : <threading>multi ;
|
||||
|
||||
compile-fail exception_fail.cpp ;
|
||||
compile-fail throw_exception_fail.cpp ;
|
||||
compile-fail error_info_const_fail.cpp ;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/detail/atomic_count.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@ -66,7 +67,33 @@ join( thread_handle & t )
|
||||
rethrow_exception(t.err_);
|
||||
}
|
||||
|
||||
struct exc: boost::exception, std::exception { };
|
||||
boost::detail::atomic_count exc_count(0);
|
||||
|
||||
struct
|
||||
exc:
|
||||
virtual boost::exception,
|
||||
virtual std::exception
|
||||
{
|
||||
exc()
|
||||
{
|
||||
++exc_count;
|
||||
}
|
||||
|
||||
exc( exc const & )
|
||||
{
|
||||
++exc_count;
|
||||
}
|
||||
|
||||
~exc()
|
||||
{
|
||||
--exc_count;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
exc & operator=( exc const & );
|
||||
};
|
||||
|
||||
typedef boost::error_info<struct answer_,int> answer;
|
||||
|
||||
void
|
||||
@ -93,6 +120,7 @@ check( boost::shared_ptr<thread_handle> const & t )
|
||||
int
|
||||
main()
|
||||
{
|
||||
BOOST_TEST(++exc_count==1);
|
||||
try
|
||||
{
|
||||
std::vector< boost::shared_ptr<thread_handle> > threads;
|
||||
@ -109,4 +137,5 @@ main()
|
||||
boost::current_exception_diagnostic_information() << std::endl;
|
||||
return 42;
|
||||
}
|
||||
BOOST_TEST(!--exc_count);
|
||||
}
|
||||
|
Reference in New Issue
Block a user