///////////////////////////////////////////////////////////////////////////// // Name: src/common/module.cpp // Purpose: Modules initialization/destruction // Author: Wolfram Gloger/adapted by Guilhem Lavaux // Modified by: // Created: 04/11/98 // RCS-ID: $Id: module.cpp 66630 2011-01-07 17:49:18Z SC $ // Copyright: (c) Wolfram Gloger and Guilhem Lavaux // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #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/listimpl.cpp" #define TRACE_MODULE wxT("module") WX_DEFINE_LIST(wxModuleList) wxIMPLEMENT_ABSTRACT_CLASS(wxModule, wxObject) wxModuleList wxModule::m_modules; void wxModule::RegisterModule(wxModule* module) { module->m_state = State_Registered; m_modules.Append(module); } void wxModule::UnregisterModule(wxModule* module) { m_modules.DeleteObject(module); delete module; } // Collect up all module-derived classes, create an instance of each, // and register them. void wxModule::RegisterModules() { for (wxClassInfo::const_iterator it = wxClassInfo::begin_classinfo(), end = wxClassInfo::end_classinfo(); it != end; ++it) { const wxClassInfo* classInfo = *it; if ( classInfo->IsKindOf(CLASSINFO(wxModule)) && (classInfo != (& (wxModule::ms_classInfo))) ) { wxLogTrace(TRACE_MODULE, wxT("Registering module %s"), classInfo->GetClassName()); wxModule* module = (wxModule *)classInfo->CreateObject(); wxModule::RegisterModule(module); } } } bool wxModule::DoInitializeModule(wxModule *module, wxModuleList &initializedModules) { if ( module->m_state == State_Initializing ) { wxLogError(_("Circular dependency involving module \"%s\" detected."), module->GetClassInfo()->GetClassName()); return false; } module->m_state = State_Initializing; // translate named dependencies to the normal ones first if ( !module->ResolveNamedDependencies() ) return false; 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() ) { if ( node->GetData()->GetClassInfo() == cinfo ) break; } if ( node ) { // this dependency is already initialized, nothing to do continue; } // 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 ) { 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; } // Clean up all currently initialized modules void wxModule::DoCleanUpModules(const wxModuleList& modules) { // 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()); wxModule * module = node->GetData(); wxASSERT_MSG( module->m_state == State_Initialized, wxT("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); } bool wxModule::ResolveNamedDependencies() { // first resolve required dependencies for ( size_t i = 0; i < m_namedDependencies.size(); ++i ) { wxClassInfo *info = wxClassInfo::FindClass(m_namedDependencies[i]); if ( !info ) { // required dependency not found return false; } // add it even if it is not derived from wxModule because // DoInitializeModule() will make sure a module with the same class // info exists and fail if it doesn't m_dependencies.Add(info); } return true; }