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