Designing with the GC out of mind
anonymous
anonymous at example.com
Tue Aug 6 10:17:47 PDT 2013
On Tuesday, 6 August 2013 at 14:27:32 UTC, Adam D. Ruppe wrote:
> and there's a gc proxy in the code but idk how to use it.
I have this little piece of hack that uses the proxy to disable
GC allocations at runtime. It's not tested well, so it probably
has some issues, but maybe it's a start for someone. See the
unittest for how to use.
CODE:
import std.exception: assertThrown;
import std.traits: ParameterTypeTuple, ReturnType;
static import core.memory;
/*NOTE: Deriving from Throwable instead of Exception, because
with Exception
catch(GCUsedWhenForbidden) doesn't work (dmd 2.063). */
class GCUsedWhenForbidden : Throwable
{
this(string gcProcName, string file = __FILE__, size_t line =
__LINE__)
{
super(gcProcName, file, line);
}
}
struct GC
{
static auto opDispatch(string n, A ...)(A args)
{
mixin("return core.memory.GC." ~ n ~ "(args);");
}
private static Proxy proxy;
static this()
{
foreach(name; __traits(allMembers, Proxy))
makeDie!name();
}
private shared static uint forbidCount = 0;
static void forbidUse()
{
if(forbidCount++ == 0) actuallyForbidUse;
}
private static void actuallyForbidUse()
{
makeNop!"gc_addRange"();
gc_setProxy(&proxy);
makeDie!"gc_addRange"();
}
static void allowUse()
{
if(--forbidCount == 0) actuallyAllowUse;
}
private static void actuallyAllowUse()
{
makeNop!"gc_removeRange"();
gc_clrProxy();
makeDie!"gc_removeRange"();
}
private static auto proxyMember(string name)()
{
mixin("return &proxy." ~ name ~ ";");
}
private static makeNop(string name)()
{
*proxyMember!name = &nop!(typeof(*proxyMember!name));
}
private static makeDie(string name)()
{
*proxyMember!name = &die!(typeof(*proxyMember!name), name);
}
}
unittest
{
int[] h = new int[1];
GC.forbidUse; // 1
assertThrown!GCUsedWhenForbidden(new int[1]);
GC.forbidUse; // 2
assertThrown!GCUsedWhenForbidden(new int[1]);
GC.allowUse; // 1
assertThrown!GCUsedWhenForbidden(new int[1]);
GC.allowUse; // 0
h = new int[1]; // now, GC can be used again
}
private extern(C) void nop(T)(ParameterTypeTuple!T) {}
private extern(C) ReturnType!T die(T, string
name)(ParameterTypeTuple!T)
{
GC.actuallyAllowUse;
scope(exit) GC.actuallyForbidUse;
throw new GCUsedWhenForbidden(name);
}
//NOTE: copied from druntime/src/gc/gc.d
private struct BlkInfo
{
void* base;
size_t size;
uint attr;
}
//NOTE: copied from druntime/src/gc/proxy.d
private struct Proxy
{
extern(C)
{
void function() gc_enable;
void function() gc_disable;
void function() gc_collect;
void function() gc_minimize;
uint function(void*) gc_getAttr;
uint function(void*, uint) gc_setAttr;
uint function(void*, uint) gc_clrAttr;
void* function(size_t, uint) gc_malloc;
BlkInfo function(size_t, uint) gc_qalloc;
void* function(size_t, uint) gc_calloc;
void* function(void*, size_t, uint ba) gc_realloc;
size_t function(void*, size_t, size_t) gc_extend;
size_t function(size_t) gc_reserve;
void function(void*) gc_free;
void* function(void*) gc_addrOf;
size_t function(void*) gc_sizeOf;
BlkInfo function(void*) gc_query;
void function(void*) gc_addRoot;
void function(void*, size_t) gc_addRange;
void function(void*) gc_removeRoot;
void function(void*) gc_removeRange;
}
}
//NOTE: copied from druntime/src/gc/proxy.d
private extern(C) void gc_setProxy(Proxy*);
private extern(C) void gc_clrProxy();
More information about the Digitalmars-d
mailing list