comparison mde/scheduler/Init.d @ 29:f985c28c0ec9

A new GUI widget plus changes to the init system. GUI: Implemented a GridWidget to layout several sub-widgets. Improved log messages about init functions. Moved all dynamic-library loading into a separate init stage. committer: Diggory Hardy <diggory.hardy@gmail.com>
author Diggory Hardy <diggory.hardy@gmail.com>
date Sat, 12 Apr 2008 14:10:13 +0100
parents b5fadd8d930b
children 467c74d4804d
comparison
equal deleted inserted replaced
28:b5fadd8d930b 29:f985c28c0ec9
40 version (SwitchAppender) { // My own variation, currently just a test 40 version (SwitchAppender) { // My own variation, currently just a test
41 import tango.util.log.SwitchingFileAppender : SwitchingFileAppender; 41 import tango.util.log.SwitchingFileAppender : SwitchingFileAppender;
42 } else { 42 } else {
43 import tango.util.log.RollingFileAppender : RollingFileAppender; 43 import tango.util.log.RollingFileAppender : RollingFileAppender;
44 } 44 }
45
46 // Derelict imports
47 import derelict.opengl.gl;
48 import derelict.sdl.sdl;
49 //import derelict.freetype.ft;
50 import derelict.util.exception;
45 51
46 /** 52 /**
47 * Static CTOR 53 * Static CTOR
48 * 54 *
49 * This should handle a minimal amount of functionality where useful. For instance, configuring the 55 * This should handle a minimal amount of functionality where useful. For instance, configuring the
99 private static Logger logger; 105 private static Logger logger;
100 static this() { 106 static this() {
101 logger = Log.getLogger ("mde.scheduler.Init.Init"); 107 logger = Log.getLogger ("mde.scheduler.Init.Init");
102 } 108 }
103 109
104 /** CTOR − initialisation 110 /** this() − initialisation
105 * 111 *
106 * Runs general initialisation code, in a threaded manner where this isn't difficult. 112 * Runs general initialisation code, in a threaded manner where this isn't difficult.
113 * If any init fails, cleanup is still handled by ~this().
107 * 114 *
108 * If any init fails, it must run necessary cleanup first since the DTOR cannot(?) be run. */ 115 * Init order: 1. Pre-init (loads components needed by most init functions). 2. Dynamic library
116 * loading (load any dynamic libraries first, so that if loading fails nothing else need be
117 * done). 3. Init functions (threaded functions handling the rest of initialisation).
118 */
109 /* In a single-threaded function this could be done with: 119 /* In a single-threaded function this could be done with:
110 * scope(failure) cleanup; 120 * scope(failure) cleanup;
111 * This won't work with a threaded init function since any threads completing succesfully will 121 * This won't work with a threaded init function since any threads completing succesfully will
112 * not clean-up, and a fixed list of clean-up functions cannot be used since clean-up functions 122 * not clean-up, and a fixed list of clean-up functions cannot be used since clean-up functions
113 * must not run where the initialisation functions have failed. 123 * must not run where the initialisation functions have failed.
130 140
131 // Now re-set the logging level: 141 // Now re-set the logging level:
132 Log.getRootLogger.setLevel (cast(Log.Level) miscOpts.logLevel, true); // set the stored log level 142 Log.getRootLogger.setLevel (cast(Log.Level) miscOpts.logLevel, true); // set the stored log level
133 //END Pre-init 143 //END Pre-init
134 144
145 debug logger.trace ("Init: pre-init done");
146
147 //BEGIN Load dynamic libraries
148 /* Can be done by init functions but much neater to do here.
149 * Also means that init functions aren't run if a library fails to load. */
150 try {
151 DerelictSDL.load();
152 DerelictGL.load();
153 //DerelictFT.load();
154 } catch (DerelictException de) {
155 logger.fatal ("Loading dynamic library failed:");
156 logger.fatal (de.msg);
157
158 throw new InitException ("Loading dynamic libraries failed (see above).");
159 return;
160 }
161 //END Load dynamic libraries
162
163 debug logger.trace ("Init: dynamic libraries loaded");
135 164
136 //BEGIN Init (stages init2, init4) 165 //BEGIN Init (stages init2, init4)
137 /* Call init functions. 166 /* Call init functions.
138 * 167 *
139 * Current method is to try using threads, and on failure assume no threads were actually 168 * Current method is to try using threads, and on failure assume no threads were actually
175 private static { 204 private static {
176 /* The following three functions, runStage*, each run all functions in a stage in some order, 205 /* The following three functions, runStage*, each run all functions in a stage in some order,
177 * catching any exceptions thrown by the functions (although this isn't guaranteed for threads), 206 * catching any exceptions thrown by the functions (although this isn't guaranteed for threads),
178 * and throw an InitStageException on initFailure. */ 207 * and throw an InitStageException on initFailure. */
179 208
180 const UFE = "Unhandled exception from Init function:"; 209 const LOG_IF_MSG = "Init function ";
210 const LOG_CF_MSG = "Cleanup function ";
211 const LOG_F_START = " - running";
212 const LOG_F_END = " - completed";
213 const LOG_F_FAIL = " - failed: ";
181 /* Runs all functions consecutively, first-to-last. 214 /* Runs all functions consecutively, first-to-last.
182 * If any function fails, halts immediately. */ 215 * If any function fails, halts immediately. */
183 void runStageForward (InitStage s) { 216 void runStageForward (InitStage s) {
184 foreach (func; s.funcs) { 217 foreach (func; s.funcs) {
185 if (initFailure) break; 218 if (initFailure) break;
186 try { 219 try {
187 func(); 220 debug logger.trace (LOG_IF_MSG ~ func.name ~ LOG_F_START);
221 func.func();
222 debug logger.trace (LOG_IF_MSG ~ func.name ~ LOG_F_END);
188 } catch (Exception e) { 223 } catch (Exception e) {
189 logger.fatal (UFE); 224 logger.fatal (LOG_IF_MSG ~ func.name ~ LOG_F_FAIL ~
190 logger.fatal (e.msg); 225 ((e.msg is null || e.msg == "") ? "(no failure message)" : e.msg) );
191 226
192 setInitFailure(); 227 setInitFailure();
193 } 228 }
194 } 229 }
195 230
198 /* Runs all functions consecutively, last-to-first. 233 /* Runs all functions consecutively, last-to-first.
199 * If any function fails, continue until all have been run. */ 234 * If any function fails, continue until all have been run. */
200 void runStageReverse (InitStage s) { 235 void runStageReverse (InitStage s) {
201 foreach_reverse (func; s.funcs) { 236 foreach_reverse (func; s.funcs) {
202 try { 237 try {
203 func(); 238 debug logger.trace (LOG_CF_MSG ~ func.name ~ LOG_F_START);
239 func.func();
240 debug logger.trace (LOG_CF_MSG ~ func.name ~ LOG_F_END);
204 } catch (Exception e) { 241 } catch (Exception e) {
205 logger.fatal (UFE); 242 logger.fatal (LOG_CF_MSG ~ func.name ~ LOG_F_FAIL ~
206 logger.fatal (e.msg); 243 ((e.msg is null || e.msg == "") ? "(no failure message)" : e.msg) );
207 244
208 setInitFailure(); 245 setInitFailure();
209 } 246 }
210 } 247 }
211 if (initFailure) throw new InitStageException; // Problem running; abort and cleanup from here. 248 if (initFailure) throw new InitStageException; // Problem running; abort and cleanup from here.
216 if (!miscOpts.useThreads) return true; // Use unthreaded route instead 253 if (!miscOpts.useThreads) return true; // Use unthreaded route instead
217 254
218 ThreadGroup tg; 255 ThreadGroup tg;
219 try { // creating/starting threads could fail 256 try { // creating/starting threads could fail
220 tg = new ThreadGroup; 257 tg = new ThreadGroup;
221 foreach (func; s.funcs) tg.create(func); // Start all threads 258 foreach (func; s.funcs) { // Start all threads
259 debug logger.trace (LOG_IF_MSG ~ func.name ~ LOG_F_START);
260 tg.create(func.func);
261 debug logger.trace (LOG_IF_MSG ~ func.name ~ LOG_F_END);
262 }
222 } catch (ThreadException e) { // Problem with threading; try without threads 263 } catch (ThreadException e) { // Problem with threading; try without threads
223 logger.error ("Caught ThreadException while trying to create threads:"); 264 logger.error ("Caught ThreadException while trying to create threads:");
224 logger.error (e.msg); 265 logger.error (e.msg);
225 logger.info ("Will disable threads and continue."); 266 logger.info ("Will disable threads and continue, assuming no threads were created.");
226 267
227 Options.setBool("misc", "useThreads", false); // Disable threads entirely 268 Options.setBool("misc", "useThreads", false); // Disable threads entirely
228 return true; // Try again without threads 269 return true; // Try again without threads
229 } 270 }
230 271