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);