sclang: ServerShmInterface - avoid object duplication in deepCopy
[supercollider.git] / external_libraries / boost / libs / exception / src / clone_current_exception_non_intrusive.cpp
blob1710cd74ac067a7666d03092a3ce3fecc781d920
1 //Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
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)
6 //This MSVC-specific cpp file implements non-intrusive cloning of exception objects.
7 //Based on an exception_ptr implementation by Anthony Williams.
9 #ifdef BOOST_NO_EXCEPTIONS
10 #error This file requires exception handling to be enabled.
11 #endif
13 #include <boost/exception/detail/clone_current_exception.hpp>
15 #if defined(BOOST_ENABLE_NON_INTRUSIVE_EXCEPTION_PTR) && defined(_MSC_VER) && defined(_M_IX86) && !defined(_M_X64)
17 //Non-intrusive cloning support implemented below, only for MSVC versions mentioned above.
18 //Thanks Anthony Williams!
20 #include <boost/exception/exception.hpp>
21 #include <boost/shared_ptr.hpp>
22 #ifndef BOOST_NO_RTTI
23 #include <typeinfo>
24 #endif
25 #include <windows.h>
26 #include <malloc.h>
28 namespace
30 unsigned const exception_maximum_parameters=15;
31 unsigned const exception_noncontinuable=1;
33 #if _MSC_VER==1310
34 int const exception_info_offset=0x74;
35 #elif (_MSC_VER==1400 || _MSC_VER==1500)
36 int const exception_info_offset=0x80;
37 #else
38 int const exception_info_offset=-1;
39 #endif
41 struct
42 exception_record
44 unsigned long ExceptionCode;
45 unsigned long ExceptionFlags;
46 exception_record * ExceptionRecord;
47 void * ExceptionAddress;
48 unsigned long NumberParameters;
49 ULONG_PTR ExceptionInformation[exception_maximum_parameters];
52 struct
53 exception_pointers
55 exception_record * ExceptionRecord;
56 void * ContextRecord;
59 unsigned const cpp_exception_code=0xE06D7363;
60 unsigned const cpp_exception_magic_flag=0x19930520;
61 unsigned const cpp_exception_parameter_count=3;
63 struct
64 dummy_exception_type
68 typedef int(dummy_exception_type::*normal_copy_constructor_ptr)(void * src);
69 typedef int(dummy_exception_type::*copy_constructor_with_virtual_base_ptr)(void * src,void * dst);
70 typedef void (dummy_exception_type::*destructor_ptr)();
72 union
73 cpp_copy_constructor
75 normal_copy_constructor_ptr normal_copy_constructor;
76 copy_constructor_with_virtual_base_ptr copy_constructor_with_virtual_base;
79 enum
80 cpp_type_flags
82 class_is_simple_type=1,
83 class_has_virtual_base=4
86 struct
87 cpp_type_info
89 unsigned flags;
90 #ifndef BOOST_NO_RTTI
91 void const * type_info;
92 #else
93 std::type_info * type_info;
94 #endif
95 int this_offset;
96 int vbase_descr;
97 int vbase_offset;
98 unsigned long size;
99 cpp_copy_constructor copy_constructor;
102 struct
103 cpp_type_info_table
105 unsigned count;
106 const cpp_type_info * info[1];
109 struct
110 cpp_exception_type
112 unsigned flags;
113 destructor_ptr destructor;
114 void(*custom_handler)();
115 cpp_type_info_table const * type_info_table;
118 struct
119 exception_object_deleter
121 cpp_exception_type const & et_;
123 exception_object_deleter( cpp_exception_type const & et ):
124 et_(et)
128 void
129 operator()( void * obj )
131 BOOST_ASSERT(obj!=0);
132 dummy_exception_type * dummy_exception_ptr=reinterpret_cast<dummy_exception_type *>(obj);
133 (dummy_exception_ptr->*(et_.destructor))();
134 free(obj);
138 cpp_type_info const &
139 get_cpp_type_info( cpp_exception_type const & et )
141 cpp_type_info const * ti = et.type_info_table->info[0];
142 BOOST_ASSERT(ti!=0);
143 return *ti;
146 void
147 copy_msvc_exception( void * dst, void * src, cpp_type_info const & ti )
149 if( !(ti.flags & class_is_simple_type) && ti.copy_constructor.normal_copy_constructor )
151 dummy_exception_type * dummy_exception_ptr = reinterpret_cast<dummy_exception_type *>(dst);
152 if( ti.flags & class_has_virtual_base )
153 (dummy_exception_ptr->*(ti.copy_constructor.copy_constructor_with_virtual_base))(src,dst);
154 else
155 (dummy_exception_ptr->*(ti.copy_constructor.normal_copy_constructor))(src);
157 else
158 memmove(dst,src,ti.size);
161 boost::shared_ptr<void>
162 clone_msvc_exception( void * src, cpp_exception_type const & et )
164 assert(src!=0);
165 cpp_type_info const & ti=get_cpp_type_info(et);
166 if( void * dst = malloc(ti.size) )
170 copy_msvc_exception(dst,src,ti);
172 catch(
173 ... )
175 free(dst);
176 throw;
178 return boost::shared_ptr<void>(dst,exception_object_deleter(et));
180 else
181 throw std::bad_alloc();
184 class
185 cloned_exception:
186 public boost::exception_detail::clone_base
188 cloned_exception( cloned_exception const & );
189 cloned_exception & operator=( cloned_exception const & );
191 cpp_exception_type const & et_;
192 boost::shared_ptr<void> exc_;
194 public:
196 cloned_exception( void * exc, cpp_exception_type const & et ):
197 et_(et),
198 exc_(clone_msvc_exception(exc,et_))
202 ~cloned_exception() throw()
206 boost::exception_detail::clone_base const *
207 clone() const
209 return new cloned_exception(exc_.get(),et_);
212 void
213 rethrow() const
215 cpp_type_info const & ti=get_cpp_type_info(et_);
216 void * dst = _alloca(ti.size);
217 copy_msvc_exception(dst,exc_.get(),ti);
218 ULONG_PTR args[cpp_exception_parameter_count];
219 args[0]=cpp_exception_magic_flag;
220 args[1]=reinterpret_cast<ULONG_PTR>(dst);
221 args[2]=reinterpret_cast<ULONG_PTR>(&et_);
222 RaiseException(cpp_exception_code,EXCEPTION_NONCONTINUABLE,cpp_exception_parameter_count,args);
226 bool
227 is_cpp_exception( EXCEPTION_RECORD const * record )
229 return record &&
230 (record->ExceptionCode==cpp_exception_code) &&
231 (record->NumberParameters==cpp_exception_parameter_count) &&
232 (record->ExceptionInformation[0]==cpp_exception_magic_flag);
235 unsigned long
236 exception_cloning_filter( int & result, boost::exception_detail::clone_base const * & ptr, void * info_ )
238 BOOST_ASSERT(exception_info_offset>=0);
239 BOOST_ASSERT(info_!=0);
240 EXCEPTION_POINTERS * info=reinterpret_cast<EXCEPTION_POINTERS *>(info_);
241 EXCEPTION_RECORD * record=info->ExceptionRecord;
242 if( is_cpp_exception(record) )
244 if( !record->ExceptionInformation[2] )
245 record = *reinterpret_cast<EXCEPTION_RECORD * *>(reinterpret_cast<char *>(_errno())+exception_info_offset);
246 if( is_cpp_exception(record) && record->ExceptionInformation[2] )
249 ptr = new cloned_exception(
250 reinterpret_cast<void *>(record->ExceptionInformation[1]),
251 *reinterpret_cast<cpp_exception_type const *>(record->ExceptionInformation[2]));
252 result = boost::exception_detail::clone_current_exception_result::success;
254 catch(
255 std::bad_alloc & )
257 result = boost::exception_detail::clone_current_exception_result::bad_alloc;
259 catch(
260 ... )
262 result = boost::exception_detail::clone_current_exception_result::bad_exception;
265 return EXCEPTION_EXECUTE_HANDLER;
269 namespace
270 boost
272 namespace
273 exception_detail
276 clone_current_exception_non_intrusive( clone_base const * & cloned )
278 BOOST_ASSERT(!cloned);
279 int result = clone_current_exception_result::not_supported;
280 if( exception_info_offset>=0 )
282 clone_base const * ptr=0;
283 __try
285 throw;
287 __except(exception_cloning_filter(result,ptr,GetExceptionInformation()))
290 if( result==clone_current_exception_result::success )
291 cloned=ptr;
293 BOOST_ASSERT(result!=clone_current_exception_result::success || cloned);
294 return result;
299 #else
301 //On all other compilers, return clone_current_exception_result::not_supported.
302 //On such platforms, only the intrusive enable_current_exception() cloning will work.
304 #include <boost/config.hpp>
306 namespace
307 boost
309 namespace
310 exception_detail
313 clone_current_exception_non_intrusive( clone_base const * & )
315 return clone_current_exception_result::not_supported;
320 #endif