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

Commit

Permalink
Merge pull request #75 from CyberShadow/add-invalidmemoryoperation
Browse files Browse the repository at this point in the history
Add InvalidMemoryOperationError to indicate garbage collector errors
  • Loading branch information
complexmath committed Sep 24, 2011
2 parents 86442f9 + 7d159ea commit 9270d5a
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 6 deletions.
57 changes: 57 additions & 0 deletions src/core/exception.d
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,47 @@ unittest
}


/**
* Thrown on an invalid memory operation.
*
* An invalid memory operation error occurs in circumstances when the garbage
* collector has detected an operation it cannot reliably handle. The default
* D GC is not re-entrant, so this can happen due to allocations done from
* within finalizers called during a garbage collection cycle.
*/
class InvalidMemoryOperationError : Error
{
this(string file = __FILE__, size_t line = __LINE__, Throwable next = null )
{
super( "Invalid memory operation", file, line, next );
}

override string toString()
{
return msg ? super.toString() : "Invalid memory operation";
}
}

unittest
{
{
auto oome = new InvalidMemoryOperationError();
assert(oome.file == __FILE__);
assert(oome.line == __LINE__ - 2);
assert(oome.next is null);
assert(oome.msg == "Invalid memory operation");
}

{
auto oome = new InvalidMemoryOperationError("hello", 42, new Exception("It's an Exception!"));
assert(oome.file == "hello");
assert(oome.line == 42);
assert(oome.next !is null);
assert(oome.msg == "Invalid memory operation");
}
}


/**
* Thrown on a switch error.
*/
Expand Down Expand Up @@ -462,6 +503,22 @@ extern (C) void onOutOfMemoryError()
}


/**
* A callback for invalid memory operations in D. An
* InvalidMemoryOperationError will be thrown.
*
* Throws:
* InvalidMemoryOperationError.
*/
extern (C) void onInvalidMemoryOperationError()
{
// The same restriction applies as for onOutOfMemoryError. The GC is in an
// undefined state, thus no allocation must occur while generating this object.
throw cast(InvalidMemoryOperationError)
cast(void*) InvalidMemoryOperationError.classinfo.init;
}


/**
* A callback for switch errors in D. A SwitchError will be thrown.
*
Expand Down
13 changes: 7 additions & 6 deletions src/gc/gcx.d
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ private
}

extern (C) void onOutOfMemoryError();
extern (C) void onInvalidMemoryOperationError();

enum
{
Expand Down Expand Up @@ -456,7 +457,7 @@ class GC
//debug(PRINTF) printf("gcx.self = %x, pthread_self() = %x\n", gcx.self, pthread_self());

if (gcx.running)
onOutOfMemoryError();
onInvalidMemoryOperationError();

size += SENTINEL_EXTRA;
bin = gcx.findBin(size);
Expand Down Expand Up @@ -587,7 +588,7 @@ class GC
private void *reallocNoSync(void *p, size_t size, uint bits = 0, size_t *alloc_size = null)
{
if (gcx.running)
onOutOfMemoryError();
onInvalidMemoryOperationError();

if (!size)
{ if (p)
Expand Down Expand Up @@ -768,7 +769,7 @@ class GC
body
{
if (gcx.running)
onOutOfMemoryError();
onInvalidMemoryOperationError();

//debug(PRINTF) printf("GC::extend(p = %p, minsize = %zu, maxsize = %zu)\n", p, minsize, maxsize);
version (SENTINEL)
Expand Down Expand Up @@ -859,7 +860,7 @@ class GC
assert(gcx);

if (gcx.running)
onOutOfMemoryError();
onInvalidMemoryOperationError();

return gcx.reserve(size);
}
Expand Down Expand Up @@ -895,7 +896,7 @@ class GC
assert (p);

if (gcx.running)
onOutOfMemoryError();
onInvalidMemoryOperationError();

Pool* pool;
size_t pagenum;
Expand Down Expand Up @@ -2465,7 +2466,7 @@ struct Gcx
//printf("\tpool address range = %p .. %p\n", minAddr, maxAddr);

if (running)
onOutOfMemoryError();
onInvalidMemoryOperationError();
running = 1;

thread_suspendAll();
Expand Down

0 comments on commit 9270d5a

Please sign in to comment.