|
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.
|