Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Leave Comments, Critiques, and Suggestions Here?

Library Integration Guide

The Tango runtime is made up of three logically separate parts: a compiler runtime library, a garbage collector, and a common application layer. Each of these parts represents a specific subset of functionality required for the proper functioning of any D program, and each may only interact with the others through a set of well-defined C routines, enumerated below. Any remaining external dependencies should be limited to standard or platform-specific C libraries. The rationale behind this design is to simplify the addition of support for new compilers, memory management strategies, and so on, and to allow the appropriate set of features to be chosen by the user at link-time.

These sub-libraries interact via a set of well-defined function calls and they do not refer to one another during any stage of the build process.

The garbage collector must expose these functions:

    extern (C) void   gc_init();
    extern (C) void   gc_term();

    extern (C) void   gc_enable();
    extern (C) void   gc_disable();
    extern (C) void   gc_collect();
    extern (C) void   gc_minimize();

    extern (C) uint   gc_getAttr( void* p );
    extern (C) uint   gc_setAttr( void* p, uint a );
    extern (C) uint   gc_clrAttr( void* p, uint a );

    extern (C) void*  gc_malloc( size_t sz, uint ba = 0 );
    extern (C) void*  gc_calloc( size_t sz, uint ba = 0 );
    extern (C) void*  gc_realloc( void* p, size_t sz, uint ba = 0 );
    extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
    extern (C) size_t gc_reserve( size_t sz );
    extern (C) void   gc_free( void* p );

    extern (C) void*  gc_addrOf( void* p );
    extern (C) size_t gc_sizeOf( void* p );

    struct BlkInfo
    {
        void*  base;
        size_t size;
        uint   attr;
    }

    extern (C) BlkInfo gc_query( void* p );

    extern (C) void   gc_addRoot( void* p );
    extern (C) void   gc_addRange( void* p, size_t sz );

    extern (C) void   gc_removeRoot( void* p );
    extern (C) void   gc_removeRange( void* p );

Bit significance of the uint value used for block attribute passing is as follows, by position:

0: Block contains a class - finalize this block on collection
1: Block contains no pointers - do not scan through this block on collections
2: Block is pinned - do not move this block during collections
3-15: Reserved for future use by Tango
16-31: Reserved for internal use by the garbage collector and compiler

The common library must expose these functions:

    extern (C) void onArrayBoundsError( char[] file, size_t line );
    extern (C) void onAssertError( char[] file, uint line );
    extern (C) void onAssertErrorMsg( char[] file, uint line, char[] msg );
    extern (C) void onFinalizeError( ClassInfo info, Exception ex );
    extern (C) void onOutOfMemoryError();
    extern (C) void onSwitchError( char[] file, size_t line );
    extern (C) void onUnicodeError( char[] msg, size_t idx );

    extern (C) void thread_init();
    extern (C) void thread_joinAll();
    extern (C) bit  thread_needLock();
    extern (C) void thread_suspendAll();
    extern (C) void thread_scanAll( void delegate( void*, void* ) scan, void* curStackTop = null );
    extern (C) void thread_resumeAll();
    extern (C) void thread_attachThis();
    extern (C) void thread_detachThis();

The compiler runtime must expose these functions and data:

    extern (C) bool  rt_init( void delegate( Exception ) dg = null );
    extern (C) bool  rt_term( void delegate( Exception ) dg = null );
    extern (C) void* rt_stackBottom();
    extern (C) void* rt_stackTop();
    extern (C) void  rt_scanStaticData( void delegate( void*, void* ) scan );
    extern (C) void  rt_setCollectHandler( void function(Object) h );
    extern (C) void  rt_finalize( void* p, bool det = true );
    extern (C) bool  rt_isHalting();
    extern (C) bool  rt_trapExceptions = true;

    extern (C) void  rt_attachDisposeEvent( Object obj, void delegate(Object) evt );
    extern (C) void  rt_detachDisposeEvent( Object obj, void delegate(Object) evt );
    extern (C) void  rt_setTraceHandler( Exception.TraceInfo function( void* ptr = null ) h );

TraceInfo must be defined as follows:

class Exception : Object
{
    interface TraceInfo
    {
        int opApply( int delegate( inout char[] ) );
        char[] toString();
    }
}

Given the following interface:

    class Object
    {
        interface Monitor
        {
            void lock();
            void unlock();
        }
    }

Object monitors must be structured like so:

    alias Object.Monitor IMonitor;

    struct Monitor
    {
        IMonitor impl;
        /* data */
    }

If impl is null then the default monitor implementation will be used. Otherwise, monitor locking and unlocking will be performed via impl. Additionally, the use of rt_attachDisposeEvent and rt_detachDisposeEvent is only supported on objects without user-defined monitors. The reasoning is that objects with user-defined monitors may have special lifetime or storage requirements that invalidate any reason for the lifetime monitoring feature.

Also, the top-level package names "rt" and "gc" are reserved for use by the compiler runtime and the garbage collector, respectively.