X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f4a8c29f7a3ffa7eb60d9b7f055565eb2df368d9..eea4d01c65f9b29baa1193db762b4c6b8144af24:/src/common/module.cpp diff --git a/src/common/module.cpp b/src/common/module.cpp index 57c8a312cc..3532ceb149 100644 --- a/src/common/module.cpp +++ b/src/common/module.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: module.cpp +// Name: src/common/module.cpp // Purpose: Modules initialization/destruction // Author: Wolfram Gloger/adapted by Guilhem Lavaux // Modified by: @@ -9,71 +9,217 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "module.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif #include "wx/module.h" -#include "wx/hash.h" -IMPLEMENT_CLASS(wxModule, wxObject) +#ifndef WX_PRECOMP + #include "wx/hash.h" + #include "wx/intl.h" + #include "wx/log.h" +#endif + +#include "wx/listimpl.cpp" -wxList wxModule::m_modules; +#define TRACE_MODULE wxT("module") + +WX_DEFINE_LIST(wxModuleList) + +wxIMPLEMENT_ABSTRACT_CLASS(wxModule, wxObject) + +wxModuleList wxModule::m_modules; void wxModule::RegisterModule(wxModule* module) { - m_modules.Append(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. -bool wxModule::RegisterModules(void) +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) { - wxNode *node; - wxClassInfo* classInfo; + 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; - wxClassInfo::classTable.BeginFind(); - node = wxClassInfo::classTable.Next(); - while (node) + // satisfy module dependencies by loading them before the current module + for ( unsigned int i = 0; i < dependencies.size(); ++i ) { - classInfo = (wxClassInfo *)node->Data(); - if ((classInfo != (& (wxModule::classwxModule))) && - classInfo->IsKindOf(CLASSINFO(wxModule))) + 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* module = (wxModule*) classInfo->CreateObject(); - RegisterModule(module); + 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; } - node = wxClassInfo::classTable.Next(); } - return TRUE; + + 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; } -bool wxModule::InitializeModules(void) +// Initialize user-defined modules +bool wxModule::InitializeModules() { - // Initialize user-defined modules - for (wxNode *node = m_modules.First(); node; node = node->Next()) + wxModuleList initializedModules; + + for ( wxModuleList::compatibility_iterator node = m_modules.GetFirst(); + node; + node = node->GetNext() ) { - if (!((wxModule*)(node->Data()))->Init()) - return FALSE; + 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; + } + } } - return TRUE; + + // remember the real initialisation order + m_modules = initializedModules; + + return true; } -void wxModule::CleanUpModules(void) +// Clean up all currently initialized modules +void wxModule::DoCleanUpModules(const wxModuleList& modules) { - // Cleanup user-defined modules - for(wxNode* node = m_modules.Last(); node; node = node->Previous()) + // 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() ) { - ((wxModule*)(node->Data()))->Exit(); - delete (wxModule*)(node->Data()); + 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; } - m_modules.Clear(); + + // 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; +}