RefCounted

JG someone at somewhere.com
Wed Apr 13 20:47:33 UTC 2022


Hi,

I would have thought that RefCounted!(T, 
RefCountedAutoInitialize.no) is to be used in place T* when I 
want reference counting instead of the usual garbage collection 
(or manual allocation). Perhaps this is wrong?

If I am correct what am I doing wrong here?

(Sorry for two space squashed style).

```
import std.stdio;
import std.typecons;

struct Node(T) {
   RefCounted!(Node!T, RefCountedAutoInitialize.no) next;
   T val;
}

struct List(T) {
   RefCounted!(Node!T, RefCountedAutoInitialize.no) head;
   bool empty() { return head.refCountedStore.isInitialized; }
   T front() { return head.val; }
   void popFront() { head = head.next; }
   typeof(this) save() { return typeof(this)(head); }
}

void main() {
   List!long l;
}
```
I also tried my own implementation but that is not working (since 
not everything is being freed) and probably
relies on undefined behavior with my casting away inout, which I 
did because
otherwise the compiler kept giving me errors about not being able 
to generate a copy constructor for List.

```
import std.stdio;
import core.stdc.stdlib;


private struct RefCountedPointer(T) {
   static struct Payload(T) {
     long cnt=1;
     T val;
   }
   Payload!T* ptr;
   this(T x) {
     ptr = cast(Payload!T*) calloc(0,Payload!T.sizeof);
     *ptr = Payload!T(1,x);
   }
   ~this() {
     if(ptr==null) { return; }
     (*ptr).cnt--;
     if((*ptr).cnt == 0) {
       ptr.val.destroy();
       free(ptr);
     }
   }
   @disable this(ref return scope immutable(typeof(this)) rhs);
   this(ref return scope inout(typeof(this)) rhs) {
     ptr = cast(Payload!T*) rhs.ptr;
     if(ptr==null) { return; }
     ptr.cnt++;
   }
   void opAssign(typeof(this) rhs) {
     if(this.ptr!=null) { (*this.ptr).cnt--; }
     this.ptr = rhs.ptr;
     if(this.ptr!=null) { (*this.ptr).cnt++; }
   }
   bool isNull() { return ptr==null; }
   ref auto dref() { assert(!isNull); return (*ptr).val; }
}

private struct Node(T) {
   RefCountedPointer!(Node!T) next;
   T val;
}


struct List(T) {
   private RefCountedPointer!(Node!T) head;
   bool empty() { return head.isNull; }
   T front() { return head.dref.val; }
   void popFront()  { head = head.dref.next;  }
   auto save() { return typeof(this)(head); }
   auto insert(T x) {
     head = RefCountedPointer!(Node!T)(Node!T(head,x));
   }
}

void main() {
   List!long list;
   list.insert(8);
import std.stdio;
import core.stdc.stdlib;


private struct RefCountedPointer(T) {
   static struct Payload(T) {
     long cnt=1;
     T val;
   }
   Payload!T* ptr;
   this(T x) {
     ptr = cast(Payload!T*) calloc(0,Payload!T.sizeof);
     *ptr = Payload!T(1,x);
   }
   ~this() {
     if(ptr==null) { return; }
     (*ptr).cnt--;
     if((*ptr).cnt == 0) {
       writeln("free");
       ptr.val.destroy();
       free(ptr);
     }
   }
   @disable this(ref return scope immutable(typeof(this)) rhs);
   this(ref return scope inout(typeof(this)) rhs) {
     ptr = cast(Payload!T*) rhs.ptr;
     if(ptr==null) { return; }
     ptr.cnt++;
   }
   void opAssign(typeof(this) rhs) {
     "here".writeln;
     if(this.ptr!=null) { (*this.ptr).cnt--; }
     this.ptr = rhs.ptr;
     if(this.ptr!=null) { (*this.ptr).cnt++; }
   }
   bool isNull() { return ptr==null; }
   ref auto dref() { assert(!isNull); return (*ptr).val; }
}

private struct Node(T) {
   RefCountedPointer!(Node!T) next;
   T val;
}


struct List(T) {
   private RefCountedPointer!(Node!T) head;
   bool empty() { return head.isNull; }
   T front() { return head.dref.val; }
   void popFront()  { head = head.dref.next;  }
   auto save() { return typeof(this)(head); }
   auto insert(T x) {
     head = RefCountedPointer!(Node!T)(Node!T(head,x));
   }
}

void main() {
   List!long list;
   list.insert(8);
import std.stdio;
import core.stdc.stdlib;


private struct RefCountedPointer(T) {
   static struct Payload(T) {
     long cnt=1;
     T val;
   }
   Payload!T* ptr;
   this(T x) {
     ptr = cast(Payload!T*) calloc(0,Payload!T.sizeof);
     *ptr = Payload!T(1,x);
   }
   ~this() {
     if(ptr==null) { return; }
     (*ptr).cnt--;
     if((*ptr).cnt == 0) {
       writeln("free");
       ptr.val.destroy();
       free(ptr);
     }
   }
   @disable this(ref return scope immutable(typeof(this)) rhs);
   this(ref return scope inout(typeof(this)) rhs) {
     ptr = cast(Payload!T*) rhs.ptr;
     if(ptr==null) { return; }
     ptr.cnt++;
   }
   void opAssign(typeof(this) rhs) {
     "here".writeln;
     if(this.ptr!=null) { (*this.ptr).cnt--; }
     this.ptr = rhs.ptr;
     if(this.ptr!=null) { (*this.ptr).cnt++; }
   }
   bool isNull() { return ptr==null; }
   ref auto dref() { assert(!isNull); return (*ptr).val; }
}

private struct Node(T) {
   RefCountedPointer!(Node!T) next;
   T val;
}


struct List(T) {
   private RefCountedPointer!(Node!T) head;
   bool empty() { return head.isNull; }
   T front() { return head.dref.val; }
   void popFront()  { head = head.dref.next;  }
   auto save() { return typeof(this)(head); }
   auto insert(T x) {
     head = RefCountedPointer!(Node!T)(Node!T(head,x));
   }
}

void main() {
   List!long list;
   list.insert(8);
   list.insert(7);
   list.insert(6);
   list.insert(5);
   list.insert(4);
   list.popFront;
   list.writeln;
   list.insert(4);
   list.insert(3);
   list.insert(2);
   list.insert(1);
   list.writeln;
}




More information about the Digitalmars-d-learn mailing list