mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-27 13:51:49 +00:00
226 lines
6.5 KiB
C++
226 lines
6.5 KiB
C++
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// 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;
|
||
|
}
|