Skip to content
This repository was archived by the owner on Jan 7, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions source/lifetime/common.d
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,35 @@ package void zeroMem(void* ptr, const size_t length) pure nothrow @nogc {
foreach(i; 0 .. length) {
ptru[i] = 0;
}
}

void emplaceInitializer(T)(scope ref T chunk) nothrow pure @trusted
if (!is(T == const) && !is(T == immutable) && !is(T == inout))
{
import core.internal.traits : hasElaborateAssign;

static if (__traits(isZeroInit, T))
{
import core.stdc.string : memset;
memset(cast(void*) &chunk, 0, T.sizeof);
}
else static if (__traits(isScalar, T) ||
T.sizeof <= 16 && !hasElaborateAssign!T && __traits(compiles, (){ T chunk; chunk = T.init; }))
{
chunk = T.init;
}
else static if (__traits(isStaticArray, T))
{
// For static arrays there is no initializer symbol created. Instead, we emplace elements one-by-one.
foreach (i; 0 .. T.length)
{
emplaceInitializer(chunk[i]);
}
}
else
{
import core.stdc.string : memcpy;
const initializer = __traits(initSymbol, T);
memcpy(cast(void*)&chunk, initializer.ptr, initializer.length);
}
}
29 changes: 29 additions & 0 deletions source/lifetime/destruction.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module lifetime.destruction;

//Copy pasted from druntime

void __ArrayDtor(T)(scope T[] a)
{
foreach_reverse (ref T e; a)
e.__xdtor();
}

public void destructRecurse(E, size_t n)(ref E[n] arr)
{
import core.internal.traits : hasElaborateDestructor;

static if (hasElaborateDestructor!E)
{
foreach_reverse (ref elem; arr)
destructRecurse(elem);
}
}

public void destructRecurse(S)(ref S s)
if (is(S == struct))
{
static if (__traits(hasMember, S, "__xdtor") &&
// Bugzilla 14746: Check that it's the exact member of S.
__traits(isSame, S, __traits(parent, s.__xdtor)))
s.__xdtor();
}
64 changes: 64 additions & 0 deletions source/object.d
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public import lifetime.array_ : _d_arraysetlengthTImpl, _d_newarrayU;

public import lwdr.string_switch : __switch;
public import core.internal.switch_ : __switch_error; //final switch
public import lifetime.destruction: __ArrayDtor;


public import rt.arrcast : __ArrayCast;
Expand Down Expand Up @@ -884,4 +885,67 @@ const:
auto p = cast(immutable char*) addrOf(MIname);
return p[0 .. strlen(p)];
}
}

/**
Copy pasted from druntime destroy functions


Destroys the given object and optionally resets to initial state. It's used to
_destroy an object, calling its destructor or finalizer so it no longer
references any other objects. It does $(I not) initiate a GC cycle or free
any GC memory.
If `initialize` is supplied `false`, the object is considered invalid after
destruction, and should not be referenced.
*/
void destroy(bool initialize = true, T)(ref T obj) if (is(T == struct))
{
import lifetime.destruction : destructRecurse;

destructRecurse(obj);

static if (initialize)
{
import lifetime.common : emplaceInitializer;
emplaceInitializer(obj); // emplace T.init
}
}


/// ditto
void destroy(bool initialize = true, T)(T obj) if (is(T == class))
{
static if (__traits(getLinkage, T) == "C++")
{
static if (__traits(hasMember, T, "__xdtor"))
obj.__xdtor();

static if (initialize)
{
const initializer = __traits(initSymbol, T);
(cast(void*)obj)[0 .. initializer.length] = initializer[];
}
}
else
{
// Bypass overloaded opCast
auto ptr = (() @trusted => *cast(void**) &obj)();
rt_finalize2(ptr, true, initialize);
}
}

/// ditto
void destroy(bool initialize = true, T)(T obj) if (is(T == interface))
{
static assert(__traits(getLinkage, T) == "D", "Invalid call to destroy() on extern(" ~ __traits(getLinkage, T) ~ ") interface");

destroy!initialize(cast(Object)obj);
}

/// ditto
void destroy(bool initialize = true, T)(ref T obj)
if (!is(T == struct) && !is(T == interface) && !is(T == class) && !__traits(isStaticArray, T))
{
static if (initialize)
obj = T.init;
}