module.h
A system for keeping initialization and shutdown modular while avoiding non-trivial global constructors/destructors.
Classes:
An engine component that requires initialization and/or cleanup.
Entry in the list of dependencies.
Record for module that this module overrides.
Public Defines
AFTER_MODULE_INIT(name) namespace { \ class _AfterModuleInit : public :: { \ public: \ typedef :: Parent; \ static _AfterModuleInit smInstance; \ virtual char* getName() { return "AFTER_MODULE_INIT( " #name " ) in " __FILE__; } \ struct _DepInitAfter : public Parent::Dependency \ { \ _DepInitAfter() \ : Parent::Dependency( ModeInitialize, DependencyAfter, &smInstance, #name ) {} \ } mDepInitAfter; \ virtual initialize(); \ }; \ _AfterModuleInit _AfterModuleInit::smInstance; \ } \ _AfterModuleInit::initialize()
Used to define a function which will be called right after the named module is initialized.
MODULE_BEGIN(name) namespace { namespace _ ## name { \ class _ModuleInst : public :: { \ public: \ typedef :: Parent; \ static _ModuleInst smInstance; \ virtual char* getName() { return #name; }
Begin a module definition.
MODULE_END() }; \ _ModuleInst _ModuleInst::smInstance; \ } }
Terminate a module definition.
MODULE_INIT() virtual initialize()
Define initialization code for the module.
MODULE_INIT_AFTER(name) struct _DepInitAfter ## name : public Parent::Dependency \ { \ _DepInitAfter ## name() \ : Parent::Dependency( ModeInitialize, DependencyAfter, &smInstance, #name ) {} \ } mDepInitAfter ## name;
Make sure this module is initialized after the module called "name".
MODULE_INIT_BEFORE(name) struct _DepInitBefore ## name : public Parent::Dependency \ { \ _DepInitBefore ## name() \ : Parent::Dependency( ModeInitialize, DependencyBefore, &smInstance, #name ) {} \ } mDepInitBefore ## name;
Make sure this module is initialized before the module called "name".
MODULE_OVERRIDE(name) struct _Override ## name : public Parent::Override \ { \ _Override ## name() \ : Parent::Override( &smInstance, #name ) {} \ } mOverride ## name;
Replace the given module in both the init and the shutdown sequence.
MODULE_SHUTDOWN() virtual shutdown()
Define cleanup code for the module.
MODULE_SHUTDOWN_AFTER(name) struct _DepShutdownAfter ## name : public Parent::Dependency \ { \ _DepShutdownAfter ## name() \ : Parent::Dependency( ModeShutdown, DependencyAfter, &smInstance, #name ) {} \ } mDepShutdownAfter ## name;
Make sure this module is initialized after the module called "name".
MODULE_SHUTDOWN_BEFORE(name) struct _DepShutdownBefore ## name : public Parent::Dependency \ { \ _DepShutdownBefore ## name() \ : Parent::Dependency( ModeShutdown, DependencyBefore, &smInstance, #name ) {} \ } mDepShutdownBefore ## name;
Make sure this module is initialized before the module called "name".
Detailed Description
A system for keeping initialization and shutdown modular while avoiding non-trivial global constructors/destructors.
Public Defines
AFTER_MODULE_INIT(name) namespace { \ class _AfterModuleInit : public :: { \ public: \ typedef :: Parent; \ static _AfterModuleInit smInstance; \ virtual char* getName() { return "AFTER_MODULE_INIT( " #name " ) in " __FILE__; } \ struct _DepInitAfter : public Parent::Dependency \ { \ _DepInitAfter() \ : Parent::Dependency( ModeInitialize, DependencyAfter, &smInstance, #name ) {} \ } mDepInitAfter; \ virtual initialize(); \ }; \ _AfterModuleInit _AfterModuleInit::smInstance; \ } \ _AfterModuleInit::initialize()
Used to define a function which will be called right after the named module is initialized.
AFTER_MODULE_INIT( Sim ) { Con::addVariable( "$myBool", TypeBool, &smMyBool ); }
MODULE_BEGIN(name) namespace { namespace _ ## name { \ class _ModuleInst : public :: { \ public: \ typedef :: Parent; \ static _ModuleInst smInstance; \ virtual char* getName() { return #name; }
Begin a module definition.
MODULE_BEGIN( MyModule ) MODULE_INIT_AFTER( Sim ) MODULE_INIT_BEFORE( 3D ) MODULE_SHUTDOWN_BEFORE( Sim ) MODULE_INIT { // Init code... } MODULE_SHUTDOWN { // Cleanup code... } MODULE_END;
MODULE_END() }; \ _ModuleInst _ModuleInst::smInstance; \ } }
Terminate a module definition.
MODULE_BEGIN( MyModule ) MODULE_END;
MODULE_INIT() virtual initialize()
Define initialization code for the module.
MODULE_BEGIN( MyModule ) MODULE_INIT { // Init code goes here. } MODULE_END;
MODULE_INIT_AFTER(name) struct _DepInitAfter ## name : public Parent::Dependency \ { \ _DepInitAfter ## name() \ : Parent::Dependency( ModeInitialize, DependencyAfter, &smInstance, #name ) {} \ } mDepInitAfter ## name;
Make sure this module is initialized after the module called "name".
MODULE_BEGIN( MyModule ) MODULE_INIT_AFTER( MyOtherModule ) MODULE_END;
MODULE_INIT_BEFORE(name) struct _DepInitBefore ## name : public Parent::Dependency \ { \ _DepInitBefore ## name() \ : Parent::Dependency( ModeInitialize, DependencyBefore, &smInstance, #name ) {} \ } mDepInitBefore ## name;
Make sure this module is initialized before the module called "name".
MODULE_BEGIN( MyModule ) MODULE_INIT_BEFORE( MyOtherModule ) MODULE_END;
MODULE_OVERRIDE(name) struct _Override ## name : public Parent::Override \ { \ _Override ## name() \ : Parent::Override( &smInstance, #name ) {} \ } mOverride ## name;
Replace the given module in both the init and the shutdown sequence.
MODULE_BEGIN( MyMoveManager ) MODULE_OVERRIDE( MoveManager ) MODULE_END;
MODULE_SHUTDOWN() virtual shutdown()
Define cleanup code for the module.
MODULE_BEGIN( MyModule ) MODULE_SHUTDOWN { // Cleanup code goes here. } MODULE_END;
MODULE_SHUTDOWN_AFTER(name) struct _DepShutdownAfter ## name : public Parent::Dependency \ { \ _DepShutdownAfter ## name() \ : Parent::Dependency( ModeShutdown, DependencyAfter, &smInstance, #name ) {} \ } mDepShutdownAfter ## name;
Make sure this module is initialized after the module called "name".
MODULE_BEGIN( MyModule ) MODULE_SHUTDOWN_AFTER( MyOtherModule ) MODULE_END;
MODULE_SHUTDOWN_BEFORE(name) struct _DepShutdownBefore ## name : public Parent::Dependency \ { \ _DepShutdownBefore ## name() \ : Parent::Dependency( ModeShutdown, DependencyBefore, &smInstance, #name ) {} \ } mDepShutdownBefore ## name;
Make sure this module is initialized before the module called "name".
MODULE_BEGIN( MyModule ) MODULE_SHUTDOWN_BEFORE( MyOtherModule ) MODULE_END;
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#ifndef _MODULE_H_ 25#define _MODULE_H_ 26 27#ifndef _TSINGLETON_H_ 28 #include "core/util/tSingleton.h" 29#endif 30#ifndef _TVECTOR_H_ 31 #include "core/util/tVector.h" 32#endif 33 34 35/// @file 36/// A system for keeping initialization and shutdown modular while 37/// avoiding non-trivial global constructors/destructors. 38 39 40/// An engine component that requires initialization and/or cleanup. 41class Module 42{ 43 public: 44 45 typedef void Parent; 46 friend struct EngineModuleManager; 47 48 protected: 49 50 struct Dependency; 51 friend struct Dependency; 52 53 enum Mode 54 { 55 ModeInitialize, 56 ModeShutdown 57 }; 58 59 /// Direction of a dependency edge. 60 enum DependencyType 61 { 62 DependencyBefore, 63 DependencyAfter 64 }; 65 66 /// Entry in the list of dependencies. 67 struct Dependency 68 { 69 /// Direction of dependence. A "before" dependence goes the reverse direction. 70 DependencyType mType; 71 72 /// Name of the module that this module depends on. 73 const char* mModuleName; 74 75 /// Pointer to module. Filled by init code. 76 Module* mModule; 77 78 /// Next dependency or NULL. 79 Dependency* mNext; 80 81 Dependency( Mode mode, DependencyType type, Module* parentModule, const char* moduleName ) 82 : mType( type ), 83 mModuleName( moduleName ), 84 mModule( NULL ), 85 mNext( mode == ModeInitialize ? parentModule->mInitDependencies : parentModule->mShutdownDependencies ) 86 { 87 if( mode == ModeInitialize ) 88 parentModule->mInitDependencies = this; 89 else 90 parentModule->mShutdownDependencies = this; 91 } 92 }; 93 94 /// Record for module that this module overrides. 95 struct Override 96 { 97 /// Name of module being overridden. 98 const char* mModuleName; 99 100 /// Next override or NULL. 101 Override* mNext; 102 103 Override( Module* parentModule, const char* moduleName ) 104 : mModuleName( moduleName ), 105 mNext( parentModule->mOverrides ) 106 { 107 parentModule->mOverrides = this; 108 } 109 }; 110 111 /// Flag to make sure we don't shutdown modules that have not been initialized. 112 bool mIsInitialized; 113 114 /// Next module in the global module list. 115 Module* mNext; 116 117 /// List of modules to which the initialization of this module has dependency relations. 118 Dependency* mInitDependencies; 119 120 /// List of modules to which the shutdown of this module has dependency relations. 121 Dependency* mShutdownDependencies; 122 123 /// List of modules being overriden by this module. 124 Override* mOverrides; 125 126 /// Global list of modules. 127 static Module* smFirst; 128 129 /// Return true if this module is constrained to precede "module" in the given "mode". 130 bool _constrainedToComeBefore( Module* module, Mode mode ); 131 132 /// Return true if this module is constrained to follow "module" in the given "mode". 133 bool _constrainedToComeAfter( Module* module, Mode mode ); 134 135 /// 136 Dependency* _getDependencies( Mode mode ) 137 { 138 if( mode == ModeInitialize ) 139 return mInitDependencies; 140 else 141 return mShutdownDependencies; 142 } 143 144 Module() 145 : mIsInitialized( false ), 146 mNext( smFirst ), 147 mInitDependencies( NULL ), 148 mShutdownDependencies( NULL ), 149 mOverrides( NULL ) 150 151 { 152 smFirst = this; 153 } 154 155 public: 156 157 /// Return the module name. 158 virtual const char* getName() const = 0; 159 160 /// Initialize the module. This is only called after all modules that this 161 /// module depends on have been initialized. 162 virtual void initialize() {} 163 164 /// Shut down the module. This is called before any module that this module 165 /// depends on have been shut down. 166 virtual void shutdown() {} 167}; 168 169 170/// Begin a module definition. 171/// 172/// @code 173/// MODULE_BEGIN( MyModule ) 174/// 175/// MODULE_INIT_AFTER( Sim ) 176/// MODULE_INIT_BEFORE( 3D ) 177/// MODULE_SHUTDOWN_BEFORE( Sim ) 178/// 179/// MODULE_INIT 180/// { 181/// // Init code... 182/// } 183/// 184/// MODULE_SHUTDOWN 185/// { 186/// // Cleanup code... 187/// } 188/// 189/// MODULE_END; 190/// @endcode 191#define MODULE_BEGIN( name ) \ 192 namespace { namespace _ ## name { \ 193 class _ModuleInst : public ::Module { \ 194 public: \ 195 typedef ::Module Parent; \ 196 static _ModuleInst smInstance; \ 197 virtual const char* getName() const { return #name; } 198 199/// Make sure this module is initialized before the module called "name". 200/// 201/// @code 202/// MODULE_BEGIN( MyModule ) 203/// MODULE_INIT_BEFORE( MyOtherModule ) 204/// MODULE_END; 205/// @endcode 206#define MODULE_INIT_BEFORE( name ) \ 207 struct _DepInitBefore ## name : public Parent::Dependency \ 208 { \ 209 _DepInitBefore ## name() \ 210 : Parent::Dependency( ModeInitialize, DependencyBefore, &smInstance, #name ) {} \ 211 } mDepInitBefore ## name; 212 213/// Make sure this module is initialized after the module called "name". 214/// 215/// @code 216/// MODULE_BEGIN( MyModule ) 217/// MODULE_INIT_AFTER( MyOtherModule ) 218/// MODULE_END; 219/// @endcode 220#define MODULE_INIT_AFTER( name ) \ 221 struct _DepInitAfter ## name : public Parent::Dependency \ 222 { \ 223 _DepInitAfter ## name() \ 224 : Parent::Dependency( ModeInitialize, DependencyAfter, &smInstance, #name ) {} \ 225 } mDepInitAfter ## name; 226 227/// Make sure this module is initialized before the module called "name". 228/// 229/// @code 230/// MODULE_BEGIN( MyModule ) 231/// MODULE_SHUTDOWN_BEFORE( MyOtherModule ) 232/// MODULE_END; 233/// @endcode 234#define MODULE_SHUTDOWN_BEFORE( name ) \ 235 struct _DepShutdownBefore ## name : public Parent::Dependency \ 236 { \ 237 _DepShutdownBefore ## name() \ 238 : Parent::Dependency( ModeShutdown, DependencyBefore, &smInstance, #name ) {} \ 239 } mDepShutdownBefore ## name; 240 241/// Make sure this module is initialized after the module called "name". 242/// 243/// @code 244/// MODULE_BEGIN( MyModule ) 245/// MODULE_SHUTDOWN_AFTER( MyOtherModule ) 246/// MODULE_END; 247/// @endcode 248#define MODULE_SHUTDOWN_AFTER( name ) \ 249 struct _DepShutdownAfter ## name : public Parent::Dependency \ 250 { \ 251 _DepShutdownAfter ## name() \ 252 : Parent::Dependency( ModeShutdown, DependencyAfter, &smInstance, #name ) {} \ 253 } mDepShutdownAfter ## name; 254 255/// Replace the given module in both the init and the shutdown sequence. 256/// 257/// @code 258/// MODULE_BEGIN( MyMoveManager ) 259/// MODULE_OVERRIDE( MoveManager ) 260/// MODULE_END; 261/// @endcode 262#define MODULE_OVERRIDE( name ) \ 263 struct _Override ## name : public Parent::Override \ 264 { \ 265 _Override ## name() \ 266 : Parent::Override( &smInstance, #name ) {} \ 267 } mOverride ## name; 268 269/// Define initialization code for the module. 270/// 271/// @code 272/// MODULE_BEGIN( MyModule ) 273/// MODULE_INIT 274/// { 275/// // Init code goes here. 276/// } 277/// MODULE_END; 278/// @endcode 279#define MODULE_INIT \ 280 virtual void initialize() 281 282/// Define cleanup code for the module. 283/// 284/// @code 285/// MODULE_BEGIN( MyModule ) 286/// MODULE_SHUTDOWN 287/// { 288/// // Cleanup code goes here. 289/// } 290/// MODULE_END; 291/// @endcode 292#define MODULE_SHUTDOWN \ 293 virtual void shutdown() 294 295/// Terminate a module definition. 296/// 297/// @code 298/// MODULE_BEGIN( MyModule ) 299/// MODULE_END; 300/// @endcode 301#define MODULE_END \ 302 }; \ 303 _ModuleInst _ModuleInst::smInstance; \ 304 } } 305 306 307 308/// Used to define a function which will be called right 309/// after the named module is initialized. 310/// 311/// @code 312/// AFTER_MODULE_INIT( Sim ) 313/// { 314/// Con::addVariable( "$myBool", TypeBool, &smMyBool ); 315/// } 316/// @endcode 317/// 318#define AFTER_MODULE_INIT( name ) \ 319 namespace { \ 320 class _AfterModuleInit : public ::Module { \ 321 public: \ 322 typedef ::Module Parent; \ 323 static _AfterModuleInit smInstance; \ 324 virtual const char* getName() const { return "AFTER_MODULE_INIT( " #name " ) in " __FILE__; } \ 325 struct _DepInitAfter : public Parent::Dependency \ 326 { \ 327 _DepInitAfter() \ 328 : Parent::Dependency( ModeInitialize, DependencyAfter, &smInstance, #name ) {} \ 329 } mDepInitAfter; \ 330 virtual void initialize(); \ 331 }; \ 332 _AfterModuleInit _AfterModuleInit::smInstance; \ 333 } \ 334 void _AfterModuleInit::initialize() 335 336 337struct EngineModuleManager 338{ 339 /// Initialize all modules registered with the system. 340 static void initializeSystem(); 341 342 /// Shutdown all modules registered with the system. 343 static void shutdownSystem(); 344 345 /// Return the instance of the module called "name" or NULL if no such module is defined. 346 static Module* findModule( const char* name ); 347 348 private: 349 350 static Module* _findOverrideFor( Module* module ); 351 static String _moduleListToString( Vector< Module*>& moduleList ); 352 static void _printModuleList( Vector< Module*>& moduleList ); 353 static void _insertIntoModuleList( Module::Mode mode, Vector< Module*>& moduleList, Module* module ); 354 static S32 _getIndexOfModuleInList( Vector< Module*>& moduleList, Module* module ); 355 static S32 _getIndexOfModuleInList( Vector< Module*>& moduleList, const char* moduleName ); 356 static void _createModuleList( Module::Mode mode, Vector< Module*>& moduleList ); 357}; 358 359#endif // !_MODULE_H_ 360