Merge branch 'modules-cleanup'

Modernize wxModule code and add AreInitialized() function.

See https://github.com/wxWidgets/wxWidgets/pull/2268
This commit is contained in:
Vadim Zeitlin
2021-03-07 23:51:04 +01:00
3 changed files with 76 additions and 67 deletions

View File

@@ -12,18 +12,11 @@
#define _WX_MODULE_H_
#include "wx/object.h"
#include "wx/list.h"
#include "wx/arrstr.h"
#include "wx/dynarray.h"
#include "wx/vector.h"
// declare a linked list of modules
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);
class wxModule;
typedef wxVector<wxModule*> wxModuleList;
// declaring a class derived from wxModule will automatically create an
// 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 RegisterModules();
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
static void UnregisterModule(wxModule *module);
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
// dependency which will be initialized before the module and unloaded
@@ -70,14 +66,14 @@ protected:
{
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
// its own. Note that className must be ASCII
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
// 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);
// 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
// must be initialized before this one
typedef wxVector<wxClassInfo*> wxArrayClassInfo;
wxArrayClassInfo m_dependencies;
// and the named dependencies: those will be resolved during run-time and
// added to m_dependencies
wxArrayString m_namedDependencies;
wxVector<wxString> m_namedDependencies;
// used internally while initializing/cleaning up modules
enum

View File

@@ -20,25 +20,32 @@
#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;
wxModuleList wxModule::ms_modules;
bool wxModule::ms_areInitialized = false;
void wxModule::RegisterModule(wxModule* module)
{
module->m_state = State_Registered;
m_modules.Append(module);
ms_modules.push_back(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;
}
@@ -87,23 +94,25 @@ bool wxModule::DoInitializeModule(wxModule *module,
wxClassInfo * cinfo = dependencies[i];
// Check if the module is already initialized
wxModuleList::compatibility_iterator node;
for ( node = initializedModules.GetFirst(); node; node = node->GetNext() )
wxModuleList::const_iterator it;
for ( it = initializedModules.begin();
it != initializedModules.end();
++it )
{
if ( node->GetData()->GetClassInfo() == cinfo )
if ( (*it)->GetClassInfo() == cinfo )
break;
}
if ( node )
if ( it != initializedModules.end() )
{
// 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() )
for ( it = ms_modules.begin(); it != ms_modules.end(); ++it )
{
wxModule *moduleDep = node->GetData();
wxModule *moduleDep = *it;
if ( moduleDep->GetClassInfo() == cinfo )
{
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."),
cinfo->GetClassName(),
@@ -136,7 +145,7 @@ bool wxModule::DoInitializeModule(wxModule *module,
module->GetClassInfo()->GetClassName());
module->m_state = State_Initialized;
initializedModules.Append(module);
initializedModules.push_back(module);
return true;
}
@@ -146,11 +155,11 @@ bool wxModule::InitializeModules()
{
wxModuleList initializedModules;
for ( wxModuleList::compatibility_iterator node = m_modules.GetFirst();
node;
node = node->GetNext() )
for ( wxModuleList::const_iterator it = ms_modules.begin();
it != ms_modules.end();
++it )
{
wxModule *module = node->GetData();
wxModule *module = *it;
// the module could have been already initialized as dependency of
// another one
@@ -168,24 +177,33 @@ bool wxModule::InitializeModules()
}
// remember the real initialisation order
m_modules = initializedModules;
ms_modules = initializedModules;
ms_areInitialized = true;
return true;
}
void wxModule::CleanUpModules()
{
DoCleanUpModules(ms_modules);
ms_areInitialized = false;
}
// 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() )
for ( wxModuleList::const_reverse_iterator rit = modules.rbegin();
rit != modules.rend();
++rit )
{
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,
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
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()
@@ -214,7 +239,7 @@ bool wxModule::ResolveNamedDependencies()
// 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);
m_dependencies.push_back(info);
}
return true;

View File

@@ -15,16 +15,18 @@
#include "wx/module.h"
#include "wx/wxcrt.h" // for wxStrcat()
static bool gs_wasInitialized = wxModule::AreInitialized();
// ----------------------------------------------------------------------------
// test classes derived from wxModule
// ----------------------------------------------------------------------------
char g_strLoadOrder[256] = "\0";
wxString g_strLoadOrder;
class Module : public wxModule
{
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 { }
};
@@ -86,32 +88,17 @@ ModuleD::ModuleD()
}
// ----------------------------------------------------------------------------
// test class
// tests themselves
// ----------------------------------------------------------------------------
class ModuleTestCase : public CppUnit::TestCase
TEST_CASE("wxModule::Initialized", "[module]")
{
public:
ModuleTestCase() { }
CHECK( !gs_wasInitialized );
CHECK( wxModule::AreInitialized() );
}
private:
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()
TEST_CASE("wxModule::LoadOrder", "[module]")
{
// module D is the only one with no dependencies and so should load as first (and so on):
CPPUNIT_ASSERT_EQUAL( std::string("ModuleDModuleCModuleBModuleA"),
g_strLoadOrder );
CHECK( g_strLoadOrder == "ModuleDModuleCModuleBModuleA" );
}