Add internal finalize method for finalizing an object without deallocating
This commit is contained in:
		@@ -11,6 +11,7 @@
 | 
				
			|||||||
module tanya.memory;
 | 
					module tanya.memory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import core.exception;
 | 
					import core.exception;
 | 
				
			||||||
 | 
					import std.algorithm.iteration;
 | 
				
			||||||
public import std.experimental.allocator : make;
 | 
					public import std.experimental.allocator : make;
 | 
				
			||||||
import std.traits;
 | 
					import std.traits;
 | 
				
			||||||
public import tanya.memory.allocator;
 | 
					public import tanya.memory.allocator;
 | 
				
			||||||
@@ -87,8 +88,8 @@ shared Allocator allocator;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
shared static this() nothrow @trusted @nogc
 | 
					shared static this() nothrow @trusted @nogc
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    import tanya.memory.mallocator;
 | 
					    import tanya.memory.mmappool;
 | 
				
			||||||
    allocator = Mallocator.instance;
 | 
					    allocator = MmapPool.instance;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@property ref shared(Allocator) defaultAllocator() nothrow @safe @nogc
 | 
					@property ref shared(Allocator) defaultAllocator() nothrow @safe @nogc
 | 
				
			||||||
@@ -202,40 +203,32 @@ private unittest
 | 
				
			|||||||
    assert(p is null);
 | 
					    assert(p is null);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/*
 | 
				
			||||||
 * Destroys and deallocates $(D_PARAM p) of type $(D_PARAM T).
 | 
					 * Destroys the object.
 | 
				
			||||||
 * It is assumed the respective entities had been allocated with the same
 | 
					 * Returns the memory should be freed.
 | 
				
			||||||
 * 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, auto ref T* p)
 | 
					package(tanya) void[] finalize(T)(ref T* p)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    static if (hasElaborateDestructor!T)
 | 
					    static if (hasElaborateDestructor!T)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        destroy(*p);
 | 
					        destroy(*p);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    () @trusted { allocator.deallocate((cast(void*) p)[0 .. T.sizeof]); }();
 | 
					    return (cast(void*) p)[0 .. T.sizeof];
 | 
				
			||||||
    p = null;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Ditto.
 | 
					package(tanya) void[] finalize(T)(ref T p)
 | 
				
			||||||
void dispose(T)(shared Allocator allocator, auto ref T p)
 | 
					 | 
				
			||||||
    if (is(T == class) || is(T == interface))
 | 
					    if (is(T == class) || is(T == interface))
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (p is null)
 | 
					    if (p is null)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    static if (is(T == interface))
 | 
					    static if (is(T == interface))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        version(Windows)
 | 
					        version(Windows)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            import core.sys.windows.unknwn : IUnknown;
 | 
					            import core.sys.windows.unknwn : IUnknown;
 | 
				
			||||||
            static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in "
 | 
					            static assert(!is(T : IUnknown), "COM interfaces can't be destroyed in "
 | 
				
			||||||
                                           ~ __PRETTY_FUNCTION__);
 | 
					                                           ~ __PRETTY_FUNCTION__);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        auto ob = cast(Object) p;
 | 
					        auto ob = cast(Object) p;
 | 
				
			||||||
@@ -244,19 +237,13 @@ void dispose(T)(shared Allocator allocator, auto ref T p)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        alias ob = p;
 | 
					        alias ob = p;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    auto ptr = cast(void *) ob;
 | 
					    auto ptr = cast(void*) ob;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto support = ptr[0 .. typeid(ob).initializer.length];
 | 
					    auto support = ptr[0 .. typeid(ob).initializer.length];
 | 
				
			||||||
    scope (success)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        () @trusted { allocator.deallocate(support); }();
 | 
					 | 
				
			||||||
        p = null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto ppv = cast(void**) ptr;
 | 
					    auto ppv = cast(void**) ptr;
 | 
				
			||||||
    if (!*ppv)
 | 
					    if (!*ppv)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    auto pc = cast(ClassInfo*) *ppv;
 | 
					    auto pc = cast(ClassInfo*) *ppv;
 | 
				
			||||||
    scope (exit)
 | 
					    scope (exit)
 | 
				
			||||||
@@ -280,21 +267,35 @@ void dispose(T)(shared Allocator allocator, auto ref T p)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        _d_monitordelete(cast(Object) ptr, true);
 | 
					        _d_monitordelete(cast(Object) ptr, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    return support;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Ditto.
 | 
					package(tanya) void[] finalize(T)(ref T[] p)
 | 
				
			||||||
void dispose(T)(shared Allocator allocator, auto ref T[] p)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    static if (hasElaborateDestructor!(typeof(p[0])))
 | 
					    static if (hasElaborateDestructor!(typeof(p[0])))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        import std.algorithm.iteration;
 | 
					        p.each!((ref e) => destroy(e));
 | 
				
			||||||
        p.each!(e => destroy(e));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    () @trusted { allocator.deallocate(p); }();
 | 
					    return p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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, auto ref T p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    () @trusted { allocator.deallocate(finalize(p)); }();
 | 
				
			||||||
    p = null;
 | 
					    p = null;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unittest
 | 
					private unittest
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct S
 | 
					    struct S
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user