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_
|
||||
|
||||
#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
|
||||
|
@@ -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;
|
||||
|
@@ -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" );
|
||||
}
|
||||
|
Reference in New Issue
Block a user