GC-proof resource classes

Timon Gehr via Digitalmars-d digitalmars-d at puremagic.com
Sat Aug 29 15:50:42 PDT 2015


On 08/29/2015 05:20 PM, cym13 wrote:
> On Saturday, 29 August 2015 at 14:32:27 UTC, Timon Gehr wrote:
>> But then classes with destructors shouldn't be allowed to be allocated
>> on the GC heap in the first place, which is a PITA as well. (Note that
>> classes/arrays can have destructors because some component structs
>> have them; structs generally assume that their destructors will be
>> called.)
>
> I don't quite follow the reasonning here. If GC doesn't call the
> destructor then this same destructor is no more than a normal method

If it is no more than a normal method:
- Why have special syntax for it?
- Why should Object have it?

> (with restrictions... would those still stand?) that is the default
> destruction method to be called by things like scoped!T or destroy if
> explicit destruction is needed.
> ...

If there is a destructor, this (usually) means that explicit destruction 
is needed.

Again, note that if I have

import std.collection: Array;
class C{ Array arr; ... }

then now C implicitly has a destructor (that does nothing but call arr's 
destructor which may in turn free memory on the C heap).

Constructor and destructor are supposed to frame the lifetime of an 
instance. Destructors are in the language so that the language can help 
with enforcing this. If there's a built-in and expected way to violate 
this property, the syntactic similarity of constructors and destructors 
is misleading, and the features are less useful.

> I think there should be a separation of concerns that isn't possible
> right now. Freeing ressources and freeing memory isn't the same thing
> and they should be decoupled.

Memory is a resource, and not all memory is allocated by the GC. (c.f. 
http://erdani.com/d/phobos-prerelease/std_experimental_allocator.html)

> I think a destructor is there to free
> ressources, and the GC is there to free memory. If the GC doesn't call
> the destructor then why should having a destructor have anything to do
> with the GC?
>
> Or do you fear for classes whose memory would be freed before freeing
> its ressources?

For example. The general idea is that there is no point in having 
language features to deal with complex issues if they actually don't.

> That could be a problem...  In that case I think the best
> option would be to allow them to be allocated by the GC

I assume this means allow 'new Class()' even if Class has a destructor.

> but GC-ing it if
> the destructor hasn't been called should spawn an error (or something
> like that, haven't taken the time to think through it).

Why is it sensible to have the same syntax for allocation if
deallocation/destruction needs to be handled differently?

> Or maybe it shouldn't be marked as garbage if the destructor hasn't been called.
> ...

I.e. leak memory.

> I think of it as a simple switch hasDestructorBeenCalled  that would be
> set to true if no destructor exists or if it has been called, and false
> otherwise, and would prevent GC-ing (or crash... I don't know what's
> best) of the object if false.
>
> That way simple classes stay simple,

Simple classes get an additional hidden field. Even the monitor field is 
too much.

> complex classes can live on the
> heap happily without fearing collection while being able to reliably
> free ressources.

This does not make a lot of sense. If there is no live reference to a 
class managing a resource and it would then need to "fear" collection, 
this means that the resource has been leaked.


More information about the Digitalmars-d mailing list