From: <cn...@us...> - 2009-10-22 18:10:28
|
Revision: 576 http://hgengine.svn.sourceforge.net/hgengine/?rev=576&view=rev Author: cnlohr Date: 2009-10-22 18:10:20 +0000 (Thu, 22 Oct 2009) Log Message: ----------- tweak RTTI, since you can't use it in constructors or destructors... Will we have a DeleteNode() virtual function? Also, make module manager smarter and able to reload modules Modified Paths: -------------- Mercury2/base_set.sh Mercury2/src/MercuryNode.cpp Mercury2/src/MercuryNode.h Mercury2/src/ModuleManager.cpp Mercury2/src/ModuleManager.h Modified: Mercury2/base_set.sh =================================================================== --- Mercury2/base_set.sh 2009-10-22 18:07:20 UTC (rev 575) +++ Mercury2/base_set.sh 2009-10-22 18:10:20 UTC (rev 576) @@ -8,13 +8,14 @@ ISMAC=1; fi -OPTIONS="X11 libxml OGL sse gprof glprofile" +OPTIONS="X11 libxml OGL sse gprof glprofile instancewatch" OPT_X11=1 OPT_OGL=1 OPT_libxml=1 OPT_sse=0 OPT_gprof=0 OPT_glprofile=0 +OPT_instancewatch=1 DEFINES="WAS_CONFIGURED USE_MSTRING" CC_BASE="-O2 -g0 -Wall" @@ -88,6 +89,10 @@ LD_BASE="-Lsrc/maclib -framework OpenGL -lobjc -framework GLUT -framework ApplicationServices" fi +if test $OPT_instancewatch = 1; then + DEFINES="$DEFINES INSTANCE_WATCH" +fi + ARCH=`uname -m` if test $ARCH = "i686" || test $ARCH = "i586"; then Modified: Mercury2/src/MercuryNode.cpp =================================================================== --- Mercury2/src/MercuryNode.cpp 2009-10-22 18:07:20 UTC (rev 575) +++ Mercury2/src/MercuryNode.cpp 2009-10-22 18:10:20 UTC (rev 576) @@ -9,12 +9,14 @@ #include <Shader.h> #include <RenderGraph.h> +#include <ModuleManager.h> + using namespace std; REGISTER_NODE_TYPE(MercuryNode); MercuryNode::MercuryNode() - :m_parent(NULL), m_prevSibling(NULL), + :Type( 0 ), m_parent(NULL), m_prevSibling(NULL), m_nextSibling(NULL), m_hidden(false), m_useAlphaPath(false), m_culled(false), m_iPasses( DEFAULT_PASSES ), m_iForcePasses( 0 ) @@ -23,6 +25,12 @@ MercuryNode::~MercuryNode() { + +#ifdef INSTANCE_WATCH + if( Type ) + DEL_INSTANCE(this, Type); +#endif + m_parent = NULL; list< MercuryNode* >::iterator i; @@ -399,7 +407,14 @@ MString t = ToUpper( type ); std::list< std::pair< MString, Callback0R<MercuryNode*> > >::iterator i; for (i = m_factoryCallbacks.begin(); i != m_factoryCallbacks.end(); ++i) - if (i->first == t) return i->second(); + if (i->first == t) + { + MercuryNode * n = i->second(); +#ifdef INSTANCE_WATCH + NEW_INSTANCE(n, n->GetType()); +#endif + return n; + } LOG.Write( "WARNING: Node type " + type + " not found." ); return NULL; } Modified: Mercury2/src/MercuryNode.h =================================================================== --- Mercury2/src/MercuryNode.h 2009-10-22 18:07:20 UTC (rev 575) +++ Mercury2/src/MercuryNode.h 2009-10-22 18:10:20 UTC (rev 576) @@ -21,7 +21,7 @@ { if (n==NULL) return NULL; return dynamic_cast<const x*>(n); } \ static x* Cast(MercuryNode* n) \ { if (n==NULL) return NULL; return dynamic_cast<x*>(n); } \ -virtual const char * GetType() { return #x; } +virtual const char * GetType() { if( !Type ) Type = #x; return #x; } /* #define GENRTTI(x) static bool IsMyType(const MercuryNode* n) \ @@ -117,6 +117,8 @@ const MercuryMatrix & GetModelViewMatrix() const { return m_pModelViewMatrix[g_iViewportID]; } inline unsigned short GetPasses() const { return m_iPasses; } + + const char * Type; protected: std::list< MercuryNode* > m_children; //These nodes are unique, not instanced MercuryNode* m_parent; @@ -171,7 +173,13 @@ MercuryNode* FactoryFunct##class() { return new class(); } \ Callback0R<MercuryNode*> factoryclbk##class( FactoryFunct##class ); \ bool GlobalRegisterSuccess##class = NodeFactory::GetInstance().RegisterFactoryCallback(#class, factoryclbk##class); \ - extern "C" { int Install##class() { LOG.Write("Installing "#class ); NodeFactory::GetInstance().RegisterFactoryCallback(#class, factoryclbk##class); return 0; } } + extern "C" { void * Install##class() { LOG.Write("Installing "#class ); \ + NodeFactory::GetInstance().RegisterFactoryCallback(#class, factoryclbk##class); \ + class * t = new class(); \ + void * vtable = *((void**)t); \ + delete t; \ + return vtable; \ + } } #endif Modified: Mercury2/src/ModuleManager.cpp =================================================================== --- Mercury2/src/ModuleManager.cpp 2009-10-22 18:07:20 UTC (rev 575) +++ Mercury2/src/ModuleManager.cpp 2009-10-22 18:10:20 UTC (rev 576) @@ -19,7 +19,7 @@ extern "C" { -typedef int (*LoaderFunction)(); +typedef void * (*LoaderFunction)(); //Returns vtable pointer }; ModuleManager::ModuleManager() @@ -37,6 +37,7 @@ void ModuleManager::InitializeAllModules() { + m_mHandleMutex.Wait(); XMLDocument* doc = XMLDocument::Load("modules.xml"); XMLNode r = doc->GetRootNode(); for (XMLNode child = r.Child(); child.IsValid(); child = child.NextNode()) @@ -51,9 +52,15 @@ #else MString ModuleName = child.Attribute( "obj" ) + ".so"; #endif + MString LoadFunct = child.Attribute( "func" ); + + m_hModuleMatching[child.Attribute( "obj" )] = child.Attribute( "class" ); + m_hClassMatching[child.Attribute( "class" )] = ModuleName; + m_hClassMFunction[child.Attribute( "class" )] = LoadFunct; LoadModule( ModuleName, LoadFunct ); } + m_mHandleMutex.UnLock(); delete doc; } @@ -63,8 +70,10 @@ dlclose( m_hAllHandles[ModuleName] ); } -bool ModuleManager::LoadModule( const MString & ModuleName, const MString & LoadFunction ) +void * ModuleManager::LoadModule( const MString & ModuleName, const MString & LoadFunction ) { + m_mHandleMutex.Wait(); + if( m_hAllHandles[ModuleName] ) UnloadModule( ModuleName ); void * v = dlopen( ModuleName.c_str(), RTLD_NOW | RTLD_GLOBAL ); @@ -81,9 +90,11 @@ return false; } + m_mHandleMutex.UnLock(); + //If no load funct, just exit early. if( LoadFunction == "" ) - return true; + return 0; LoaderFunction T = (LoaderFunction)dlsym( m_hAllHandles[ModuleName], LoadFunction.c_str() ); if( !T ) @@ -92,16 +103,50 @@ return false; } - int ret = T(); - if( ret ) + void * ret = T(); + if( !ret ) { - fprintf( stderr, "Error executing (Returned error %d): %s() in %s\n", ret, LoadFunction.c_str(), ModuleName.c_str() ); + fprintf( stderr, "Error executing (Returned error %p): %s() in %s\n", ret, LoadFunction.c_str(), ModuleName.c_str() ); return false; } - return true; + return ret; } + +#ifdef INSTANCE_WATCH + +void ModuleManager::ReloadModule( const MString & sClass ) +{ + m_mHandleMutex.Wait(); + + std::set< void * > & s = m_hAllInstances[sClass]; + std::set< void * >::iterator i = s.begin(); + + void * newvtable = LoadModule( m_hClassMatching[sClass], m_hClassMFunction[sClass] ); + + for( ; i != s.end(); i++ ) + *((void**)(*i)) = newvtable; + + m_mHandleMutex.UnLock(); +} + +void ModuleManager::RegisterInstance( void * instance, const char * sClass ) +{ + m_hAllInstances[sClass].insert( instance ); +} + +void ModuleManager::UnregisterInstance( void * instance, const char * sClass ) +{ + std::set< void * > & s = m_hAllInstances[sClass]; + std::set< void * >::iterator i = s.find( instance ); + + if( i != s.end() ) + s.erase( i ); +} + +#endif + /**************************************************************************** * Copyright (C) 2009 by Charles Lohr * * * Modified: Mercury2/src/ModuleManager.h =================================================================== --- Mercury2/src/ModuleManager.h 2009-10-22 18:07:20 UTC (rev 575) +++ Mercury2/src/ModuleManager.h 2009-10-22 18:10:20 UTC (rev 576) @@ -3,6 +3,8 @@ #include <MercuryUtil.h> #include <MercuryHash.h> +#include <MercuryThreads.h> +#include <set> /* This is the module loader mechanism. This allows for run-time loading of new modules. Eventually, it will allow for run-time re-loading of modules. @@ -15,15 +17,44 @@ static ModuleManager & GetInstance(); void InitializeAllModules(); - bool LoadModule( const MString & ModuleName, const MString & LoadFunction ); + void * LoadModule( const MString & ModuleName, const MString & LoadFunction ); void UnloadModule( const MString & ModuleName ); + +#ifdef INSTANCE_WATCH + void ReloadModule( const MString & sClass ); + + void RegisterInstance( void * instance, const char * sClass ); + void UnregisterInstance( void * instance, const char * sClass ); +#endif + +private: + + MercuryMutex m_mHandleMutex; + +#ifdef INSTANCE_WATCH + MHash< std::set< void * > > m_hAllInstances; +#endif + MHash< void * > m_hAllHandles; + MHash< MString > m_hModuleMatching; + MHash< MString > m_hClassMatching; + MHash< MString > m_hClassMFunction; }; static InstanceCounter<ModuleManager> ModMancounter("ModuleManager"); +#ifdef INSTANCE_WATCH +#define NEW_INSTANCE( node, t ) ModuleManager::GetInstance().RegisterInstance( node, t ); +#define DEL_INSTANCE( node, t ) ModuleManager::GetInstance().UnregisterInstance( node, t ); +#else + +#define NEW_INSTANCE( t ) +#define DEL_INSTANCE( t ) + +#endif + /**************************************************************************** * Copyright (C) 2009 by Charles Lohr * * * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |