On Wednesday, 28 June 2017 at 00:05:20 UTC, Guillaume Piolat wrote:
On Tuesday, 27 June 2017 at 23:54:50 UTC, Moritz Maxeiner wrote:
- Replace calls by the GC to `~this` with calls to `finalize` (or invent some cool other shortened name for the latter)

My point is that in such a "finalize()" function the only sane things to do is to crash if the resource wasn't freed already. Why so?

[...]

Not every class can't be finalized, so it might make sense for finalization to remain an available option. What I think reasonable is treating destruction and finalization as two distinct things. This could look like the following:

---
// Does not refer to other GC memory, can be finalized
class File
{
private:
    int fd;
public:
    this() { fd = open(...); }
    ~this() { close(fd); }

// If the GC collects a File object that hasn't been destroyed yet, it will call this finalizer, // which *manually* calls the destructor (because it's safe to do so in this case) // A File object can still be manually `destroy`ed beforehand, in which case this particular finalizer is still safe, since an object won't be destroyed twice
    finalize() { destroy(this); }
    // Or maybe prettier: alias finalize = ~this;
}

class Foo
{
private:
    File f;
public:
    this() { f = new File(); }

// Make the process crash on finalization of an undestroyed Foo object
    @disable finalize();
}
---


- Reserve `~this` for being called by deterministic lifetime management (std.experimental.allocator.dispose, object.destroy, RefCounted, Unique, etc.)

That's precisely what the GC-proof-resource-class allows, by preventing defective, non-composable usages of ~this.

The GC proof resource class idiom is a necessary hack, but it *is* a hack with its own limitations (e.g. depending on Error being catchable).

Reply via email to