November 12, 2021

Hello,
I implemented reference counted pointers supporting:

  • weak pointers (optional).
  • aliasing.
  • atomic/non-atomic counters.
  • multithread ref counted pointers .
  • arrays.
  • destructors with attributes
  • pure, const, immutable and shared support.
  • limited dip1000 and @safe support.
  • intrusive pointers
  • unique pointers

Api is inspired with std::shared_ptr
Implementation is inspired by clang std::shared_ptr.

git: https://github.com/submada/autoptr
doc: https://submada.github.io/autoptr/
dub: https://code.dlang.org/packages/autoptr

Examples:


import autoptr.shared_ptr;


///
pure nothrow @nogc unittest{

    static class Foo{
        int i;

        this(int i)pure nothrow @safe @nogc{
            this.i = i;
        }
    }

    static class Bar : Foo{
        double d;

        this(int i, double d)pure nothrow @safe @nogc{
            super(i);
            this.d = d;
        }
    }

    //implicit qualifier cast
    {
        SharedPtr!(const Foo) foo =  SharedPtr!Foo.make(42);
        assert(foo.get.i == 42);
        assert(foo.useCount == 1);

        const SharedPtr!Foo foo2 = foo;
        assert(foo2.get.i == 42);
        assert(foo.useCount == 2);

    }

    //polymorphic classes:
    {
        SharedPtr!Foo foo = SharedPtr!Bar.make(42, 3.14);
        assert(foo != null);
        assert(foo.useCount == 1);
        assert(foo.get.i == 42);

        //dynamic cast:
        {
            SharedPtr!Bar bar = dynCast!Bar(foo);
            assert(foo.useCount == 2);

            assert(bar.get.i == 42);
            assert(bar.get.d == 3.14);
        }

    }

    //aliasing:
    {
        SharedPtr!Foo foo = SharedPtr!Bar.make(42, 3.14);
        assert(foo.useCount == 1);

        auto x = SharedPtr!int(foo, &foo.get.i);
        assert(foo.useCount == 2);
        assert(x.useCount == 2);

        assert(*x == 42);
    }

    //weak references:
    {
        auto x = SharedPtr!double.make(3.14);
        assert(x.useCount == 1);
        assert(x.weakCount == 0);

        auto w = x.weak();  //weak pointer
        assert(x.useCount == 1);
        assert(x.weakCount == 1);
        assert(*w.lock == 3.14);

        SharedPtr!double.WeakType w2 = x;
        assert(x.useCount == 1);
        assert(x.weakCount == 2);

        assert(w2.expired == false);
        x = null;
        assert(w2.expired == true);
    }

    //dynamic array
    {
        import std.algorithm : all;

        {
            auto arr = SharedPtr!(long[]).make(10, -1);

            assert(arr.length == 10);
            assert(arr.get.all!(x => x == -1));
        }

        {
            auto arr = SharedPtr!(long[]).make(8);
            assert(arr.length == 8);
            assert(arr.get.all!(x => x == long.init));
        }
    }

    //static array
    {
        import std.algorithm : all;

        {
            auto arr = SharedPtr!(long[4]).make(-1);
            assert(arr.get[].all!(x => x == -1));

        }

        {
            long[4] tmp = [0, 1, 2, 3];
            auto arr = SharedPtr!(long[4]).make(tmp);
            assert(arr.get[] == tmp[]);
        }
    }

}

///
pure nothrow @safe @nogc unittest{
    //make SharedPtr object
    static struct Foo{
        int i;

        this(int i)pure nothrow @safe @nogc{
            this.i = i;
        }
    }

    {
        auto foo = SharedPtr!Foo.make(42);
        auto foo2 = SharedPtr!Foo.make!Mallocator(42);  //explicit stateless allocator
    }

    {
        import std.experimental.allocator : make, dispose;

        static void deleter(long* x)pure nothrow @trusted @nogc{
            Mallocator.instance.dispose(x);
        }
        long* element = Mallocator.instance.make!long;

        auto x = SharedPtr!long.make(element, &deleter);
    }

    {
        auto arr = SharedPtr!(long[]).make(10); //dynamic array with length 10
        assert(arr.length == 10);
    }
}

///
nothrow unittest{
    //alloc SharedPtr object
    import std.experimental.allocator : make, dispose, allocatorObject;

    auto allocator = allocatorObject(Mallocator.instance);

    {
        auto x = SharedPtr!long.alloc(allocator, 42);
    }

    {
        static void deleter(long* x)pure nothrow @trusted @nogc{
            Mallocator.instance.dispose(x);
        }
        long* element = Mallocator.instance.make!long;
        auto x = SharedPtr!long.alloc(allocator, element, &deleter);
    }

    {
        auto arr = SharedPtr!(long[]).alloc(allocator, 10); //dynamic array with length 10
        assert(arr.length == 10);
    }

}
November 13, 2021

On Friday, 12 November 2021 at 14:32:42 UTC, vit wrote:

>

Hello,
I implemented reference counted pointers supporting:

  • weak pointers (optional).
  • aliasing.
  • atomic/non-atomic counters.
  • multithread ref counted pointers .
  • arrays.
  • destructors with attributes
  • pure, const, immutable and shared support.
  • limited dip1000 and @safe support.
  • intrusive pointers
  • unique pointers

Api is inspired with std::shared_ptr
Implementation is inspired by clang std::shared_ptr.

git: https://github.com/submada/autoptr
doc: https://submada.github.io/autoptr/
dub: https://code.dlang.org/packages/autoptr

Nicely done!

There are over 1000 lines of test code, line 2590 starts unittests.

Thank you...