On Friday, 25 May 2012 at 11:23:40 UTC, Jacob Carlborg wrote:
On 2012-05-25 11:02, foobar wrote:
It makes the call order deterministic like in C++.
e.g.
class Foo {}
struct A {
resource r;
~this() { release(r); }
}
struct B {
A* a;
Foo foo;
~this() { delete a; } // [1]
}
I though we were talking about classes holding structs:
class B {
A* a;
Foo foo;
~this() { delete a; }
}
In this case you don't know when/if the destructor of B is
called. It doesn't help to wrap it in a struct, you could just
have put it directly in A. Is that correct?
No. see below.
Lets look at point [1]:
The "foo" instance is "managed" by the GC since the only
resource it
holds is memory. The "a" member wraps some "non-managed"
resource (e.g.
file descriptor) and in this model is still valid, thus allows
me to
deterministically dispose of it as in c++.
Ok, but if B is a class?
This can be simply checked at compile-time - you can only
reference non
class instance members in the destructor, so adding a "delete
foo;"
statement at point [1] simply won't compile.
If you have a pointer to a struct you don't know how it was
created. It's possible it's been created with "new", which
means the garbage collector needs to delete it.
let's say we add two classes:
class FooA {
A a;
}
class FooPA {
A* pa;
}
For the first case, both the class and the struct share the same
lifetime thus when an instance of FooA is GC-ed, the GC would
call A's d-tor and allow it to do what-ever (self) cleaning it
requires. This means the d-tor will always be called.
For the second case, The GC will only scan "pa" to find inner
class instances but will *not* handle the struct value itself.
In order to clean what "pa" points to, you need to explicitly
call the destructor yourself. One way to do this would be to
register a callback with the GC to get notified when an instance
of FooPA is collected and inside the callback function maintain a
reference-counter.
This also means that if you allocate a struct value on the heap
via "new" you are responsible to call delete _yourself_ and the
gc will not call it for you.
I think that loosing this small convenience is worth it - we gay
more orthogonal semantics that are easier to reason about.