[cpp-threads] Issue 1369 --- thread safety of std::rethrow_exception
Anthony Williams
anthony at justsoftwaresolutions.co.uk
Tue Nov 16 08:00:37 GMT 2010
On 15/11/10 16:21, Howard Hinnant wrote:
> On Nov 15, 2010, at 10:55 AM, Anthony Williams wrote:
>
>> I appreciate that if the data is not present in code compiled to
>> the C++03 ABI then C++0x code can only depend on C++0x code.
>> However, can't the ABI be made backwards compatible, so it remains
>> compatible with the C++03 ABI **and** is compatible with the new
>> C++0x ABI? This would avoid "doubling the size of the OS". Of
>> course, it depends on the details.
>
> To make this change, I would need to see an implemented
> backwards-compatible Itanium ABI which successfully passed through
> review at cxx-abi-dev at codesourcery.com. I have not personally come
> up with a design which I thought would be implementable and pass such
> a review.
In order to clone exceptions you need two things: the size of the object
to clone (so you can allocate space for the new one), and the ability to
call the copy constructor so you can actually do the copy.
I've looked at the Itanium ABI at
http://www.codesourcery.com/public/cxx-abi/abi.html to try and see where
this could be done.
One option I see would be to add a new class derived from
abi::__class_type_info that had virtual member functions for the size
and copy constructor:
class __copyable_class_type_info: public __class_type_info
{
public:
size_t __object_size;
virtual void __copy_construct(void* __source, void* __dest)=0;
};
You would need similar derived classes for __si_class_type_info and
__vmi_class_type_info.
Because these are derived classes, they shouldn't affect the existing
ABI structures. The size of non-class types can be determined from the
type directly, since all pointers have the same size and fundamental
types have a fixed size under the ABI. Such types can also be copied
with memcpy().
rethrow_exception can then check the type_info pointed to by the
exceptionType member of the __cxa_exception header, and either
(i) copy the exception with memcpy (because it's a fundamental type or
pointer)
(ii) throw bad_alloc because this is an old ABI exception and cannot
therefore be copied
(iii) dynamic_cast the type info to __copyable_class_type_info use the
new __object_size and __copy_construct virtual functions to clone the
exception
A second object is to add the size and copy construction functions to
the __cxa_exception header. The ABI says "By convention, a
__cxa_exception pointer points at the C++ object representing the
exception being thrown, immediately following the header. The header
structure is accessed at a negative offset from the __cxa_exception
pointer. This layout allows consistent treatment of exception objects
from different languages (or different implementations of the same
language), and allows future extensions of the header structure while
maintaining binary compatibility. "
We could therefore take advantage of this leeway to "extend the header
structure while maintaining binary compatibility" to add the new size
and copy construction members.
What do you think?
>> Is there nothing else in C++0x that breaks the ABI? There are
>> certainly a lot of language facilities that are not in C++03. Is
>> Apple going to oppose any change that breaks the ABI?
>
> Apple currently has a migration strategy: For all "high level" parts
> of C++0x, we will version the ABI using inline namespaces. This
> allows for separate C++03 and C++0x ABI's to be shipped on the same
> OS and the only doubling is in the OS-supplied dyld of the std::lib
> (we will ship C++03 and C++0x std::libs). Applications and dyld's can
> migrate or not. If two dyld's using the different ABI's are used in
> the same application, they will either work (because they share the
> same ABI, or they do not expose ABI-versioned std::lib components in
> their interface), or they will fail at link time. std::string is an
> obvious example that will be ABI-incompatible (ABI-versioned) between
> C++03 and C++0x.
>
> However "low level" parts of the std::lib are not versioned, and will
> be ABI compatible across C++03 and C++0x. These low level parts
> include operator new/delete, so that memory allocated from the C++03
> std::lib can be deallocated by the C++0x lib, and vice-versa. And
> exception throwing/catching is also ABI compatible across the C++03
> and C++0x. This is done so that an application can link to dyld1 and
> dyld2, and not have to care which std::lib its dyld's are using. As
> exceptions bubble up from the dyld's, the application does not need
> to concern itself if these are C++03 or C++0x exceptions. Even the
> std-defined exception classes are ABI compatible across C++03 and
> C++0x.
Thank you for the info; that makes sense.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++0x thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
More information about the cpp-threads
mailing list