/////////////////////////////////////////////////////////////////////////////
-// Name: module.cpp
+// Name: src/common/module.cpp
// Purpose: Modules initialization/destruction
// Author: Wolfram Gloger/adapted by Guilhem Lavaux
// Modified by:
// 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;
+}