On Tuesday, 9 April 2013 at 20:46:12 UTC, Steven Schveighoffer wrote:
No. You are not allowed to access any GC-managed resources inside a destructor.
Okay, I finally found it: http://dlang.org/class.html#destructors. But it's not listed here: http://dlang.org/garbage.html.
And it won't be null, because that would be extremely costly. Consider if 300 objects had a pointer to a block of memory. Now those 300 objects all go away. By your expectation, if the targeted block of memory was collected, the GC would have to spend time going through all those 300 pointers, setting them to null. When they are about to all be destroyed. 99.99% of the time, that would be wasted, as those 300 objects may not even have destructors that care.
I thought about the case when the user sets the reference to null before the destructor was even called.
A destructor is ONLY for destroying non-GC managed resources, nothing else. Like an OS file handle for instance.
Imagine this case:

// External C library.
extern(C) {
    alias void* a_handle;
    alias void* b_handle;

    a_handle create_a();
    void destroy_a(a_handle);

    b_handle create_b(a_handle);
    void destroy_b(b_handle);
}

class A {
    this() {
        // An a_handle owns multiple b_handles.
        handle = create_a();
    }

    ~this() {
        // Destroys all bs connected with this a.
        destroy_a(handle);
    }

    private a_handle handle;
}

class B {
    this(A a) {
        this.a = a;
        // Creates a b_handle connected to the given a_handle.
        handle = create_b(a.handle);
    }

    ~this() {
        // a already destroyed -> segfault
        // a still alive -> works
        destroy_b(handle);
    }

    private A a;
    private b_handle handle;
}

Any instance of B always needs to be destructed _before_ the A it's connected to. How do you express this in D?

Reply via email to