Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
The GC will now call destructors on heap allocated structs. It is imp…
Browse files Browse the repository at this point in the history
…ossible to feasibly implement the invokation of arrays of finalizable structs, due to the inability to know which elements in the array, which may, or may not have been, initialized to begin with. There is also no way to know what the actual length of the array is, you can know how much memory was allocated for it, but not whether there was ever a reference to that point in the array. The destructors for structs in classes are still called as they were previously, which is immediately after the body of the outer class's finalizer.
  • Loading branch information
Orvid committed Jan 13, 2015
1 parent 0815912 commit 3f06283
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 27 deletions.
1 change: 1 addition & 0 deletions mak/SRCS
Expand Up @@ -78,6 +78,7 @@ SRCS=\
src\gc\bits.d \
src\gc\config.d \
src\gc\stats.d \
src\gc\structinfo.d \
src\gc\proxy.d \
\
src\rt\aApply.d \
Expand Down
83 changes: 83 additions & 0 deletions src/core/exception.d
Expand Up @@ -181,6 +181,71 @@ unittest
}
}

/**
* Thrown on struct finalize error.
*/
class StructFinalizeError : Error
{
StructInfo info;

@safe pure nothrow this( StructInfo si, Throwable next, string file = __FILE__, size_t line = __LINE__ )
{
this(si, file, line, next);
}

@safe pure nothrow this( StructInfo si, string file = __FILE__, size_t line = __LINE__, Throwable next = null )
{
super( "Finalization error", file, line, next );
info = si;
}

@safe override const string toString()
{
return "An exception was thrown while finalizing an instance of struct " ~ info.name;
}
}

unittest
{
StructInfo info = new StructInfo;
info.name = "testInfo";

{
auto fe = new StructFinalizeError(info);
assert(fe.file == __FILE__);
assert(fe.line == __LINE__ - 2);
assert(fe.next is null);
assert(fe.msg == "Finalization error");
assert(fe.info == info);
}

{
auto fe = new StructFinalizeError(info, new Exception("It's an Exception!"));
assert(fe.file == __FILE__);
assert(fe.line == __LINE__ - 2);
assert(fe.next !is null);
assert(fe.msg == "Finalization error");
assert(fe.info == info);
}

{
auto fe = new StructFinalizeError(info, "hello", 42);
assert(fe.file == "hello");
assert(fe.line == 42);
assert(fe.next is null);
assert(fe.msg == "Finalization error");
assert(fe.info == info);
}

{
auto fe = new StructFinalizeError(info, "hello", 42, new Exception("It's an Exception!"));
assert(fe.file == "hello");
assert(fe.line == 42);
assert(fe.next !is null);
assert(fe.msg == "Finalization error");
assert(fe.info == info);
}
}

/**
* Thrown on hidden function error.
Expand Down Expand Up @@ -488,6 +553,24 @@ extern (C) void onFinalizeError( ClassInfo info, Throwable e, string file = __FI
}


/**
* A callback for struct finalize errors in D. A StructFinalizeError will be thrown.
*
* Params:
* info = The StructInfo instance for the object that failed finalization.
* e = The exception thrown during finalization.
* file = The name of the file that signaled this error.
* line = The line number on which this error occurred.
*
* Throws:
* FinalizeError.
*/
extern (C) void onStructFinalizeError( StructInfo info, Throwable e, string file = __FILE__, size_t line = __LINE__ ) @safe pure nothrow
{
throw new StructFinalizeError( info, file, line, e );
}


/**
* A callback for hidden function errors in D. A $(LREF HiddenFuncError) will be
* thrown.
Expand Down
1 change: 1 addition & 0 deletions src/core/memory.d
Expand Up @@ -220,6 +220,7 @@ struct GC
and is only implemented for data structures at least a page in size.
*/
NO_INTERIOR = 0b0001_0000,
STRUCT_FINALIZE = 0b0010_0000, /// Finalize the struct data in this block on collect.
}


Expand Down

0 comments on commit 3f06283

Please sign in to comment.