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