diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d index 8264fba..5ec3867 100644 --- a/source/tanya/math/mp.d +++ b/source/tanya/math/mp.d @@ -898,7 +898,10 @@ struct Integer } /** - * Casting to boolean. + * Casting. + * + * Params: + * T = Target type. * * Returns: $(D_KEYWORD false) if the $(D_PSYMBOL Integer) is 0, * $(D_KEYWORD true) otherwise. @@ -911,7 +914,10 @@ struct Integer /** * Casting to integer types. * - * Returns: Integer type. + * Params: + * T = Target type. + * + * Returns: Signed integer. */ T opCast(T : long)() const// pure nothrow @safe @nogc { diff --git a/source/tanya/memory/package.d b/source/tanya/memory/package.d index 7c288da..db389a2 100644 --- a/source/tanya/memory/package.d +++ b/source/tanya/memory/package.d @@ -10,11 +10,16 @@ */ module tanya.memory; +import core.exception; import std.algorithm.mutation; -public import std.experimental.allocator; +public import std.experimental.allocator : make, makeArray, expandArray, + stateSize, shrinkArray; +import std.traits; public import tanya.memory.allocator; public import tanya.memory.types; +private extern (C) void _d_monitordelete(Object h, bool det) @nogc; + shared Allocator allocator; shared static this() nothrow @safe @nogc @@ -82,3 +87,117 @@ unittest defaultAllocator.resizeArray(p, 0); assert(p is null); } + +private void deStruct(T)(ref T s) + if (is(S == struct)) +{ + static if (__traits(hasMember, T, "__xdtor") + && __traits(isSame, T, __traits(parent, s.__xdtor))) + { + s.__xdtor(); + } + auto buf = (cast(ubyte*) &s)[0 .. T.sizeof]; + auto init = cast(ubyte[])typeid(T).initializer(); + if (init.ptr is null) // null ptr means initialize to 0s + { + buf[] = 0; + } + else + { + buf[] = init[]; + } +} + +/** + * Destroys and deallocates $(D_PARAM p) of type $(D_PARAM T). + * It is assumed the respective entities had been allocated with the same + * allocator. + * + * Params: + * T = Type of $(D_PARAM p). + * allocator = Allocator the $(D_PARAM p) was allocated with. + * p = Object or array to be destroyed. + */ +void dispose(T)(shared Allocator allocator, T* p) +{ + static if (hasElaborateDestructor!T) + { + deStruct(*p); + } + allocator.deallocate((cast(void*) p)[0 .. T.sizeof]); +} + +/// Ditto. +void dispose(T)(shared Allocator allocator, T p) + if (is(T == class) || is(T == interface)) +{ + if (p is null) + { + return; + } + static if (is(T == interface)) + { + version(Windows) + { + import core.sys.windows.unknwn : IUnknown; + static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in " + ~ __PRETTY_FUNCTION__); + } + auto ob = cast(Object) p; + } + else + { + alias ob = p; + } + auto ptr = cast(void *) ob; + auto support = ptr[0 .. typeid(ob).initializer.length]; + + auto ppv = cast(void**) ptr; + if (!*ppv) + { + return; + } + + auto pc = cast(ClassInfo*) *ppv; + try + { + auto c = *pc; + do + { + if (c.destructor) // call destructor + { + (cast(void function (Object)) c.destructor)(cast(Object) ptr); + } + } + while ((c = c.base) !is null); + + if (ppv[1]) // if monitor is not null + { + _d_monitordelete(cast(Object) ptr, true); + } + auto w = (*pc).initializer; + ptr[0 .. w.length] = w[]; + } + catch (Exception e) + { + onFinalizeError(*pc, e); + } + finally + { + *ppv = null; + } + allocator.deallocate(support); +} + +/// Ditto. +void dispose(T)(shared Allocator allocator, T[] array) +{ + static if (hasElaborateDestructor!(typeof(array[0]))) + { + foreach (ref e; array) + { + deStruct(e); + } + } + allocator.deallocate(array); +}