Merge branch 'modules-cleanup'
Modernize wxModule code and add AreInitialized() function. See https://github.com/wxWidgets/wxWidgets/pull/2268
This commit is contained in:
@@ -12,18 +12,11 @@
|
|||||||
#define _WX_MODULE_H_
|
#define _WX_MODULE_H_
|
||||||
|
|
||||||
#include "wx/object.h"
|
#include "wx/object.h"
|
||||||
#include "wx/list.h"
|
#include "wx/vector.h"
|
||||||
#include "wx/arrstr.h"
|
|
||||||
#include "wx/dynarray.h"
|
|
||||||
|
|
||||||
// declare a linked list of modules
|
class wxModule;
|
||||||
class WXDLLIMPEXP_FWD_BASE wxModule;
|
|
||||||
WX_DECLARE_USER_EXPORTED_LIST(wxModule, wxModuleList, WXDLLIMPEXP_BASE);
|
|
||||||
|
|
||||||
// and an array of class info objects
|
|
||||||
WX_DEFINE_USER_EXPORTED_ARRAY_PTR(wxClassInfo *, wxArrayClassInfo,
|
|
||||||
class WXDLLIMPEXP_BASE);
|
|
||||||
|
|
||||||
|
typedef wxVector<wxModule*> wxModuleList;
|
||||||
|
|
||||||
// declaring a class derived from wxModule will automatically create an
|
// declaring a class derived from wxModule will automatically create an
|
||||||
// instance of this class on program startup, call its OnInit() method and call
|
// instance of this class on program startup, call its OnInit() method and call
|
||||||
@@ -54,14 +47,17 @@ public:
|
|||||||
static void RegisterModule(wxModule *module);
|
static void RegisterModule(wxModule *module);
|
||||||
static void RegisterModules();
|
static void RegisterModules();
|
||||||
static bool InitializeModules();
|
static bool InitializeModules();
|
||||||
static void CleanUpModules() { DoCleanUpModules(m_modules); }
|
static void CleanUpModules();
|
||||||
|
static bool AreInitialized() { return ms_areInitialized; }
|
||||||
|
|
||||||
// used by wxObjectLoader when unloading shared libs's
|
// used by wxObjectLoader when unloading shared libs's
|
||||||
|
|
||||||
static void UnregisterModule(wxModule *module);
|
static void UnregisterModule(wxModule *module);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static wxModuleList m_modules;
|
static wxModuleList ms_modules;
|
||||||
|
|
||||||
|
static bool ms_areInitialized;
|
||||||
|
|
||||||
// the function to call from constructor of a deriving class add module
|
// the function to call from constructor of a deriving class add module
|
||||||
// dependency which will be initialized before the module and unloaded
|
// dependency which will be initialized before the module and unloaded
|
||||||
@@ -70,14 +66,14 @@ protected:
|
|||||||
{
|
{
|
||||||
wxCHECK_RET( dep, wxT("NULL module dependency") );
|
wxCHECK_RET( dep, wxT("NULL module dependency") );
|
||||||
|
|
||||||
m_dependencies.Add(dep);
|
m_dependencies.push_back(dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as the version above except it will look up wxClassInfo by name on
|
// same as the version above except it will look up wxClassInfo by name on
|
||||||
// its own. Note that className must be ASCII
|
// its own. Note that className must be ASCII
|
||||||
void AddDependency(const char *className)
|
void AddDependency(const char *className)
|
||||||
{
|
{
|
||||||
m_namedDependencies.Add(wxASCII_STR(className));
|
m_namedDependencies.push_back(wxASCII_STR(className));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -89,7 +85,7 @@ private:
|
|||||||
|
|
||||||
// cleanup the modules in the specified list (which may not contain all
|
// cleanup the modules in the specified list (which may not contain all
|
||||||
// modules if we're called during initialization because not all modules
|
// modules if we're called during initialization because not all modules
|
||||||
// could be initialized) and also empty m_modules itself
|
// could be initialized) and also empty ms_modules itself
|
||||||
static void DoCleanUpModules(const wxModuleList& modules);
|
static void DoCleanUpModules(const wxModuleList& modules);
|
||||||
|
|
||||||
// resolve all named dependencies and add them to the normal m_dependencies
|
// resolve all named dependencies and add them to the normal m_dependencies
|
||||||
@@ -98,11 +94,12 @@ private:
|
|||||||
|
|
||||||
// module dependencies: contains wxClassInfo pointers for all modules which
|
// module dependencies: contains wxClassInfo pointers for all modules which
|
||||||
// must be initialized before this one
|
// must be initialized before this one
|
||||||
|
typedef wxVector<wxClassInfo*> wxArrayClassInfo;
|
||||||
wxArrayClassInfo m_dependencies;
|
wxArrayClassInfo m_dependencies;
|
||||||
|
|
||||||
// and the named dependencies: those will be resolved during run-time and
|
// and the named dependencies: those will be resolved during run-time and
|
||||||
// added to m_dependencies
|
// added to m_dependencies
|
||||||
wxArrayString m_namedDependencies;
|
wxVector<wxString> m_namedDependencies;
|
||||||
|
|
||||||
// used internally while initializing/cleaning up modules
|
// used internally while initializing/cleaning up modules
|
||||||
enum
|
enum
|
||||||
|
@@ -20,25 +20,32 @@
|
|||||||
#include "wx/log.h"
|
#include "wx/log.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/listimpl.cpp"
|
|
||||||
|
|
||||||
#define TRACE_MODULE wxT("module")
|
#define TRACE_MODULE wxT("module")
|
||||||
|
|
||||||
WX_DEFINE_LIST(wxModuleList)
|
|
||||||
|
|
||||||
wxIMPLEMENT_ABSTRACT_CLASS(wxModule, wxObject)
|
wxIMPLEMENT_ABSTRACT_CLASS(wxModule, wxObject)
|
||||||
|
|
||||||
wxModuleList wxModule::m_modules;
|
wxModuleList wxModule::ms_modules;
|
||||||
|
bool wxModule::ms_areInitialized = false;
|
||||||
|
|
||||||
void wxModule::RegisterModule(wxModule* module)
|
void wxModule::RegisterModule(wxModule* module)
|
||||||
{
|
{
|
||||||
module->m_state = State_Registered;
|
module->m_state = State_Registered;
|
||||||
m_modules.Append(module);
|
ms_modules.push_back(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxModule::UnregisterModule(wxModule* module)
|
void wxModule::UnregisterModule(wxModule* module)
|
||||||
{
|
{
|
||||||
m_modules.DeleteObject(module);
|
for ( wxModuleList::iterator it = ms_modules.begin();
|
||||||
|
it != ms_modules.end();
|
||||||
|
++it )
|
||||||
|
{
|
||||||
|
if ( *it == module )
|
||||||
|
{
|
||||||
|
ms_modules.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delete module;
|
delete module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,23 +94,25 @@ bool wxModule::DoInitializeModule(wxModule *module,
|
|||||||
wxClassInfo * cinfo = dependencies[i];
|
wxClassInfo * cinfo = dependencies[i];
|
||||||
|
|
||||||
// Check if the module is already initialized
|
// Check if the module is already initialized
|
||||||
wxModuleList::compatibility_iterator node;
|
wxModuleList::const_iterator it;
|
||||||
for ( node = initializedModules.GetFirst(); node; node = node->GetNext() )
|
for ( it = initializedModules.begin();
|
||||||
|
it != initializedModules.end();
|
||||||
|
++it )
|
||||||
{
|
{
|
||||||
if ( node->GetData()->GetClassInfo() == cinfo )
|
if ( (*it)->GetClassInfo() == cinfo )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( node )
|
if ( it != initializedModules.end() )
|
||||||
{
|
{
|
||||||
// this dependency is already initialized, nothing to do
|
// this dependency is already initialized, nothing to do
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the module in the registered modules list
|
// find the module in the registered modules list
|
||||||
for ( node = m_modules.GetFirst(); node; node = node->GetNext() )
|
for ( it = ms_modules.begin(); it != ms_modules.end(); ++it )
|
||||||
{
|
{
|
||||||
wxModule *moduleDep = node->GetData();
|
wxModule *moduleDep = *it;
|
||||||
if ( moduleDep->GetClassInfo() == cinfo )
|
if ( moduleDep->GetClassInfo() == cinfo )
|
||||||
{
|
{
|
||||||
if ( !DoInitializeModule(moduleDep, initializedModules ) )
|
if ( !DoInitializeModule(moduleDep, initializedModules ) )
|
||||||
@@ -116,7 +125,7 @@ bool wxModule::DoInitializeModule(wxModule *module,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !node )
|
if ( it == ms_modules.end() )
|
||||||
{
|
{
|
||||||
wxLogError(_("Dependency \"%s\" of module \"%s\" doesn't exist."),
|
wxLogError(_("Dependency \"%s\" of module \"%s\" doesn't exist."),
|
||||||
cinfo->GetClassName(),
|
cinfo->GetClassName(),
|
||||||
@@ -136,7 +145,7 @@ bool wxModule::DoInitializeModule(wxModule *module,
|
|||||||
module->GetClassInfo()->GetClassName());
|
module->GetClassInfo()->GetClassName());
|
||||||
|
|
||||||
module->m_state = State_Initialized;
|
module->m_state = State_Initialized;
|
||||||
initializedModules.Append(module);
|
initializedModules.push_back(module);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -146,11 +155,11 @@ bool wxModule::InitializeModules()
|
|||||||
{
|
{
|
||||||
wxModuleList initializedModules;
|
wxModuleList initializedModules;
|
||||||
|
|
||||||
for ( wxModuleList::compatibility_iterator node = m_modules.GetFirst();
|
for ( wxModuleList::const_iterator it = ms_modules.begin();
|
||||||
node;
|
it != ms_modules.end();
|
||||||
node = node->GetNext() )
|
++it )
|
||||||
{
|
{
|
||||||
wxModule *module = node->GetData();
|
wxModule *module = *it;
|
||||||
|
|
||||||
// the module could have been already initialized as dependency of
|
// the module could have been already initialized as dependency of
|
||||||
// another one
|
// another one
|
||||||
@@ -168,24 +177,33 @@ bool wxModule::InitializeModules()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remember the real initialisation order
|
// remember the real initialisation order
|
||||||
m_modules = initializedModules;
|
ms_modules = initializedModules;
|
||||||
|
|
||||||
|
ms_areInitialized = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxModule::CleanUpModules()
|
||||||
|
{
|
||||||
|
DoCleanUpModules(ms_modules);
|
||||||
|
|
||||||
|
ms_areInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Clean up all currently initialized modules
|
// Clean up all currently initialized modules
|
||||||
void wxModule::DoCleanUpModules(const wxModuleList& modules)
|
void wxModule::DoCleanUpModules(const wxModuleList& modules)
|
||||||
{
|
{
|
||||||
// cleanup user-defined modules in the reverse order compared to their
|
// cleanup user-defined modules in the reverse order compared to their
|
||||||
// initialization -- this ensures that dependencies are respected
|
// initialization -- this ensures that dependencies are respected
|
||||||
for ( wxModuleList::compatibility_iterator node = modules.GetLast();
|
for ( wxModuleList::const_reverse_iterator rit = modules.rbegin();
|
||||||
node;
|
rit != modules.rend();
|
||||||
node = node->GetPrevious() )
|
++rit )
|
||||||
{
|
{
|
||||||
wxLogTrace(TRACE_MODULE, wxT("Cleanup module %s"),
|
wxLogTrace(TRACE_MODULE, wxT("Cleanup module %s"),
|
||||||
node->GetData()->GetClassInfo()->GetClassName());
|
(*rit)->GetClassInfo()->GetClassName());
|
||||||
|
|
||||||
wxModule * module = node->GetData();
|
wxModule * module = *rit;
|
||||||
|
|
||||||
wxASSERT_MSG( module->m_state == State_Initialized,
|
wxASSERT_MSG( module->m_state == State_Initialized,
|
||||||
wxT("not initialized module being cleaned up") );
|
wxT("not initialized module being cleaned up") );
|
||||||
@@ -195,7 +213,14 @@ void wxModule::DoCleanUpModules(const wxModuleList& modules)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clear all modules, even the non-initialized ones
|
// clear all modules, even the non-initialized ones
|
||||||
WX_CLEAR_LIST(wxModuleList, m_modules);
|
for ( wxModuleList::const_iterator it = ms_modules.begin();
|
||||||
|
it != ms_modules.end();
|
||||||
|
++it )
|
||||||
|
{
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
ms_modules.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxModule::ResolveNamedDependencies()
|
bool wxModule::ResolveNamedDependencies()
|
||||||
@@ -214,7 +239,7 @@ bool wxModule::ResolveNamedDependencies()
|
|||||||
// add it even if it is not derived from wxModule because
|
// add it even if it is not derived from wxModule because
|
||||||
// DoInitializeModule() will make sure a module with the same class
|
// DoInitializeModule() will make sure a module with the same class
|
||||||
// info exists and fail if it doesn't
|
// info exists and fail if it doesn't
|
||||||
m_dependencies.Add(info);
|
m_dependencies.push_back(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -15,16 +15,18 @@
|
|||||||
#include "wx/module.h"
|
#include "wx/module.h"
|
||||||
#include "wx/wxcrt.h" // for wxStrcat()
|
#include "wx/wxcrt.h" // for wxStrcat()
|
||||||
|
|
||||||
|
static bool gs_wasInitialized = wxModule::AreInitialized();
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// test classes derived from wxModule
|
// test classes derived from wxModule
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
char g_strLoadOrder[256] = "\0";
|
wxString g_strLoadOrder;
|
||||||
|
|
||||||
class Module : public wxModule
|
class Module : public wxModule
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual bool OnInit() wxOVERRIDE { wxStrcat(g_strLoadOrder, GetClassInfo()->GetClassName()); return true; }
|
virtual bool OnInit() wxOVERRIDE { g_strLoadOrder += GetClassInfo()->GetClassName(); return true; }
|
||||||
virtual void OnExit() wxOVERRIDE { }
|
virtual void OnExit() wxOVERRIDE { }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,32 +88,17 @@ ModuleD::ModuleD()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// test class
|
// tests themselves
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class ModuleTestCase : public CppUnit::TestCase
|
TEST_CASE("wxModule::Initialized", "[module]")
|
||||||
{
|
{
|
||||||
public:
|
CHECK( !gs_wasInitialized );
|
||||||
ModuleTestCase() { }
|
CHECK( wxModule::AreInitialized() );
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
TEST_CASE("wxModule::LoadOrder", "[module]")
|
||||||
CPPUNIT_TEST_SUITE( ModuleTestCase );
|
|
||||||
CPPUNIT_TEST( LoadOrder );
|
|
||||||
CPPUNIT_TEST_SUITE_END();
|
|
||||||
|
|
||||||
void LoadOrder();
|
|
||||||
wxDECLARE_NO_COPY_CLASS(ModuleTestCase);
|
|
||||||
};
|
|
||||||
|
|
||||||
// register in the unnamed registry so that these tests are run by default
|
|
||||||
CPPUNIT_TEST_SUITE_REGISTRATION( ModuleTestCase );
|
|
||||||
|
|
||||||
// also include in its own registry so that these tests can be run alone
|
|
||||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ModuleTestCase, "ModuleTestCase" );
|
|
||||||
|
|
||||||
void ModuleTestCase::LoadOrder()
|
|
||||||
{
|
{
|
||||||
// module D is the only one with no dependencies and so should load as first (and so on):
|
// module D is the only one with no dependencies and so should load as first (and so on):
|
||||||
CPPUNIT_ASSERT_EQUAL( std::string("ModuleDModuleCModuleBModuleA"),
|
CHECK( g_strLoadOrder == "ModuleDModuleCModuleBModuleA" );
|
||||||
g_strLoadOrder );
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user