diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index acfb0d629..c083f326f 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -232,6 +232,8 @@ FGGlobals::~FGGlobals() delete locale; locale = NULL; + cleanupListeners(); + props.clear(); delete commands; @@ -525,9 +527,26 @@ FGGlobals::resetPropertyRoot() { delete locale; + cleanupListeners(); + + // we don't strictly need to clear these (they will be reset when we + // initProperties again), but trying to reduce false-positives when dumping + // ref-counts. + positionLon.clear(); + positionLat.clear(); + positionAlt.clear(); + viewLon.clear(); + viewLat.clear(); + viewAlt.clear(); + orientPitch.clear(); + orientHeading.clear(); + orientRoll.clear(); + SG_LOG(SG_GENERAL, SG_INFO, "root props refcount:" << props.getNumRefs()); treeDumpRefCounts(0, props); + //BaseStackSnapshot::dumpAll(std::cout); + props = new SGPropertyNode; initProperties(); locale = new FGLocale(props); @@ -709,4 +728,18 @@ void FGGlobals::set_chatter_queue(FGSampleQueue* queue) _chatter_queue = queue; } +void FGGlobals::addListenerToCleanup(SGPropertyChangeListener* l) +{ + _listeners_to_cleanup.push_back(l); +} + +void FGGlobals::cleanupListeners() +{ + SGPropertyChangeListenerVec::iterator i = _listeners_to_cleanup.begin(); + for (; i != _listeners_to_cleanup.end(); ++i) { + delete *i; + } + _listeners_to_cleanup.clear(); +} + // end of globals.cxx diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index 3f8ae0689..8f1736f14 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -163,6 +163,12 @@ private: void initProperties(); SGSharedPtr _chatter_queue; + + void cleanupListeners(); + + typedef std::vector SGPropertyChangeListenerVec; + SGPropertyChangeListenerVec _listeners_to_cleanup; + public: FGGlobals(); @@ -346,6 +352,8 @@ public: FGSampleQueue* get_chatter_queue() const; void set_chatter_queue(FGSampleQueue* queue); + + void addListenerToCleanup(SGPropertyChangeListener* l); }; diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 8b7083470..7756a6d0c 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -299,7 +299,9 @@ static void upper_case_property(const char *name) else assert(t == props::STRING); } - p->addChangeListener(new FGMakeUpperCase); + SGPropertyChangeListener* muc = new FGMakeUpperCase; + globals->addListenerToCleanup(muc); + p->addChangeListener(muc); } // see http://code.google.com/p/flightgear-bugs/issues/detail?id=385 diff --git a/src/Main/positioninit.cxx b/src/Main/positioninit.cxx index ee45af498..cd5130db6 100644 --- a/src/Main/positioninit.cxx +++ b/src/Main/positioninit.cxx @@ -65,7 +65,8 @@ static bool fgSetTowerPosFromAirportID( const string& id) { } -struct FGTowerLocationListener : SGPropertyChangeListener { +class FGTowerLocationListener : public SGPropertyChangeListener { + void valueChanged(SGPropertyNode* node) { string id(node->getStringValue()); if (fgGetBool("/sim/tower/auto-position",true)) @@ -82,7 +83,7 @@ struct FGTowerLocationListener : SGPropertyChangeListener { } }; -struct FGClosestTowerLocationListener : SGPropertyChangeListener +class FGClosestTowerLocationListener : public SGPropertyChangeListener { void valueChanged(SGPropertyNode* ) { @@ -98,9 +99,14 @@ struct FGClosestTowerLocationListener : SGPropertyChangeListener }; void initTowerLocationListener() { + + SGPropertyChangeListener* tll = new FGTowerLocationListener(); + globals->addListenerToCleanup(tll); fgGetNode("/sim/tower/airport-id", true) - ->addChangeListener( new FGTowerLocationListener(), true ); + ->addChangeListener( tll, true ); + FGClosestTowerLocationListener* ntcl = new FGClosestTowerLocationListener(); + globals->addListenerToCleanup(ntcl); fgGetNode("/sim/airport/closest-airport-id", true) ->addChangeListener(ntcl , true ); fgGetNode("/sim/tower/auto-position", true) diff --git a/src/Viewer/fg_os_osgviewer.cxx b/src/Viewer/fg_os_osgviewer.cxx index 976b3d753..5d85dcaba 100644 --- a/src/Viewer/fg_os_osgviewer.cxx +++ b/src/Viewer/fg_os_osgviewer.cxx @@ -286,7 +286,9 @@ void fgOSOpenWindow(bool stencil) void fgOSResetProperties() { SGPropertyNode* osgLevel = fgGetNode("/sim/rendering/osg-notify-level", true); - osgLevel->addChangeListener(new NotifyLevelListener, true); + NotifyLevelListener* l = new NotifyLevelListener; + globals->addListenerToCleanup(l); + osgLevel->addChangeListener(l, true); osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault()); if (guiCamera) { diff --git a/src/Viewer/renderer.cxx b/src/Viewer/renderer.cxx index d195d42b5..81b135bc4 100644 --- a/src/Viewer/renderer.cxx +++ b/src/Viewer/renderer.cxx @@ -430,6 +430,11 @@ FGRenderer::FGRenderer() : FGRenderer::~FGRenderer() { + SGPropertyChangeListenerVec::iterator i = _listeners.begin(); + for (; i != _listeners.end(); ++i) { + delete *i; + } + DeletionManager::uninstall(mRealRoot.get()); #ifdef FG_JPEG_SERVER jpgRenderFrame = NULL; @@ -498,6 +503,13 @@ public: } }; +void +FGRenderer::addChangeListener(SGPropertyChangeListener* l, const char* path) +{ + _listeners.push_back(l); + fgAddChangeListener(l, path); +} + void FGRenderer::init( void ) { @@ -508,14 +520,14 @@ FGRenderer::init( void ) _classicalRenderer = !fgGetBool("/sim/rendering/rembrandt/enabled", false); _shadowMapSize = fgGetInt( "/sim/rendering/shadows/map-size", 4096 ); - fgAddChangeListener( new ShadowMapSizeListener, "/sim/rendering/shadows/map-size" ); - fgAddChangeListener( new ShadowEnabledListener, "/sim/rendering/shadows/enabled" ); + addChangeListener( new ShadowMapSizeListener, "/sim/rendering/shadows/map-size" ); + addChangeListener( new ShadowEnabledListener, "/sim/rendering/shadows/enabled" ); ShadowRangeListener* srl = new ShadowRangeListener; - fgAddChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[0]"); + addChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[0]"); fgAddChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[1]"); fgAddChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[2]"); fgAddChangeListener(srl, "/sim/rendering/shadows/cascade-far-m[3]"); - fgAddChangeListener(new ShadowNumListener, "/sim/rendering/shadows/num-cascades"); + addChangeListener(new ShadowNumListener, "/sim/rendering/shadows/num-cascades"); _numCascades = fgGetInt("/sim/rendering/shadows/num-cascades", 4); _cascadeFar[0] = fgGetFloat("/sim/rendering/shadows/cascade-far-m[0]", 5.0f); _cascadeFar[1] = fgGetFloat("/sim/rendering/shadows/cascade-far-m[1]", 50.0f); diff --git a/src/Viewer/renderer.hxx b/src/Viewer/renderer.hxx index 959847408..f6a51b529 100644 --- a/src/Viewer/renderer.hxx +++ b/src/Viewer/renderer.hxx @@ -138,6 +138,9 @@ protected: float _cascadeFar[4]; bool _useColorForDepth; + typedef std::vector SGPropertyChangeListenerVec; + SGPropertyChangeListenerVec _listeners; + flightgear::CameraInfo* buildCameraFromRenderingPipeline(FGRenderingPipeline* rpipe, flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera, const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc); @@ -168,6 +171,8 @@ protected: osg::ref_ptr _depthInColor; osg::ref_ptr _pipeline; + + void addChangeListener(SGPropertyChangeListener* l, const char* path); }; bool fgDumpSceneGraphToFile(const char* filename);