Exceptions in @nogc code

deadalnix via Digitalmars-d digitalmars-d at puremagic.com
Sat Apr 1 07:54:21 PDT 2017


On Saturday, 1 April 2017 at 13:34:58 UTC, Andrei Alexandrescu 
wrote:
> Walter and I discussed the following promising setup:
>
> Use "throw new scope Exception" from @nogc code. That will 
> cause the exception to be allocated in a special stack-like 
> region.
>
> If the catching code uses "catch (scope Exception obj)", then a 
> reference to the exception thus created will be passed to 
> catch. At the end of the catch block there's no outstanding 
> reference to "obj" so it will be freed. All @nogc code must use 
> this form of catch.
>
> If the catching code uses "catch (Exception obj)", the 
> exception is cloned on the gc heap and then freed.
>
> Finally, if an exception is thrown with "throw new Exception" 
> it can be caught with "catch (scope Exception obj)" by copying 
> the exception from the heap into the special region, and then 
> freeing the exception on the heap.
>
> Such a scheme preserves backward compatibility and leverages 
> the work done on "scope".
>
>
> Andrei

I'll repeat myself, even if I don't believe it'll be listened to 
at this point.

The problem you want to address is not GC allocations, it is GC 
collection cycles. If everything is freed, then there is no GC 
problem. not only this, but this is the only way GC and nogc code 
will interact with each others.

As long as a memory allocation has an owner the compiler can 
track, it can be freed explicitly, and, when it cannot, the 
compiler transfer ownership to the GC, which is illegal in @nogc 
code.

Transfering the ownership to the unwind handler when doing:

throw new FooException();

Is not rocket science and doesn't need any new language addition.

Now onto to scope. Scope essentially means that you are going to 
use some object without taking ownership of it. Indeed, in case 
of catch(Exception e) the language has to transfers the ownership 
of the Exception to the GC, which is the thing that should be 
illegal (not throwing). catch(scope Exception e) would work both 
with GC owned and runtime owned exception, and, because the 
runtime know what's up, it can explicitly free the exception when 
it exit the catch block (there is already a runtime call for 
that), in the case it owns it.

It doesn't need any kind of throw new scope Exception, and was 
proposed, literally, years ago during discussion around DIP25 and 
alike.

I urge you to reconsider the proposal that were made at the time. 
They solve all the problems you are discovering now, and more. 
And, while more complex that DIP25 alone, considering 
DIP25+DIP1000+this thing+the RC object thing, you are already in 
the zone where the "simple" approach is not so simple already.

Things are unfolding exactly as predicted at the time. Ad hoc 
solutions to various problems are proposed one by one and the 
overall complexity is growing much larger than initially proposed 
solutions.



More information about the Digitalmars-d mailing list