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


Reply via email to