Date: Thu, 29 Feb 2024 11:10:28 +0000
On Thu, Feb 29, 2024 at 10:53 AM Jan Schultke wrote:
>
> I agree with Jonathan; this does not belong in the standard. For
> starters, it makes optimizations impossible such as eliminating:
>
> > try {
> > throw 0;
> > } catch (...) {}
I wasn't aware of any compilers doing this. Nor have I ever seen any
real code that looks like this.
> While compilers aren't very good at eliminating unnecessary try/catch,
Compiler vendors probably have bigger fish to fry, because there
aren't many programmers out there writing redundant try-catch's
(especially in a context where performance is critical).
> yet they should be allowed to do it. If you make it so that throwing
> inevitably calls a global handler, this optimization becomes entirely
> impossible, since any throw might have observable side effects.
>
> I'm also confident that given enough time (perhaps not C++26, but
> eventually) constexpr exception handling will be a thing. It's unclear
> how that would work when there is global mutable state in the form of
> a throw handler. Global mutable state doesn't really exist in constant
> expressions.
Well we haven't got constexpr/consteval exception handling yet, so for
the timebeing I'll put this feature forward. I'm reaching here . . .
but if we're gonna have constexpr exception handling then maybe have
constexpr 'throw handlers' as well.
> It's irrelevant how quickly you could hack together something that
> works in a specific implementation.
If we are to consider how much hassle it would be for compiler vendors
to implement a new feature, then I think it's good to point out that
one working implementation only took an hour to code in once source
file on GodBolt.
> This doesn't belong in the C++ standard.
The only argument I can see here against it being in the Standard is
that the compiler won't be able to optimise away no-op try-catch
blocks. I can't recall in all my life having ever seen a superfluous
try-catch block that doesn't do anything (except of course in mock-up
code for debugging).
By the way in my previous GodBolt, I had the following code:
[[noreturn]] void __cxa_throw(void *p, void *pti, void (*pf)(void *))
{
if ( std::detail_current_throw_handler.load() )
{
static thread_local bool already_entered = false;
if ( already_entered ) std::terminate();
already_entered = true;
std::detail_current_throw_handler.load()(p,
*static_cast<std::type_info*>(pti));
already_entered = false;
}
original_cxa_throw(p,pti,pf);
std::terminate();
}
but I can see the race condition that would occur if another thread
were to change the 'throw handler' around about the time that the
current 'throw handler' throws an exception, so that should be:
[[noreturn]] void __cxa_throw(void *p, void *pti, void (*pf)(void *))
{
static thread_local bool already_entered = false;
if ( already_entered ) std::terminate();
if ( std::detail_current_throw_handler.load() )
{
already_entered = true;
std::detail_current_throw_handler.load()(p,
*static_cast<std::type_info*>(pti));
already_entered = false;
}
original_cxa_throw(p,pti,pf);
std::terminate();
}
>
> I agree with Jonathan; this does not belong in the standard. For
> starters, it makes optimizations impossible such as eliminating:
>
> > try {
> > throw 0;
> > } catch (...) {}
I wasn't aware of any compilers doing this. Nor have I ever seen any
real code that looks like this.
> While compilers aren't very good at eliminating unnecessary try/catch,
Compiler vendors probably have bigger fish to fry, because there
aren't many programmers out there writing redundant try-catch's
(especially in a context where performance is critical).
> yet they should be allowed to do it. If you make it so that throwing
> inevitably calls a global handler, this optimization becomes entirely
> impossible, since any throw might have observable side effects.
>
> I'm also confident that given enough time (perhaps not C++26, but
> eventually) constexpr exception handling will be a thing. It's unclear
> how that would work when there is global mutable state in the form of
> a throw handler. Global mutable state doesn't really exist in constant
> expressions.
Well we haven't got constexpr/consteval exception handling yet, so for
the timebeing I'll put this feature forward. I'm reaching here . . .
but if we're gonna have constexpr exception handling then maybe have
constexpr 'throw handlers' as well.
> It's irrelevant how quickly you could hack together something that
> works in a specific implementation.
If we are to consider how much hassle it would be for compiler vendors
to implement a new feature, then I think it's good to point out that
one working implementation only took an hour to code in once source
file on GodBolt.
> This doesn't belong in the C++ standard.
The only argument I can see here against it being in the Standard is
that the compiler won't be able to optimise away no-op try-catch
blocks. I can't recall in all my life having ever seen a superfluous
try-catch block that doesn't do anything (except of course in mock-up
code for debugging).
By the way in my previous GodBolt, I had the following code:
[[noreturn]] void __cxa_throw(void *p, void *pti, void (*pf)(void *))
{
if ( std::detail_current_throw_handler.load() )
{
static thread_local bool already_entered = false;
if ( already_entered ) std::terminate();
already_entered = true;
std::detail_current_throw_handler.load()(p,
*static_cast<std::type_info*>(pti));
already_entered = false;
}
original_cxa_throw(p,pti,pf);
std::terminate();
}
but I can see the race condition that would occur if another thread
were to change the 'throw handler' around about the time that the
current 'throw handler' throws an exception, so that should be:
[[noreturn]] void __cxa_throw(void *p, void *pti, void (*pf)(void *))
{
static thread_local bool already_entered = false;
if ( already_entered ) std::terminate();
if ( std::detail_current_throw_handler.load() )
{
already_entered = true;
std::detail_current_throw_handler.load()(p,
*static_cast<std::type_info*>(pti));
already_entered = false;
}
original_cxa_throw(p,pti,pf);
std::terminate();
}
Received on 2024-02-29 11:10:40