X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/32d4c30a13f65b7c8cb66f813a0b8c606ad8480b..7419ba028c7e2d0e585a9b043af587d993da16a7:/src/common/module.cpp?ds=sidebyside diff --git a/src/common/module.cpp b/src/common/module.cpp index e4eb228f23..9167848b89 100644 --- a/src/common/module.cpp +++ b/src/common/module.cpp @@ -16,13 +16,14 @@ #pragma hdrstop #endif +#include "wx/module.h" + #ifndef WX_PRECOMP #include "wx/hash.h" + #include "wx/intl.h" + #include "wx/log.h" #endif -#include "wx/module.h" -#include "wx/intl.h" -#include "wx/log.h" #include "wx/listimpl.cpp" #define TRACE_MODULE _T("module") @@ -35,6 +36,7 @@ wxModuleList wxModule::m_modules; void wxModule::RegisterModule(wxModule* module) { + module->m_state = State_Registered; m_modules.Append(module); } @@ -68,42 +70,133 @@ void wxModule::RegisterModules() } } -bool wxModule::InitializeModules() +bool wxModule::DoInitializeModule(wxModule *module, + wxModuleList &initializedModules) { - // Initialize user-defined modules - wxModuleList::compatibility_iterator node; - for ( node = m_modules.GetFirst(); node; node = node->GetNext() ) + if ( module->m_state == State_Initializing ) { - wxModule *module = node->GetData(); - if ( !module->Init() ) + wxLogError(_("Circular dependency involving module \"%s\" detected."), + module->GetClassInfo()->GetClassName()); + return false; + } + + module->m_state = State_Initializing; + + const wxArrayClassInfo& dependencies = module->m_dependencies; + + // satisfy module dependencies by loading them before the current module + for ( unsigned int i = 0; i < dependencies.size(); ++i ) + { + wxClassInfo * cinfo = dependencies[i]; + + // Check if the module is already initialized + wxModuleList::compatibility_iterator node; + for ( node = initializedModules.GetFirst(); node; node = node->GetNext() ) { - wxLogError(_("Module \"%s\" initialization failed"), - module->GetClassInfo()->GetClassName()); + if ( node->GetData()->GetClassInfo() == cinfo ) + break; + } + + if ( node ) + { + // this dependency is already initialized, nothing to do + continue; + } - // clean up already initialized modules - process in reverse order - wxModuleList::compatibility_iterator n; - for ( n = node->GetPrevious(); n; n = n->GetPrevious() ) + // find the module in the registered modules list + for ( node = m_modules.GetFirst(); node; node = node->GetNext() ) + { + wxModule *moduleDep = node->GetData(); + if ( moduleDep->GetClassInfo() == cinfo ) { - n->GetData()->OnExit(); + if ( !DoInitializeModule(moduleDep, initializedModules ) ) + { + // failed to initialize a dependency, so fail this one too + return false; + } + + break; } + } + if ( !node ) + { + wxLogError(_("Dependency \"%s\" of module \"%s\" doesn't exist."), + cinfo->GetClassName(), + module->GetClassInfo()->GetClassName()); return false; } } + if ( !module->Init() ) + { + wxLogError(_("Module \"%s\" initialization failed"), + module->GetClassInfo()->GetClassName()); + return false; + } + + wxLogTrace(TRACE_MODULE, wxT("Module \"%s\" initialized"), + module->GetClassInfo()->GetClassName()); + + module->m_state = State_Initialized; + initializedModules.Append(module); + + return true; +} + +// Initialize user-defined modules +bool wxModule::InitializeModules() +{ + wxModuleList initializedModules; + + for ( wxModuleList::compatibility_iterator node = m_modules.GetFirst(); + node; + node = node->GetNext() ) + { + wxModule *module = node->GetData(); + + // the module could have been already initialized as dependency of + // another one + if ( module->m_state == State_Registered ) + { + if ( !DoInitializeModule( module, initializedModules ) ) + { + // failed to initialize all modules, so clean up the already + // initialized ones + DoCleanUpModules(initializedModules); + + return false; + } + } + } + + // remember the real initialisation order + m_modules = initializedModules; + return true; } -void wxModule::CleanUpModules() +// Clean up all currently initialized modules +void wxModule::DoCleanUpModules(const wxModuleList& modules) { - // Cleanup user-defined modules - wxModuleList::compatibility_iterator node; - for ( node = m_modules.GetFirst(); node; node = node->GetNext() ) + // cleanup user-defined modules in the reverse order compared to their + // initialization -- this ensures that dependencies are respected + for ( wxModuleList::compatibility_iterator node = modules.GetLast(); + node; + node = node->GetPrevious() ) { wxLogTrace(TRACE_MODULE, wxT("Cleanup module %s"), node->GetData()->GetClassInfo()->GetClassName()); - node->GetData()->Exit(); + + wxModule * module = node->GetData(); + + wxASSERT_MSG( module->m_state == State_Initialized, + _T("not initialized module being cleaned up") ); + + module->Exit(); + module->m_state = State_Registered; } + // clear all modules, even the non-initialized ones WX_CLEAR_LIST(wxModuleList, m_modules); }