module.cpp
Public Defines
define
DEBUG_SPEW_LEVEL() 2
Detailed Description
Public Defines
DEBUG_SPEW_LEVEL() 2
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "core/module.h" 26#include "core/util/tVector.h" 27#include "core/strings/stringFunctions.h" 28 29 30//#define DEBUG_SPEW 31#define DEBUG_SPEW_LEVEL 2 32 33 34Module* Module::smFirst; 35 36 37//----------------------------------------------------------------------------- 38 39bool Module::_constrainedToComeBefore( Module* module, Mode mode ) 40{ 41 if( module == this ) 42 return false; 43 44 for( Dependency* dependency = _getDependencies( mode ); 45 dependency != NULL; dependency = dependency->mNext ) 46 { 47 Module* depModule = dependency->mModule; 48 if( !depModule ) 49 { 50 depModule = EngineModuleManager::findModule( dependency->mModuleName ); 51 if( !depModule ) 52 { 53 // Module does not exist. Only emit a warning here so that modules 54 // can be omitted from a link without requiring the module definitions 55 // to be adapted. 56 57 Platform::outputDebugString( "[EngineModuleManager] Module %s of '%s' depends on module '%s' which does not exist", 58 mode == Module::ModeInitialize ? "init" : "shutdown", 59 module->getName(), dependency->mModuleName ); 60 continue; 61 } 62 63 dependency->mModule = depModule; 64 } 65 66 if( dependency->mType == DependencyBefore ) 67 { 68 if( depModule == module 69 || depModule->_constrainedToComeBefore( module, mode ) ) 70 return true; 71 } 72 } 73 74 return false; 75} 76 77//----------------------------------------------------------------------------- 78 79bool Module::_constrainedToComeAfter( Module* module, Mode mode ) 80{ 81 if( module == this ) 82 return false; 83 84 for( Dependency* dependency = _getDependencies( mode ); 85 dependency != NULL; dependency = dependency->mNext ) 86 { 87 Module* depModule = dependency->mModule; 88 if( !depModule ) 89 { 90 depModule = EngineModuleManager::findModule( dependency->mModuleName ); 91 if( !depModule ) 92 { 93 // Module does not exist. Only emit a warning here so that modules 94 // can be omitted from a link without requiring the module definitions 95 // to be adapted. 96 97 Platform::outputDebugString( "[EngineModuleManager] Module %s of '%s' depends on module '%s' which does not exist", 98 mode == Module::ModeInitialize ? "init" : "shutdown", 99 module->getName(), dependency->mModuleName ); 100 continue; 101 } 102 103 dependency->mModule = depModule; 104 } 105 106 if( dependency->mType == DependencyAfter ) 107 { 108 if( depModule == module 109 || depModule->_constrainedToComeAfter( module, mode ) ) 110 return true; 111 } 112 } 113 114 return false; 115} 116 117//----------------------------------------------------------------------------- 118 119String EngineModuleManager::_moduleListToString( Vector< Module*>& moduleList ) 120{ 121 StringBuilder str; 122 123 const U32 numModules = moduleList.size(); 124 bool isFirst = true; 125 for( U32 i = 0; i < numModules; ++ i ) 126 { 127 if( !isFirst ) 128 str.append( " -> " ); 129 130 str.append( moduleList[ i ]->getName() ); 131 132 isFirst = false; 133 } 134 135 return str.end(); 136} 137 138//----------------------------------------------------------------------------- 139 140void EngineModuleManager::_printModuleList( Vector< Module*>& moduleList ) 141{ 142 Platform::outputDebugString( _moduleListToString( moduleList ) ); 143} 144 145//----------------------------------------------------------------------------- 146 147void EngineModuleManager::_insertIntoModuleList( Module::Mode mode, Vector< Module*>& moduleList, Module* module ) 148{ 149 // If this module is being overridden, switch over to 150 // the module overriding it. 151 152 Module* override; 153 do 154 { 155 override = _findOverrideFor( module ); 156 if( override ) 157 module = override; 158 } 159 while( override != NULL ); 160 161 // If we are already on the list, return. 162 163 if( _getIndexOfModuleInList( moduleList, module ) != -1 ) 164 return; 165 166 // If we don't have dependencies, just push the module 167 // to the back of the list. 168 169 if( !module->_getDependencies( mode ) ) 170 { 171 #if defined( DEBUG_SPEW ) && DEBUG_SPEW_LEVEL > 1 172 Platform::outputDebugString( "[EngineModuleManager] Appending '%s' to '%s'", 173 module->getName(), _moduleListToString( moduleList ).c_str() ); 174 #endif 175 176 moduleList.push_back( module ); 177 return; 178 } 179 180 // First make sure that all 'after' dependencies are in the list. 181 182 #if defined( DEBUG_SPEW ) && DEBUG_SPEW_LEVEL > 1 183 Platform::outputDebugString( "[EngineModuleManager] Resolving %s dependencies of '%s'", 184 mode == Module::ModeInitialize ? "init" : "shutdown", 185 module->getName() ); 186 #endif 187 188 for( Module::Dependency* dependency = module->_getDependencies( mode ); 189 dependency != NULL; dependency = dependency->mNext ) 190 { 191 if( dependency->mType != Module::DependencyAfter ) 192 continue; 193 194 dependency->mModule = findModule( dependency->mModuleName ); 195 if( !dependency->mModule ) 196 continue; // Allow modules to not exist. 197 198 if( _getIndexOfModuleInList( moduleList, dependency->mModule ) == -1 ) 199 _insertIntoModuleList( mode, moduleList, dependency->mModule ); 200 } 201 202 AssertFatal( _getIndexOfModuleInList( moduleList, module ) == -1, 203 avar( "EngineModuleManager::_insertModuleIntoList - Cycle in 'after' %s dependency chain of '%s'", 204 mode == Module::ModeInitialize ? "init" : "shutdown", 205 module->getName() ) ); 206 207 // Now add the module itself. 208 209 const U32 numModules = moduleList.size(); 210 for( U32 i = 0; i < numModules; ++ i ) 211 { 212 const bool thisBeforeCurrent = module->_constrainedToComeBefore( moduleList[ i ], mode ); 213 const bool currentAfterThis = moduleList[ i ]->_constrainedToComeAfter( module, mode ); 214 215 AssertFatal( !( thisBeforeCurrent && currentAfterThis ), 216 avar( "EngineModuleManager::_insertModuleIntoList - Ambiguous %s placement of module '%s' relative to '%s'", 217 mode == Module::ModeInitialize ? "init" : "shutdown", 218 module->getName(), moduleList[ i ]->getName() ) ); 219 220 // If no contraints relate us to this module, 221 // push us one more position back in the line. 222 223 if( !thisBeforeCurrent && !currentAfterThis ) 224 continue; 225 226 // If this module is contrained to come before the 227 // module at our current position but that module does 228 // not actually have dependencies of its own, make sure 229 // that module is at the back of the module list so that 230 // if we have more dependencies, it will not prevent us 231 // from correctly positioning us in relation to them. 232 233 if( thisBeforeCurrent && !moduleList[ i ]->_getDependencies( mode ) && i != numModules - 1 ) 234 { 235 #if defined( DEBUG_SPEW ) && DEBUG_SPEW_LEVEL > 1 236 Platform::outputDebugString( "[EngineModuleManager] Pushing '%s' to back end of chain for resolving '%s'", 237 moduleList[ i ]->getName(), module->getName() ); 238 #endif 239 240 Module* depModule = moduleList[ i ]; 241 moduleList.erase( i ); 242 -- i; 243 244 moduleList.push_back( depModule ); 245 continue; 246 } 247 248 // Try the reverse constraint with all remaining modules in the list. 249 // If there is one for which we have one, then the placement of this 250 // module is ambiguous. 251 252 for( U32 n = i + 1; n < numModules; ++ n ) 253 AssertFatal( !( moduleList[ n ]->_constrainedToComeBefore( module, mode ) 254 || module->_constrainedToComeAfter( moduleList[ n ], mode ) ), 255 avar( "EngineModuleManager::_insertModuleIntoList - Ambiguous %s constraint on module '%s' to come before '%s' yet after '%s'", 256 mode == Module::ModeInitialize ? "init" : "shutdown", 257 module->getName(), 258 moduleList[ i ]->getName(), 259 moduleList[ n ]->getName() ) ); 260 261 // Add the module at this position. 262 263 #if defined( DEBUG_SPEW ) && DEBUG_SPEW_LEVEL > 1 264 Platform::outputDebugString( "[EngineModuleManager] Inserting '%s' at index %i into '%s'", 265 module->getName(), i, _moduleListToString( moduleList ).c_str() ); 266 #endif 267 268 moduleList.insert( i, module ); 269 return; 270 } 271 272 // No constraint-based position. Just append. 273 274 #if defined( DEBUG_SPEW ) && DEBUG_SPEW_LEVEL > 1 275 Platform::outputDebugString( "[EngineModuleManager] Appending '%s' to '%s'", 276 module->getName(), _moduleListToString( moduleList ).c_str() ); 277 #endif 278 279 moduleList.push_back( module ); 280} 281 282//----------------------------------------------------------------------------- 283 284Module* EngineModuleManager::_findOverrideFor( Module* module ) 285{ 286 const char* name = module->getName(); 287 288 for( Module* ptr = Module::smFirst; ptr != NULL; ptr = ptr->mNext ) 289 for( Module::Override* override = ptr->mOverrides; override != NULL; override = override->mNext ) 290 if( dStricmp( override->mModuleName, name ) == 0 ) 291 return ptr; 292 293 return NULL; 294} 295 296//----------------------------------------------------------------------------- 297 298S32 EngineModuleManager::_getIndexOfModuleInList( Vector< Module*>& moduleList, Module* module ) 299{ 300 const U32 numModules = moduleList.size(); 301 for( U32 i = 0; i < numModules; ++ i ) 302 if( moduleList[ i ] == module ) 303 return i; 304 305 return -1; 306} 307 308//----------------------------------------------------------------------------- 309 310S32 EngineModuleManager::_getIndexOfModuleInList( Vector< Module*>& moduleList, const char* moduleName ) 311{ 312 const U32 numModules = moduleList.size(); 313 for( U32 i = 0; i < numModules; ++ i ) 314 if( dStricmp( moduleList[ i ]->getName(), moduleName ) == 0 ) 315 return i; 316 317 return -1; 318} 319 320//----------------------------------------------------------------------------- 321 322void EngineModuleManager::_createModuleList( Module::Mode mode, Vector< Module*>& moduleList ) 323{ 324 for( Module* module = Module::smFirst; module != NULL; module = module->mNext ) 325 _insertIntoModuleList( mode, moduleList, module ); 326} 327 328//----------------------------------------------------------------------------- 329 330void EngineModuleManager::initializeSystem() 331{ 332 Vector< Module*> modules; 333 334 _createModuleList( Module::ModeInitialize, modules ); 335 336 const U32 numModules = modules.size(); 337 for( U32 i = 0; i < numModules; ++ i ) 338 { 339 Module* module = modules[ i ]; 340 if( !module->mIsInitialized ) 341 { 342 #ifdef DEBUG_SPEW 343 Platform::outputDebugString( "[EngineModuleManager] Initializing %s", 344 module->getName() ); 345 #endif 346 347 module->initialize(); 348 module->mIsInitialized = true; 349 } 350 } 351} 352 353//----------------------------------------------------------------------------- 354 355void EngineModuleManager::shutdownSystem() 356{ 357 Vector< Module*> modules; 358 359 _createModuleList( Module::ModeShutdown, modules ); 360 361 const U32 numModules = modules.size(); 362 for( U32 i = 0; i < numModules; ++ i ) 363 { 364 if( modules[ i ]->mIsInitialized ) 365 { 366 #ifdef DEBUG_SPEW 367 Platform::outputDebugString( "[EngineModuleManager] Shutting down %s", 368 modules[ i ]->getName() ); 369 #endif 370 371 modules[ i ]->shutdown(); 372 modules[ i ]->mIsInitialized = false; 373 } 374 } 375} 376 377//----------------------------------------------------------------------------- 378 379Module* EngineModuleManager::findModule( const char* name ) 380{ 381 for( Module* module = Module::smFirst; module != NULL; module = module->mNext ) 382 if( dStricmp( module->getName(), name ) == 0 ) 383 return module; 384 385 return NULL; 386} 387