View mode: basic / threaded / horizontal-split · Log in · Help
May 24, 2012
Re: Destructor nonsense on dlang.org
On 24-05-2012 18:06, Andrei Alexandrescu wrote:
> On 5/24/12 9:57 AM, Alex Rønne Petersen wrote:
>> On 24-05-2012 16:54, Andrei Alexandrescu wrote:
>>> On 5/24/12 9:28 AM, Alex Rønne Petersen wrote:
>>>> The GC should (and probably does) assume at shutdown that all objects
>>>> are unreferenced, and therefore reclaim and finalize them.
>>>
>>> They may refer to one another.
>>>
>>> Andrei
>>>
>>
>> Doesn't matter: Nothing is guaranteed about order of finalization (and
>> this is reasonable). Thus, the finalizers can be run in any arbitrary
>> order. The important point here is that they are run *at all*.
>
> It does matter because a destructor may use an object that has just been
> destroyed.
>
> Andrei
>

No, the docs specifically state that this is invalid (and it currently 
throws InvalidMemoryOperationError in most cases).

Whether it *should* be allowed is arguable, but it isn't currently, both 
in docs and impl.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 24, 2012
Re: Destructor nonsense on dlang.org
On 5/24/12 10:27 AM, deadalnix wrote:
> Le 24/05/2012 16:54, Andrei Alexandrescu a écrit :
>> On 5/24/12 9:28 AM, Alex Rønne Petersen wrote:
>>> The GC should (and probably does) assume at shutdown that all objects
>>> are unreferenced, and therefore reclaim and finalize them.
>>
>> They may refer to one another.
>>
>> Andrei
>>
>
> So what ?
>
> Each GC passes must, mark object that have to be removed, call finalizer
> on them all, THEN recycle memory.
>
> So « zombie » object can still refer to one another in finalization.

This is possible but not trivial as the state of zombie objects must be 
properly defined. Often such objects will fail their invariant (a 
reasonable state of a zombie object is with the correct vtable, no 
mutex, and all fields in the pre-constructor state).

> The real problem is resurrection, which should be 100% forbiden and this
> must be enforced by the language (ie, the scopeness of this parameter is
> something important).

As one aspect, calls to new should fail during destruction.


Andrei
May 24, 2012
Re: Destructor nonsense on dlang.org
On 24-05-2012 18:10, Andrei Alexandrescu wrote:
> On 5/24/12 10:27 AM, deadalnix wrote:
>> Le 24/05/2012 16:54, Andrei Alexandrescu a écrit :
>>> On 5/24/12 9:28 AM, Alex Rønne Petersen wrote:
>>>> The GC should (and probably does) assume at shutdown that all objects
>>>> are unreferenced, and therefore reclaim and finalize them.
>>>
>>> They may refer to one another.
>>>
>>> Andrei
>>>
>>
>> So what ?
>>
>> Each GC passes must, mark object that have to be removed, call finalizer
>> on them all, THEN recycle memory.
>>
>> So « zombie » object can still refer to one another in finalization.
>
> This is possible but not trivial as the state of zombie objects must be
> properly defined. Often such objects will fail their invariant (a
> reasonable state of a zombie object is with the correct vtable, no
> mutex, and all fields in the pre-constructor state).
>
>> The real problem is resurrection, which should be 100% forbiden and this
>> must be enforced by the language (ie, the scopeness of this parameter is
>> something important).
>
> As one aspect, calls to new should fail during destruction.
>
>
> Andrei

Finalization happens once the world has been resumed, meaning GC 
allocation (and even explicit deallocation) should be perfectly safe. 
This is absolutely essential: Finalization models where finalizers run 
in a paused world are doomed to fail miserably.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 24, 2012
Re: Destructor nonsense on dlang.org
On Thursday, 24 May 2012 at 16:06:23 UTC, Andrei Alexandrescu 
wrote:
> On 5/24/12 9:57 AM, Alex Rønne Petersen wrote:
>> Doesn't matter: Nothing is guaranteed about order of 
>> finalization (and
>> this is reasonable). Thus, the finalizers can be run in any 
>> arbitrary
>> order. The important point here is that they are run *at all*.
> It does matter because a destructor may use an object that has 
> just been destroyed.

You can't do that in today's D either, going by the spec as well 
by the actual implementation.

David
May 24, 2012
Re: Destructor nonsense on dlang.org
Le 24/05/2012 18:10, Alex Rønne Petersen a écrit :
> On 24-05-2012 18:06, Andrei Alexandrescu wrote:
>> It does matter because a destructor may use an object that has just been
>> destroyed.
>>
>> Andrei
>>
>
> No, the docs specifically state that this is invalid (and it currently
> throws InvalidMemoryOperationError in most cases).
>
> Whether it *should* be allowed is arguable, but it isn't currently, both
> in docs and impl.
>

