Re: Reference counting example

2022-04-27 Thread vit via Digitalmars-d-learn

On Tuesday, 26 April 2022 at 23:33:28 UTC, cc wrote:

On Tuesday, 26 April 2022 at 22:16:01 UTC, cc wrote:

Test application:


I should point out that all this stuff with saving refcounted 
things to arrays and so on is extremely untested and 
experimental


One problem I'm seeing is the inability for a refcounted class 
to pass itself to another function, since the class internals 
don't see the struct wrapper.. you can pass the naked object 
reference itself, and hope the reference doesn't get saved 
otherwise there's your dangling pointer, but then you also have 
the problem of inconsistent method declarations, with some 
things taking Foo and others taking RefCounted!Foo etc...


Every night I pray for a `refcounted` keyword.  Wouldn't 
something like `auto foo = new refcount Foo();` be nice?  Then 
every class that deals with the objects could continue to be 
allocator-agnostic... definitely not a trivial change though.


Yor code has antoher big problem. Class Animal has 
@safe/pure/nothrow/@nogc destruction but class Cow has @system 
destructor. When you assign RC!Cow to RC!Animal you can have 
@safe @nogc ... function call @system destructor of Cow.



I have library with check this kind of error for you 
(https://code.dlang.org/packages/btl).


If you need aliasing (your case) or weak pointers then try it.

```d

import std.stdio;
import core.memory;
import core.lifetime;

import btl.autoptr;
import btl.vector;

alias ARRAY = Vector;
alias RC = RcPtr;

class Animal {
void speak() {
writeln("Animal: ???");
}

~this()@system{}   //without this code doesnt compile
}
class Cow : Animal {
ARRAY!(RC!Animal) friends; // Amazingly, this works, as 
long as the array elem type is NOT the same as RC!(this class)
// otherwise we get a 
forwarding error

int x;
this() { writefln("[Cow]"); }
this(int x) { this.x = x; writefln("[Cow %s]", x); }
~this() { writefln("[/Cow %s]", x); }
override void speak() {
writefln("Cow#%s: Moo.", x);
}
}

class Farm {
ARRAY!(RC!Cow) animals;
//this() {}
this(int) { writeln("[Farm]"); }
~this() {
writeln("[~Farm]");
animals.clear();
writeln("[/Farm]");
}

void pet(RC!Animal animal) {
writefln("Farm: The %s says...", animal);
animal.get.speak;
}

}

void main() {
auto used = GC.stats.usedSize;
scope(exit) assert(GC.stats.usedSize == used); // GC is 
not touched!

{
assert(RC!Cow.make().get.x == 0);
assert(RC!Cow.make(99).get.x == 99);
}

RC!Animal other;

auto farm = RC!Farm.make(1);
{
auto cow = RC!Cow.make(1);
farm.get.animals ~= cow;
farm.get.animals ~= RC!Cow.make(2);
other = farm.get.animals[1];
auto cowGoesOutOfScope = RC!Cow.make(70);
}
writeln("out, should have seen Cow#70's dtor");

farm.get.animals[0] = farm.get.animals[1];
writeln("animals[0] (Cow#1) just got overwritten so we 
should have seen its dtor");


farm.get.animals ~= RC!Cow.make(3);

farm.get.pet(other);
other = null;

farm = null;

writeln("done");
}
```


Re: Reference counting example

2022-04-26 Thread cc via Digitalmars-d-learn

On Tuesday, 26 April 2022 at 22:16:01 UTC, cc wrote:

Test application:


I should point out that all this stuff with saving refcounted 
things to arrays and so on is extremely untested and experimental


One problem I'm seeing is the inability for a refcounted class to 
pass itself to another function, since the class internals don't 
see the struct wrapper.. you can pass the naked object reference 
itself, and hope the reference doesn't get saved otherwise 
there's your dangling pointer, but then you also have the problem 
of inconsistent method declarations, with some things taking Foo 
and others taking RefCounted!Foo etc...


Every night I pray for a `refcounted` keyword.  Wouldn't 
something like `auto foo = new refcount Foo();` be nice?  Then 
every class that deals with the objects could continue to be 
allocator-agnostic... definitely not a trivial change though.


Re: Reference counting example

2022-04-26 Thread cc via Digitalmars-d-learn

On Tuesday, 26 April 2022 at 06:55:34 UTC, Alain De Vos wrote:
Can someone provide a simple/very simple reference counting or 
refcounted example i can understand. Thanks.


I've been playing around with the automem[1] library's RefCounted 
feature as we speak, it seems to fit my needs more than 
std.typecons which doesn't quite do what I want.  I did have to 
make some changes to the library though to allow for inheritance 
and manually releasing (below).  It's pretty fun so far so I'm 
looking forward to trying it in some other projects like a non-GC 
XML library.

[1] https://github.com/atilaneves/automem

Test application:
```d
import std.stdio;
import core.memory;
import util.array; // ARRAY Custom wrapper for std.container.array
// The vector/array library provided with automem does NOT 
properly destroy array elements

// so we'll use std.container.array instead

import std.experimental.allocator.mallocator;
import automem;

alias RC(T) = RefCounted!(T, Mallocator);
// Optional default constructor workaround
auto RCREATE(T, Args...)(auto ref Args args) {
return RC!T.create(args);
}

class Farm {
ARRAY!(RC!Cow) animals;
//this() {}
this(int) { writeln("[Farm]"); }
~this() {
writeln("[~Farm]");
animals.clear();
writeln("[/Farm]");
}

void pet(RC!Animal animal) {
writefln("Farm: The %s says...", animal);
animal.speak;
}

}
class Animal {
void speak() {
writeln("Animal: ???");
}
}
class Cow : Animal {
	ARRAY!(RC!Animal) friends; // Amazingly, this works, as long as 
the array elem type is NOT the same as RC!(this class)

// otherwise we 
get a forwarding error
int x;
this() { writefln("[Cow]"); }
this(int x) { this.x = x; writefln("[Cow %s]", x); }
~this() { writefln("[/Cow %s]", x); }
override void speak() {
writefln("Cow#%s: Moo.", x);
}
}


void main() {
auto used = GC.stats.usedSize;
	scope(exit) assert(GC.stats.usedSize == used); // GC is not 
touched!

{
assert(RCREATE!Cow.x == 0);
assert(RCREATE!Cow(99).x == 99);
}

RC!Animal other;

auto farm = RC!Farm(1);
{
auto cow = RC!Cow(1);
farm.animals ~= cow;
farm.animals ~= RC!Cow(2);
other = farm.animals[1];
auto cowGoesOutOfScope = RC!Cow(70);
}
writeln("out, should have seen Cow#70's dtor");

farm.animals[0] = farm.animals[1];
	writeln("animals[0] (Cow#1) just got overwritten so we should 
have seen its dtor");


farm.animals ~= RC!Cow(3);

farm.pet(other);
other = null;

farm = null;

writeln("done");
}
```

Output:
```
[Cow]
[/Cow 0]
[Cow 99]
[/Cow 99]
[Farm]
[Cow 1]
[Cow 2]
[Cow 70]
[/Cow 70]
out, should have seen Cow#70's dtor
[/Cow 1]
animals[0] (Cow#1) just got overwritten so we should have seen 
its dtor

[Cow 3]
Farm: The memtest.Cow says...
Cow#2: Moo.
[~Farm]
[/Cow 2]
[/Cow 3]
[/Farm]
done
```


I added the following functions to automem `ref_counted.d`:
```d
// static .create method to allow use of class's default 
constructor if desired
static if (isGlobal && is(Type == class) && 
__traits(compiles, new Type())) {

static auto create(Args...)(auto ref Args args) {
typeof(this) obj;
obj.makeObject!args();
return obj;
}
}

// allow instantiation or assignment from derived classes if 
the Allocator is the same
this(U)(ref RefCounted!(U,Allocator) rhs) if (is(U == class) 
&& !is(U == Type)) {

_impl = cast(typeof(_impl)) rhs._impl;
if(_impl !is null) inc;
}
void opAssign(U : Type)(ref RefCounted!(U,Allocator) other) 
if (is(U == class) && !is(U == Type)) {

//if (_impl == other._impl) return;
if (_impl._rawMemory.ptr == other._impl._rawMemory.ptr) 
return;

if(_impl !is null) release;
static if(!isGlobal)
_allocator = other._allocator;
_impl = cast(typeof(_impl)) other._impl;
if(_impl !is null) inc;
}

// Allow assigning null to manually release payload
void opAssign(typeof(null)) {
if(_impl !is null) release;
_impl = null;
}
```



Re: Reference counting example

2022-04-26 Thread JG via Digitalmars-d-learn

On Tuesday, 26 April 2022 at 06:55:34 UTC, Alain De Vos wrote:
Can someone provide a simple/very simple reference counting or 
refcounted example i can understand. Thanks.


I suggest to look at RefCounted 
[here](https://code.dlang.org/packages/automem) rather than in 
Phobos. There are simple examples.


Reference counting example

2022-04-26 Thread Alain De Vos via Digitalmars-d-learn
Can someone provide a simple/very simple reference counting or 
refcounted example i can understand. Thanks.