|  | /** | 
|  | * Contains the external GC interface. | 
|  | * | 
|  | * Copyright: Copyright Digital Mars 2005 - 2016. | 
|  | * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). | 
|  | * Authors:   Walter Bright, Sean Kelly | 
|  | */ | 
|  |  | 
|  | /*          Copyright Digital Mars 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.proxy; | 
|  |  | 
|  | import gc.impl.conservative.gc; | 
|  | import gc.impl.manual.gc; | 
|  | import gc.config; | 
|  | import gc.gcinterface; | 
|  |  | 
|  | static import core.memory; | 
|  |  | 
|  | private | 
|  | { | 
|  | static import core.memory; | 
|  | alias BlkInfo = core.memory.GC.BlkInfo; | 
|  |  | 
|  | extern (C) void thread_init(); | 
|  | extern (C) void thread_term(); | 
|  |  | 
|  | __gshared GC instance; | 
|  | __gshared GC proxiedGC; // used to iterate roots of Windows DLLs | 
|  |  | 
|  | } | 
|  |  | 
|  |  | 
|  | extern (C) | 
|  | { | 
|  |  | 
|  | void gc_init() | 
|  | { | 
|  | config.initialize(); | 
|  | ManualGC.initialize(instance); | 
|  | ConservativeGC.initialize(instance); | 
|  | if (instance is null) | 
|  | { | 
|  | import core.stdc.stdio : fprintf, stderr; | 
|  | import core.stdc.stdlib : exit; | 
|  |  | 
|  | fprintf(stderr, "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr); | 
|  | exit(1); | 
|  | } | 
|  |  | 
|  | // NOTE: The GC must initialize the thread library | 
|  | //       before its first collection. | 
|  | thread_init(); | 
|  | } | 
|  |  | 
|  | void gc_term() | 
|  | { | 
|  | // NOTE: There may be daemons threads still running when this routine is | 
|  | //       called.  If so, cleaning memory out from under then is a good | 
|  | //       way to make them crash horribly.  This probably doesn't matter | 
|  | //       much since the app is supposed to be shutting down anyway, but | 
|  | //       I'm disabling cleanup for now until I can think about it some | 
|  | //       more. | 
|  | // | 
|  | // NOTE: Due to popular demand, this has been re-enabled.  It still has | 
|  | //       the problems mentioned above though, so I guess we'll see. | 
|  |  | 
|  | instance.collectNoStack(); // not really a 'collect all' -- still scans | 
|  | // static data area, roots, and ranges. | 
|  |  | 
|  | thread_term(); | 
|  |  | 
|  | ManualGC.finalize(instance); | 
|  | ConservativeGC.finalize(instance); | 
|  | } | 
|  |  | 
|  | void gc_enable() | 
|  | { | 
|  | instance.enable(); | 
|  | } | 
|  |  | 
|  | void gc_disable() | 
|  | { | 
|  | instance.disable(); | 
|  | } | 
|  |  | 
|  | void gc_collect() nothrow | 
|  | { | 
|  | instance.collect(); | 
|  | } | 
|  |  | 
|  | void gc_minimize() nothrow | 
|  | { | 
|  | instance.minimize(); | 
|  | } | 
|  |  | 
|  | uint gc_getAttr( void* p ) nothrow | 
|  | { | 
|  | return instance.getAttr(p); | 
|  | } | 
|  |  | 
|  | uint gc_setAttr( void* p, uint a ) nothrow | 
|  | { | 
|  | return instance.setAttr(p, a); | 
|  | } | 
|  |  | 
|  | uint gc_clrAttr( void* p, uint a ) nothrow | 
|  | { | 
|  | return instance.clrAttr(p, a); | 
|  | } | 
|  |  | 
|  | void* gc_malloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow | 
|  | { | 
|  | return instance.malloc(sz, ba, ti); | 
|  | } | 
|  |  | 
|  | BlkInfo gc_qalloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow | 
|  | { | 
|  | return instance.qalloc( sz, ba, ti ); | 
|  | } | 
|  |  | 
|  | void* gc_calloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow | 
|  | { | 
|  | return instance.calloc( sz, ba, ti ); | 
|  | } | 
|  |  | 
|  | void* gc_realloc( void* p, size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow | 
|  | { | 
|  | return instance.realloc( p, sz, ba, ti ); | 
|  | } | 
|  |  | 
|  | size_t gc_extend( void* p, size_t mx, size_t sz, const TypeInfo ti = null ) nothrow | 
|  | { | 
|  | return instance.extend( p, mx, sz,ti ); | 
|  | } | 
|  |  | 
|  | size_t gc_reserve( size_t sz ) nothrow | 
|  | { | 
|  | return instance.reserve( sz ); | 
|  | } | 
|  |  | 
|  | void gc_free( void* p ) nothrow | 
|  | { | 
|  | return instance.free( p ); | 
|  | } | 
|  |  | 
|  | void* gc_addrOf( void* p ) nothrow | 
|  | { | 
|  | return instance.addrOf( p ); | 
|  | } | 
|  |  | 
|  | size_t gc_sizeOf( void* p ) nothrow | 
|  | { | 
|  | return instance.sizeOf( p ); | 
|  | } | 
|  |  | 
|  | BlkInfo gc_query( void* p ) nothrow | 
|  | { | 
|  | return instance.query( p ); | 
|  | } | 
|  |  | 
|  | core.memory.GC.Stats gc_stats() nothrow | 
|  | { | 
|  | return instance.stats(); | 
|  | } | 
|  |  | 
|  | void gc_addRoot( void* p ) nothrow | 
|  | { | 
|  | return instance.addRoot( p ); | 
|  | } | 
|  |  | 
|  | void gc_addRange( void* p, size_t sz, const TypeInfo ti = null ) nothrow | 
|  | { | 
|  | return instance.addRange( p, sz, ti ); | 
|  | } | 
|  |  | 
|  | void gc_removeRoot( void* p ) nothrow | 
|  | { | 
|  | return instance.removeRoot( p ); | 
|  | } | 
|  |  | 
|  | void gc_removeRange( void* p ) nothrow | 
|  | { | 
|  | return instance.removeRange( p ); | 
|  | } | 
|  |  | 
|  | void gc_runFinalizers( in void[] segment ) nothrow | 
|  | { | 
|  | return instance.runFinalizers( segment ); | 
|  | } | 
|  |  | 
|  | bool gc_inFinalizer() nothrow | 
|  | { | 
|  | return instance.inFinalizer(); | 
|  | } | 
|  |  | 
|  | GC gc_getProxy() nothrow | 
|  | { | 
|  | return instance; | 
|  | } | 
|  |  | 
|  | export | 
|  | { | 
|  | void gc_setProxy( GC proxy ) | 
|  | { | 
|  | foreach (root; instance.rootIter) | 
|  | { | 
|  | proxy.addRoot(root); | 
|  | } | 
|  |  | 
|  | foreach (range; instance.rangeIter) | 
|  | { | 
|  | proxy.addRange(range.pbot, range.ptop - range.pbot, range.ti); | 
|  | } | 
|  |  | 
|  | proxiedGC = instance; // remember initial GC to later remove roots | 
|  | instance = proxy; | 
|  | } | 
|  |  | 
|  | void gc_clrProxy() | 
|  | { | 
|  | foreach (root; proxiedGC.rootIter) | 
|  | { | 
|  | instance.removeRoot(root); | 
|  | } | 
|  |  | 
|  | foreach (range; proxiedGC.rangeIter) | 
|  | { | 
|  | instance.removeRange(range); | 
|  | } | 
|  |  | 
|  | instance = proxiedGC; | 
|  | proxiedGC = null; | 
|  | } | 
|  | } | 
|  | } |