DIP74: Reference Counted Class Objects

bitwise via Digitalmars-d digitalmars-d at puremagic.com
Wed Mar 4 12:04:58 PST 2015


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


More information about the Digitalmars-d mailing list