On Tuesday, 27 June 2017 at 13:11:10 UTC, Steven Schveighoffer wrote:
But I would use a close method, and not destroy(obj). The reason is because often times, you have wrapper types around your socket type, and just one extra level of indirection means the destructor cannot be used to clean up the socket (you are not allowed to access GC-allocated resources in a destructor).

All destructor restrictions do not apply when it's not called by the GC.

There really are two categories of destructors: called by the GC and called deterministically. Their usage should not overlap.




My reasoning went with the following:

1 - "I should have close() methods so that I don't rely on the GC, and the GC is calling ~this from the wrong thread etc, not everything can be released in this context (eg: OpenGL objects should be released from one thread only). Close methods will call close methods of "owned" objects."

2 - "Uh, oh. Refcounted and Unique and Scoped all use .destroy, so destructors should call close() methods. To avoid double release, close should handle being called several times. The GC will close what I forgot!"

3 - "Actually there is no order of destruction when called by the GC. So I can't release owned objects when called by the GC. Better do nothing when close() is called by the GC, let's detect this.

4 - close() is now identical with ~this (at least for classes). Let's remove the close() method. Crash when a resource is freed by the GC.

That's how the GC-proof resource class came to existence, after many destruction bugs, and it let's you use the GC as a detector for non-deterministic destruction. I miss it in @nogc :)

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

Remember years ago when Alexandrescu suggested the GC shouldn't call heap destructors? That's what we get for having said no at the time.

Reply via email to