module.h

Engine/source/core/module.h

A system for keeping initialization and shutdown modular while avoiding non-trivial global constructors/destructors.

More...

Classes:

class

An engine component that requires initialization and/or cleanup.

class

Entry in the list of dependencies.

class

Record for module that this module overrides.

Public Defines

define
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.

define
MODULE_BEGIN(name)    namespace { namespace _ ## name {                                             \
      class _ModuleInst : public :: {                                      \
         public:                                                                 \
            typedef :: Parent;                                             \
            static _ModuleInst smInstance;                                       \
            virtual  char* getName()  { return #name; }

Begin a module definition.

define
MODULE_END()       };                                                                         \
      _ModuleInst _ModuleInst::smInstance;                                       \
   } }

Terminate a module definition.

define
MODULE_INIT()             virtual  initialize()

Define initialization code for the module.

define
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".

define
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".

define
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.

define
MODULE_SHUTDOWN()             virtual  shutdown()

Define cleanup code for the module.

define
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".

define
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