Exceptions in @nogc code

deadalnix via Digitalmars-d digitalmars-d at puremagic.com
Sun Apr 2 14:27:07 PDT 2017


On Saturday, 1 April 2017 at 22:08:27 UTC, Walter Bright wrote:
> On 4/1/2017 7:54 AM, deadalnix wrote:
>> It doesn't need any kind of throw new scope Exception, and was 
>> proposed,
>> literally, years ago during discussion around DIP25 and alike.
>
> A link to that proposal would be appreciated.

The forum search isn't returning anything useful so I'm not sure 
how to get that link. However, it goes roughly as follow. Note 
that it's a solution to solve DIP25+DIP1000+RC+nogc exception and 
a sludge of other issues, and that comparing it to any of these 
independently will yield the obvious it is more complex. But that 
wouldn't be a fair comparison, as one should compare it to the 
sum of all these proposals, not to any of them independently.

The compiler already has the nothing of "unique" and use it to 
some extent, for instance to optimize pure functions and allow to 
do some magic with new allocations. The proposal relax and extend 
the concept of unique and make it explicit, via the type 
qualifier 'owned'. Going into the details here would take too 
long, so i'll just reference this paper ( 
https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/msr-tr-2012-79.pdf ) for detailed work in C# about this. This is easily applicable to D.

The GC heap is currently composed of several islands. One island 
per thread + one shared island + one immutable island. The owned 
qualifier essentially enable to have more island, and each 
indirection tagged owned is a jump to another island. What's 
currently understood as "unique" by the compiler can be 
considered owned, which includes values returned from strongly 
pure functions and fresh new allocations.

Let's see how that apply to exceptions and the GC:
  - If a T is thrown, the runtime assumes GC ownership of the 
exception.
  - If a owned(T) is thrown, the runtime takes ownership of the 
exception (and of the graph of objects reachable from the 
exception.

When catching:
  - If the catch isn't scope or owned, then is is a "consume" 
operation. If the runtime had ownership of the exception, it 
transfers it to the GC.
  - If the catch is scope, then the runtime keeps ownership of the 
Exception. Exiting the catch block is going to destroy the 
Exception and the whole island associated with it.
  - If the catch is owned, then the ownership of the Exception is 
transferred to the catch block. It is then either transferred 
back to the runtime in case of rethrow, or consumed/destroyed 
depending on what the catch block is doing with it.

The only operations that need to be disallowed in nogc code are 
consuming owned such as their ownership is transferred to the GC, 
in this case, catch blocks which aren't owned or scope.

This mechanism solves numerous other issues. Notably and non 
exhaustively:
  - General reduction in the amount of garbage created.
  - Ability to transfers ownership of data between thread safely 
(without cast to/from shared).
  - Safe std.parralelism .
  - Elaborate construction of shared and immutable objects.
  - Safe reference counting.
  - Safe "arena" style reference counting such as: 
https://www.youtube.com/watch?v=JfmTagWcqoE
  - Solves problems with collection ownership and alike.



More information about the Digitalmars-d mailing list