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

Reply via email to