Destructors vs. Finalizers

Moritz Maxeiner via Digitalmars-d digitalmars-d at puremagic.com
Wed Jul 26 02:29:15 PDT 2017


On Wednesday, 26 July 2017 at 02:58:00 UTC, Mike Parker wrote:
> Regarding the issue with `destroy` not being @nogc, I my 
> understanding is it comes down to `rt_finalize` not being 
> @nogc. I haven't dug too deeply into the discussions around it, 
> but I'm wondering if it's possible to separate the concept of 
> destruction from finalization in the implementation?

Possible, yes, and I agree that separating destruction 
(deterministic end of object lifetime) and finalization (GC 
collection caused end of object lifetime) for classes is 
something we should do.

>
> Externally, we can do it with the existing language:
>
> class {
>     ~this() {}     // Finalizer
>
>     ~this @nogc {} // Destructor
> }

As class destructors (in contrast to class finalizers) are then 
called exclusively in a deterministic fashion, there's no reason 
to forbid them from allocating using the GC, so I don't think 
using the @nogc attribute would be appropriate; I would much 
rather see another attribute in the likes of @disable, e.g. 
@deterministic, so
---
~this() {}                    // Finalizer
~this() @nogc {}              // Finalizer
~this @deterministic {}       // Destructor
~this @nogc @deterministic {} // Destructor
}
---


>
> Internally, the runtime will treat each differently. an 
> rt_destruct would call all every __dtor in a hierarchy

As long as finalizers are then not part of __dtor.

> and rt_finalize would be changed to call every __finalizer (a 
> new addition) in a hierarchy.

> When cleaning up, the GC will ensure that all destructors are 
> run where they exist, followed by all finalizers.

Having the GC directly call destructors defeats the point of 
separating them from finalizers in the first place: If a 
destructor should be run on GC finalication, the finalizer must 
manually call the destructor (using e.g. `destroy`).
The GC must *never* call destructors automatically after 
splitting off finalizers, because that would turn destructors 
back into finalizers.

> And destroy would be changed to call rt_destruct instead of 
> rt_finalize.

Yes, that would then be the correct behaviour for `destroy`.


More information about the Digitalmars-d mailing list