Mercurial > projects > mde
view mde/init.d @ 6:dcb24afa0dce
Some fixes from mde/text/format.d unittests plus a few more fixes.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Thu, 10 Jan 2008 18:33:24 +0000 |
parents | 9a990644948c |
children | f63f4f41a2dc |
line wrap: on
line source
/************************************************************************************************** * Initialisation setup and exit cleanup module. * * This module controls most of the initialisation and deinitialisation of the program. *************************************************************************************************/ module mde.init; import mde.exception; import mde.input.input; // tango imports import tango.core.Thread; import tango.util.log.Log : Log, Logger; import tango.util.log.ConsoleAppender : ConsoleAppender; import derelict.sdl.sdl; import derelict.util.exception; /** * Static CTOR * * This should handle a minimal amount of functionality where useful. For instance, configuring the * logger here and not in Init allows unittests to use the logger. */ static this() { // For now, just log to the console: Logger root = Log.getRootLogger(); root.setLevel(root.Level.Trace); root.addAppender(new ConsoleAppender); } static ~this() { } /** * Init class * * A scope class created at beginning of the program and destroyed at the end; thus the CTOR * handles program initialisation and the DTOR handles program cleanup. */ scope class Init { static Logger logger; static this() { logger = Log.getLogger ("mde.init.Init"); } /** CTOR − initialisation * * Runs general initialisation code, in a threaded manner where this isn't difficult. * * If this fails by throwing an exception, it must run necessary cleanup first since the DTOR * cannot be run. */ /* In a single-threaded function this could be done with: * scope(failure) cleanup; * This won't work with a threaded init function since any threads completing succesfully will * not clean-up, and a fixed list of clean-up functions cannot be used since clean-up functions * must not run where the initialisation functions have failed. * Hence a list of clean-up functions is built similarly to scope(failure) --- see addCleanupFct. */ this() { // Start all threads ThreadGroup tg = new ThreadGroup; tg.create(&initSDL); // Do some initialisation in the main thread Input.instance.loadConfig (0); // Wait for all threads to complete try { tg.joinAll (true); // rethrows any exceptions } catch (initException e) { // Any problems? // All cleanup-on-failure must be done here. runCleanupFcts(); throw e; // Rethrow. Warning: if multiple threads throw exceptions, only one gets returned. } } /* Initialisation functions. * * These should each handle a separate area of initialisation such that these functions could * be run simultaneously in separate threads. */ void initSDL () { try { // SDL Joystick, used by mde.input DerelictSDL.load(); } catch (DerelictException de) { throw new DynamicLibraryLoadException (de.msg); } logger.info ("Derelict: loaded SDL"); SDL_Init (SDL_INIT_TIMER | SDL_INIT_JOYSTICK); addCleanupFct (&cleanupSDL); logger.info ("SDL initialised"); } ~this() { runCleanupFcts(); } /* Cleanup Functions. * * These may exist simply as something to add to the cleanup list... */ static void cleanupSDL () { SDL_Quit(); } private static { void function ()[] cleanup; // all functions to be run for cleanup // Adding cleanup functions must be synchronized; use: void addCleanupFct (void function () fct) { synchronized cleanup ~= fct; } // Clean-up fcts are run in reverse order to how they're added: void runCleanupFcts () { foreach_reverse (fct; cleanup) fct(); } } } unittest { /* Fake init and cleanup. This happens before the CTOR runs so the extra Init.runCleanupFcts() * call isn't going to mess things up. The extra function called by runCleanupFcts won't cause * any harm either. */ static bool initialised = false; static void cleanup () { initialised = false; } static void init () { initialised = true; Init.addCleanupFct (&cleanup); } init(); assert (initialised); Init.runCleanupFcts(); assert (!initialised); }