RefCounted

Salih Dincer salihdb at hotmail.com
Thu Apr 14 02:36:06 UTC 2022


On Wednesday, 13 April 2022 at 21:15:13 UTC, JG wrote:
> On Wednesday, 13 April 2022 at 20:47:33 UTC, JG wrote:
>> 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?
>>
>> [...]
>
> Perhaps I should have added in case it is relevant, I am not 
> actually interested in building lists. I eventually want to use 
> this in a "persistent" version of a red black tree (where if r 
> is such a tree and we set r1=r.insert(x) then r is unaffected 
> and r1 has the new element inserted - but they share most 
> nodes). This data structure is to be used in a multithreaded 
> application searching for a solution to some problem. The 
> current version has bad performance seemingly due to gc 
> stopping all threads while freeing unused nodes.

I don't know what RefCount is for but  I fixed your codes that 
mixed up:

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

  private struct RefCountedPointer(T) {
    static struct Payload(T) {
      int 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;
    }
  }

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

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

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