Jump to page: 1 24  
Page
Thread overview
Destructors vs. Finalizers
Jul 26, 2017
Mike Parker
Jul 26, 2017
Mike Parker
Jul 26, 2017
Moritz Maxeiner
Jul 26, 2017
Mike Parker
Jul 26, 2017
jmh530
Jul 26, 2017
Daniel Kozak
Jul 26, 2017
Guillaume Piolat
Jul 26, 2017
Mike Parker
Jul 26, 2017
Guillaume Piolat
Jul 26, 2017
Moritz Maxeiner
Jul 26, 2017
Guillaume Piolat
Jul 26, 2017
Guillaume Piolat
Jul 27, 2017
Guillaume Piolat
Jul 27, 2017
Dgame
Jul 27, 2017
Guillaume Piolat
Jul 26, 2017
jmh530
Jul 26, 2017
Guillaume Piolat
Jul 26, 2017
Mike Parker
Jul 26, 2017
Dgame
Jul 26, 2017
Moritz Maxeiner
Jul 26, 2017
Dgame
Jul 26, 2017
Moritz Maxeiner
Jul 26, 2017
Dgame
Jul 26, 2017
Moritz Maxeiner
Jul 26, 2017
Moritz Maxeiner
Jul 27, 2017
Moritz Maxeiner
Jul 27, 2017
Swoorup Joshi
July 26, 2017
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?

Externally, we can do it with the existing language:

class {
    ~this() {}     // Finalizer

    ~this @nogc {} // Destructor
}

Internally, the runtime will treat each differently. an rt_destruct would call all every __dtor in a hierarchy 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. And destroy would be changed to call rt_destruct instead of rt_finalize.

Thoughts?
July 26, 2017
On Wednesday, 26 July 2017 at 02:58:00 UTC, Mike Parker wrote:
>
> Internally, the runtime will treat each differently. an rt_destruct would call all every __dtor in a hierarchy 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. And destroy would be changed to call rt_destruct instead of rt_finalize.
>
> Thoughts?

And an important bit I left out -- destroy would still call rt_finalize if no destructor is present, which would preserve current behavior.

July 26, 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`.
July 26, 2017
On Wednesday, 26 July 2017 at 02:58:00 UTC, Mike Parker wrote:
> When cleaning up, the GC will ensure that all destructors are run where they exist, followed by all finalizers. And destroy would be changed to call rt_destruct instead of rt_finalize.
>
> Thoughts?

I don't get the distinction between destructors and "finalizers" but imho the problem is very much that the GC is calling ~this.
July 26, 2017
On Wednesday, 26 July 2017 at 12:19:15 UTC, Guillaume Piolat wrote:
>
> I don't get the distinction between destructors and "finalizers" but imho the problem is very much that the GC is calling ~this.

Destructors are deterministic, finalizers are not. At least, that's how I understand the terms are commonly used.
July 26, 2017
On 7/26/17 8:19 AM, Guillaume Piolat wrote:
> On Wednesday, 26 July 2017 at 02:58:00 UTC, Mike Parker wrote:
>> When cleaning up, the GC will ensure that all destructors are run where they exist, followed by all finalizers. And destroy would be changed to call rt_destruct instead of rt_finalize.
>>
>> Thoughts?
> 
> I don't get the distinction between destructors and "finalizers" but imho the problem is very much that the GC is calling ~this.

In D, the difference is when the thing is called. If it's called deterministically, either by function or by the compiler, then you have a lot more flexibility. If it's by the GC, it can be out of order with regards to your members, it could be on a different thread than the one that owned it, etc.

Regarding the OP, I think we really should strive to have something to fix this issue.

A poor-mans distinction could be done by checking whether the GC is currently the one destroying (a flag is available, but isn't publicly accessible), though that could get expensive.

-Steve
July 26, 2017
On Wednesday, 26 July 2017 at 09:29:15 UTC, Moritz Maxeiner wrote:


> 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
> }

Yeah, this brings with it more flexibility. I'd prefer to avoid adding a new attribute for it, but this looks more interesting.


>> 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:

Indeed! Let's pretend I didn't write that.

July 26, 2017
On Wednesday, 26 July 2017 at 12:43:27 UTC, Steven Schveighoffer wrote:
>
> Regarding the OP, I think we really should strive to have something to fix this issue.
>
> A poor-mans distinction could be done by checking whether the GC is currently the one destroying (a flag is available, but isn't publicly accessible), though that could get expensive.

That's essentially what Guillaume's "GC-proof resource class" idiom does now.

https://p0nce.github.io/d-idioms/#GC-proof-resource-class

July 26, 2017
On Wednesday, 26 July 2017 at 12:55:17 UTC, Mike Parker wrote:
>> ---
>> ~this() {}                    // Finalizer
>> ~this() @nogc {}              // Finalizer
>> ~this @deterministic {}       // Destructor
>> ~this @nogc @deterministic {} // Destructor
>> }
>
> Yeah, this brings with it more flexibility. I'd prefer to avoid adding a new attribute for it, but this looks more interesting.
>
>

Some other options:
~~this() {}
!this() {}
!~this() {}
this!(true) () {} //not really a big fan of this version
July 26, 2017
On 7/26/17 8:57 AM, Mike Parker wrote:
> On Wednesday, 26 July 2017 at 12:43:27 UTC, Steven Schveighoffer wrote:
>>
>> Regarding the OP, I think we really should strive to have something to fix this issue.
>>
>> A poor-mans distinction could be done by checking whether the GC is currently the one destroying (a flag is available, but isn't publicly accessible), though that could get expensive.
> 
> That's essentially what Guillaume's "GC-proof resource class" idiom does now.
> 
> https://p0nce.github.io/d-idioms/#GC-proof-resource-class
> 

Yeah, I've seen that.

https://issues.dlang.org/show_bug.cgi?id=17563

-Steve
« First   ‹ Prev
1 2 3 4