view lphobos/std/moduleinit.d @ 883:b52d5de7783f

GC defines and linkage changes.
author Christian Kamm <kamm incasoftware de>
date Thu, 08 Jan 2009 18:20:02 +0100
parents eef8ac26c66c
children
line wrap: on
line source
// Modified for LDC

module std.moduleinit;

//debug = 1;

private
{
    import object;
    import std.c.stdio;
    import std.c.stdlib;
}

enum
{   MIctorstart = 1,	// we've started constructing it
    MIctordone = 2,	// finished construction
    MIstandalone = 4,	// module ctor does not depend on other module
			// ctors being done first
}

// had to move the class to object.d, as its declaration is needed in the compiler code,
// otherwise the DMDFE Module::moduleinfo member is NULL

class ModuleCtorError : Exception
{
    this(ModuleInfo m)
    {
	super("circular initialization dependency with module " ~ m.name);
    }
}


// this gets initialized in _moduleCtor()
extern (C) ModuleInfo[] _moduleinfo_array;

// this method returns the linker constructed, null terminated, array of moduleinfos
extern (C) void** _d_get_moduleinfo_array();

ModuleInfo[] _moduleinfo_dtors;
uint _moduleinfo_dtors_i;

// Register termination function pointers
extern (C) int _fatexit(void *);

/*************************************
 * Initialize the modules.
 */

extern (C) void _moduleCtor()
{
    debug printf("_moduleCtor()\n");
	int len = 0;

	for (auto mr = _Dmodule_ref; mr; mr=mr.next)
	    len++;
	_moduleinfo_array = new ModuleInfo[len];
	len = 0;
	for (auto mr = _Dmodule_ref; mr; mr=mr.next)
	{   _moduleinfo_array[len] = mr.mod;
	    len++;
	}

    version (Win32)
    {
	// Ensure module destructors also get called on program termination
	//_fatexit(&_STD_moduleDtor);
    }

    _moduleinfo_dtors = new ModuleInfo[len];
    debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
    _moduleCtor2(_moduleinfo_array, 0);

    version (none)
    {
	foreach (m; _moduleinfo_array)
	{
	    writefln("module %s, %d", m.name, m.localClasses.length);
	    foreach (c; m.localClasses)
	    {
		writefln("\tclass %s", c.name);
	    }
	}
    }
}

void _moduleCtor2(ModuleInfo[] mi, int skip)
{
    debug printf("_moduleCtor2(): %d modules\n", mi.length);
    for (uint i = 0; i < mi.length; i++)
    {
	ModuleInfo m = mi[i];

	debug printf("\tmodule[%d] = '%p'\n", i, m);
	if (!m)
	    continue;
	debug printf("\tmodule[%d] = '%.*s'\n", i, m.name.length, m.name.ptr);
	if (m.flags & MIctordone)
	    continue;
	debug printf("\tmodule[%d] = '%.*s', m = 0x%x\n", i, m.name.length, m.name.ptr, m);

	if (m.ctor || m.dtor)
	{
	    if (m.flags & MIctorstart)
	    {	if (skip || m.flags & MIstandalone)
		    continue;
		debug printf("\tmodule[%d] = '%.*s', cyclic dependency!\n", i, m.name.length, m.name.ptr);
		int x = 0; x /= x;
		throw new ModuleCtorError(m);
	    }

	    m.flags |= MIctorstart;
	    _moduleCtor2(m.importedModules, 0);
	    if (m.ctor)
		(*m.ctor)();
	    m.flags &= ~MIctorstart;
	    m.flags |= MIctordone;

	    // Now that construction is done, register the destructor
	    //printf("\tadding module dtor x%x\n", m);
	    assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
	    _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
	}
	else
	{
	    m.flags |= MIctordone;
	    _moduleCtor2(m.importedModules, 1);
	}
    }
}


/**********************************
 * Destruct the modules.
 */

// Starting the name with "_STD" means under linux a pointer to the
// function gets put in the .dtors segment.

extern (C) void _moduleDtor()
{
    debug printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
    for (uint i = _moduleinfo_dtors_i; i-- != 0;)
    {
	ModuleInfo m = _moduleinfo_dtors[i];

	debug printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
	if (m.dtor)
	{
	    (*m.dtor)();
	}
    }
    debug printf("_moduleDtor() done\n");
}

/**********************************
 * Run unit tests.
 */

extern (C) void _moduleUnitTests()
{
    debug printf("_moduleUnitTests() %i\n", _moduleinfo_array.length);
    for (uint i = 0; i < _moduleinfo_array.length; i++)
    {
	ModuleInfo m = _moduleinfo_array[i];

	if (!m)
	    continue;

	debug printf("\tmodule[%d] = '%.*s'\n", i, m.name);
	if (m.unitTest)
	{
	    (*m.unitTest)();
	}
    }
}