On Wednesday, 4 March 2015 at 18:59:54 UTC, Andrei Alexandrescu wrote:
On 3/4/15 10:48 AM, bitwise wrote:
After looking at DIP74, it seems that there is no way to create a weak reference to a ref counted object, but is not explicitly stated. Has
this idea been considered at all?

DIP74 aims at not disallowing weak references whilst leaving it to libraries to effect implementations, but we'd need a proof of concept implementation to make sure DIP74 is enough as is. -- Andrei

I suppose you could add "getWeak()" and "releaseWeak()" to a ref counted class, and implement a "struct Weak(T)" that calls them for you, but I doesn't seem like much of a leap to just add something like this to the DIP.

couldn't "opAddWeak" and "opReleaseWeak" be added and follow identical rules to "opAddRef" and "opRelease"? The compiler could simply insert "opAddWeak() instead of opAddRef() when it found the "weak" keyword.

For example:

class Widget {
    private uint _refs = 1;
    private uint _weaks = 0;

    private int[] _payload; // owned
        
    void opAddRef() {
        ++_refs;
    }
    void opRelease() {
        if (--_refs == 0) {
            GC.free(_payload.ptr);
            _payload = null;

// I'm assuming this would leave "_weaks" and "_refs" untouched
            this.destroy();

            if(_weaks == 0) {
                GC.free(cast(void*)this);
            }
        }
    }

    void opAddWeak() {
        ++_weaks;
    }
    void opReleaseWeak() {
        if(--_weaks == 0 && _refs == 0) {
                GC.free(cast(void*)this);
        }
    }

    // optional/recommended
    bool expired() {
                return _refs == 0;
    }
}

Widget a = new Widget; // refs == 1, weaks == 0

Widget b = weak a; // refs == 1, weaks == 1
//a.opAddWeak();

Widget c = b;
// b.opAddRef(); // refs == 2, weaks == 1

a = null; // refs == 1, weaks == 1
//a.opRelease();

assert(b.expired() == false);

c = null; // refs == 0, weaks == 1
// c.opRelease();

assert(b.expired() == true);

b = null; // refs == 0, weaks == 0
// b.opReleaseWeak();

////////// or for function calls:

void func(weak Widget a) {
        //...
}

Widget a = new Widget;
func(a);

Reply via email to