Reference counting example
vit
vit at vit.vit
Wed Apr 27 06:25:42 UTC 2022
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");
}
```
More information about the Digitalmars-d-learn
mailing list