diff --git a/source/vibe/container/internal/utilallocator.d b/source/vibe/container/internal/utilallocator.d index c4881a1..82cfb6e 100644 --- a/source/vibe/container/internal/utilallocator.d +++ b/source/vibe/container/internal/utilallocator.d @@ -2,6 +2,7 @@ module vibe.container.internal.utilallocator; public import stdx.allocator : allocatorObject, CAllocatorImpl, dispose, expandArray, IAllocator, make, makeArray, shrinkArray, theAllocator; +public import stdx.allocator.gc_allocator; public import stdx.allocator.mallocator; public import stdx.allocator.building_blocks.affix_allocator; @@ -15,6 +16,52 @@ public import stdx.allocator.building_blocks.affix_allocator; return s_threadAllocator; } +auto makeGCSafe(T, Allocator, A...)(Allocator allocator, A args) +{ + import core.memory : GC; + import std.traits : hasIndirections; + + auto ret = allocator.make!T(args); + static if (is (T == class)) enum tsize = __traits(classInstanceSize, T); + else enum tsize = T.sizeof; + static if (hasIndirections!T) + () @trusted { GC.addRange(cast(void*)ret, tsize, typeid(T)); } (); + return ret; +} + +void disposeGCSafe(T, Allocator)(Allocator allocator, T obj) +{ + import core.memory : GC; + import std.traits : hasIndirections; + + static if (hasIndirections!T) + GC.removeRange(cast(void*)obj); + allocator.dispose(obj); +} + +void ensureNotInGC(T)(string info = null) nothrow +{ + import core.exception : InvalidMemoryOperationError; + try + { + import core.memory : GC; + cast(void) GC.malloc(1); + return; + } + catch(InvalidMemoryOperationError e) + { + import core.stdc.stdio : fprintf, stderr; + import core.stdc.stdlib : exit; + fprintf(stderr, + "Error: clean-up of %s incorrectly depends on destructors called by the GC.\n", + T.stringof.ptr); + if (info) + fprintf(stderr, "Info: %s\n", info.ptr); + assert(false); + } +} + + final class RegionListAllocator(Allocator, bool leak = false) : IAllocator { import vibe.internal.memory_legacy : AllocSize, alignedSize; import std.algorithm.comparison : min, max; @@ -113,9 +160,9 @@ final class RegionListAllocator(Allocator, bool leak = false) : IAllocator { override Ternary resolveInternalPointer(void* p, ref void[] result) { return Ternary.unknown; } } static if (is(Parameters!(IAllocator.owns)[0] == const(void[]))) { - override Ternary owns(const void[] b) { return Ternary.unknown; } + override Ternary owns(const void[] b) { return Ternary.unknown; } } else { - override Ternary owns(void[] b) { return Ternary.unknown; } + override Ternary owns(void[] b) { return Ternary.unknown; } }