Add internal finalize method for finalizing an object without deallocating

This commit is contained in:
Eugen Wissner 2017-04-16 20:13:20 +02:00
parent 8156d0fe3a
commit 7aa9ac9f4a

View File

@ -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,41 +203,33 @@ 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
{ {