Retro68/gcc/libphobos/libdruntime/gc/impl/manual/gc.d
Wolfgang Thaller 6fbf4226da gcc-9.1
2019-06-20 20:10:10 +02:00

275 lines
6.0 KiB
D

/**
* This module contains a minimal garbage collector implementation according to
* published requirements. This library is mostly intended to serve as an
* example, but it is usable in applications which do not rely on a garbage
* collector to clean up memory (ie. when dynamic array resizing is not used,
* and all memory allocated with 'new' is freed deterministically with
* 'delete').
*
* Please note that block attribute data must be tracked, or at a minimum, the
* FINALIZE bit must be tracked for any allocated memory block because calling
* rt_finalize on a non-object block can result in an access violation. In the
* allocator below, this tracking is done via a leading uint bitmask. A real
* allocator may do better to store this data separately, similar to the basic
* GC.
*
* Copyright: Copyright Sean Kelly 2005 - 2016.
* License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
* Authors: Sean Kelly
*/
/* Copyright Sean Kelly 2005 - 2016.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
module gc.impl.manual.gc;
import gc.config;
import gc.gcinterface;
import rt.util.container.array;
import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc;
static import core.memory;
extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */
class ManualGC : GC
{
__gshared Array!Root roots;
__gshared Array!Range ranges;
static void initialize(ref GC gc)
{
import core.stdc.string;
if (config.gc != "manual")
return;
auto p = cstdlib.malloc(__traits(classInstanceSize, ManualGC));
if (!p)
onOutOfMemoryError();
auto init = typeid(ManualGC).initializer();
assert(init.length == __traits(classInstanceSize, ManualGC));
auto instance = cast(ManualGC) memcpy(p, init.ptr, init.length);
instance.__ctor();
gc = instance;
}
static void finalize(ref GC gc)
{
if (config.gc != "manual")
return;
auto instance = cast(ManualGC) gc;
instance.Dtor();
cstdlib.free(cast(void*) instance);
}
this()
{
}
void Dtor()
{
}
void enable()
{
}
void disable()
{
}
void collect() nothrow
{
}
void collectNoStack() nothrow
{
}
void minimize() nothrow
{
}
uint getAttr(void* p) nothrow
{
return 0;
}
uint setAttr(void* p, uint mask) nothrow
{
return 0;
}
uint clrAttr(void* p, uint mask) nothrow
{
return 0;
}
void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow
{
void* p = cstdlib.malloc(size);
if (size && p is null)
onOutOfMemoryError();
return p;
}
BlkInfo qalloc(size_t size, uint bits, const TypeInfo ti) nothrow
{
BlkInfo retval;
retval.base = malloc(size, bits, ti);
retval.size = size;
retval.attr = bits;
return retval;
}
void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow
{
void* p = cstdlib.calloc(1, size);
if (size && p is null)
onOutOfMemoryError();
return p;
}
void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow
{
p = cstdlib.realloc(p, size);
if (size && p is null)
onOutOfMemoryError();
return p;
}
size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti) nothrow
{
return 0;
}
size_t reserve(size_t size) nothrow
{
return 0;
}
void free(void* p) nothrow
{
cstdlib.free(p);
}
/**
* Determine the base address of the block containing p. If p is not a gc
* allocated pointer, return null.
*/
void* addrOf(void* p) nothrow
{
return null;
}
/**
* Determine the allocated size of pointer p. If p is an interior pointer
* or not a gc allocated pointer, return 0.
*/
size_t sizeOf(void* p) nothrow
{
return 0;
}
/**
* Determine the base address of the block containing p. If p is not a gc
* allocated pointer, return null.
*/
BlkInfo query(void* p) nothrow
{
return BlkInfo.init;
}
core.memory.GC.Stats stats() nothrow
{
return typeof(return).init;
}
void addRoot(void* p) nothrow @nogc
{
roots.insertBack(Root(p));
}
void removeRoot(void* p) nothrow @nogc
{
foreach (ref r; roots)
{
if (r is p)
{
r = roots.back;
roots.popBack();
return;
}
}
assert(false);
}
@property RootIterator rootIter() return @nogc
{
return &rootsApply;
}
private int rootsApply(scope int delegate(ref Root) nothrow dg)
{
foreach (ref r; roots)
{
if (auto result = dg(r))
return result;
}
return 0;
}
void addRange(void* p, size_t sz, const TypeInfo ti = null) nothrow @nogc
{
ranges.insertBack(Range(p, p + sz, cast() ti));
}
void removeRange(void* p) nothrow @nogc
{
foreach (ref r; ranges)
{
if (r.pbot is p)
{
r = ranges.back;
ranges.popBack();
return;
}
}
assert(false);
}
@property RangeIterator rangeIter() return @nogc
{
return &rangesApply;
}
private int rangesApply(scope int delegate(ref Range) nothrow dg)
{
foreach (ref r; ranges)
{
if (auto result = dg(r))
return result;
}
return 0;
}
void runFinalizers(in void[] segment) nothrow
{
}
bool inFinalizer() nothrow
{
return false;
}
}