I really had a hard time to believe it when #D told me so, but there is 
no guaranteed order of destruction and as you cannot relies on members 
still being alive in a class destructor.
All of it can happen when making absolutely no cycles in the object graph.

What I do now is having a close function for each class which hold a 
non-memory resource.

This is writtent in TDPL, but I wish I was told earlier :)
May 24, 2012
Re: Destructor nonsense on dlang.org
On Thursday, 24 May 2012 at 17:06:19 UTC, ponce wrote:
> I really had a hard time to believe it when #D told me so, but 
> there is no guaranteed order of destruction and as you cannot 
> relies on members still being alive in a class destructor.
> All of it can happen when making absolutely no cycles in the 
> object graph.
>
> What I do now is having a close function for each class which 
> hold a non-memory resource.
>
> This is writtent in TDPL, but I wish I was told earlier :)

http://dlang.org/class.html#destructors

"This rule does not apply to auto objects or objects deleted with 
the DeleteExpression, as the destructor is not being run by the 
garbage collector, meaning all references are valid."

i.e. non gc resources are fine... and it's also fine if you call 
clear()... it's only a problem if you rely on automatic 
collection and reference a object... so there's no need for 
close, as clear() will do the trick.
May 24, 2012
Re: Destructor nonsense on dlang.org
On 24-05-2012 19:47, Tove wrote:
> On Thursday, 24 May 2012 at 17:06:19 UTC, ponce wrote:
>> I really had a hard time to believe it when #D told me so, but there
>> is no guaranteed order of destruction and as you cannot relies on
>> members still being alive in a class destructor.
>> All of it can happen when making absolutely no cycles in the object
>> graph.
>>
>> What I do now is having a close function for each class which hold a
>> non-memory resource.
>>
>> This is writtent in TDPL, but I wish I was told earlier :)
>
> http://dlang.org/class.html#destructors
>
> "This rule does not apply to auto objects or objects deleted with the
> DeleteExpression, as the destructor is not being run by the garbage
> collector, meaning all references are valid."
>
> i.e. non gc resources are fine... and it's also fine if you call
> clear()... it's only a problem if you rely on automatic collection and
> reference a object... so there's no need for close, as clear() will do
> the trick.
>
>

I would strongly advise against that, because a missed clear() means 
your finalizer may be run by the runtime's finalization machinery, and 
thus invalidate any invariants you were relying on in the finalizer.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
May 24, 2012
Re: Destructor nonsense on dlang.org
On Thursday, 24 May 2012 at 17:55:02 UTC, Alex Rønne Petersen 
wrote:
> I would strongly advise against that, because a missed clear() 
> means your finalizer may be run by the runtime's finalization 
> machinery, and thus invalidate any invariants you were relying 
> on in the finalizer.

Yes – the »correc†
May 24, 2012
Re: Destructor nonsense on dlang.org
On Thu, 24 May 2012 13:47:31 -0400, Tove <tove@fransson.se> wrote:

> On Thursday, 24 May 2012 at 17:06:19 UTC, ponce wrote:
>> I really had a hard time to believe it when #D told me so, but there is  
>> no guaranteed order of destruction and as you cannot relies on members  
>> still being alive in a class destructor.
>> All of it can happen when making absolutely no cycles in the object  
>> graph.
>>
>> What I do now is having a close function for each class which hold a  
>> non-memory resource.
>>
>> This is writtent in TDPL, but I wish I was told earlier :)
>
> http://dlang.org/class.html#destructors
>
> "This rule does not apply to auto objects or objects deleted with the  
> DeleteExpression, as the destructor is not being run by the garbage  
> collector, meaning all references are valid."
>
> i.e. non gc resources are fine... and it's also fine if you call  
> clear()... it's only a problem if you rely on automatic collection and  
> reference a object... so there's no need for close, as clear() will do  
> the trick.

There's a big problem with this though.  Your destructor *has no idea*  
whether it's being called from within a collection cycle, or from clear.   
You must assume the most restrictive environment, i.e. that the dtor is  
being called from the GC.

This is even true with struct dtors!

-Steve
May 24, 2012
Re: Destructor nonsense on dlang.org
On Thursday, 24 May 2012 at 17:55:02 UTC, Alex Rønne Petersen 
wrote:
> I would strongly advise against that, because a missed clear() 
> means your finalizer may be run by the runtime's finalization 
> machinery, and thus invalidate any invariants you were relying 
> on in the finalizer.

Yes – the »correct« way to handle situations where you need 
deterministic finalization is to use structs on the stack, 
possibly in conjunction with reference counting. Of course, there 
are some situations (e.g. when there are cycles) where this 
doesn't work, but at least it covers most of the »external 
non-memory resource« cases.

Composability can still be a problem, though, because holding a 
reference in a (GC-managed) class object might leave you with 
exactly the same problem you tried to avoid in the first place.

David
1 2 3 4 5 6 7
Top | Discussion index | About this forum | D home