Mercurial > projects > mde
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 |