On Sat, 16 Apr 2011, Anders Gidenstam wrote:

I think that is a different leak from the effects. IIRC each particle
system is attached to the scene graph in (at least) two places: at the
emitter's location in the graph and in a global vector of particle system
updaters. IIRC they are never removed from the global list of updaters
(a bug - but a hard one to fix due to concurrency issues).
Tim knows more about this.

My failed attempt to unlink the particle systems might provide some insight into that issue. The attempt is broken because the
methods calls
            if (!Particles::getCommonRoot()->removeChild(item)) {
or
            if (!Particles::getCommonGeode()->removeDrawable(item)) {
can get called while another OSG thread traverses or inserts into the vector of children to the common root/geod.

Basically the ~CustomMatrixTransform() destructor is called on the wrong thread for this attempt to work. The clean up action needs either to be communicated to the right thread or synchronization added to removeChild/Drawable() method (which would be against the OSG design).

(Note: the preprocessor variable OSG_PARTICLE_FIX is unrelated to my changes.)

Cheers,

Anders
--
---------------------------------------------------------------------------
Anders Gidenstam
WWW: http://www.gidenstam.org/FlightGear/
diff --git a/simgear/scene/model/particles.cxx b/simgear/scene/model/particles.cxx
index acac7df..4d49ac3 100644
--- a/simgear/scene/model/particles.cxx
+++ b/simgear/scene/model/particles.cxx
@@ -51,6 +51,57 @@
 
 namespace simgear
 {
+
+class CustomMatrixTransform : public osg::MatrixTransform 
+{
+public:
+  CustomMatrixTransform(osgParticle::ParticleSystem* particleSystem) :
+      item(0) {
+      this->particleSystem = particleSystem;
+  };
+
+#ifdef OSG_PARTICLE_FIX
+    void setCleanupItem(osg::Group* item)
+#else
+    void setCleanupItem(osg::Drawable* item)
+#endif
+    {
+        this->item = item;
+    }
+
+protected:
+    ~CustomMatrixTransform()
+    {
+        if (!Particles::getPSU()->removeParticleSystem(particleSystem)) {
+            SG_LOG(SG_GENERAL, SG_ALERT,
+                   "particles.cxx: ~CustomMatrixTransform() "
+                   "Cleanup of particle system updater failed" << std::endl);
+        }
+        if (item) {
+#ifdef OSG_PARTICLE_FIX
+            if (!Particles::getCommonRoot()->removeChild(item)) {
+                SG_LOG(SG_GENERAL, SG_ALERT,
+                       "particles.cxx: ~CustomMatrixTransform() "
+                       "Cleanup of common root failed" << std::endl);
+            }
+#else
+            if (!Particles::getCommonGeode()->removeDrawable(item)) {
+                SG_LOG(SG_GENERAL, SG_ALERT,
+                       "particles.cxx: ~CustomMatrixTransform() "
+                       "Cleanup of common geode failed" << std::endl);
+            }
+#endif
+        }
+    }
+
+    osg::ref_ptr<osgParticle::ParticleSystem> particleSystem;
+#ifdef OSG_PARTICLE_FIX
+    osg::ref_ptr<osg::Group> item;
+#else
+    osg::ref_ptr<osg::Drawable> item;
+#endif
+};
+
 void GlobalParticleCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
 {
     enabled = !enabledNode || enabledNode->getBoolValue();
@@ -151,7 +202,7 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode,
     //may not be used depending on the configuration
     PointerGuard<Particles> callback;
 
-    getPSU()->addParticleSystem(particleSys); 
+    getPSU()->addParticleSystem(particleSys);
     getPSU()->setUpdateCallback(new GlobalParticleCallback(modelRoot));
     //contains counter, placer and shooter by default
     osgParticle::ModularEmitter* emitter = new osgParticle::ModularEmitter;
@@ -160,7 +211,7 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode,
 
     // Set up the alignment node ("stolen" from animation.cxx)
     // XXX Order of rotations is probably not correct.
-    osg::MatrixTransform *align = new osg::MatrixTransform;
+    CustomMatrixTransform* align = new CustomMatrixTransform(particleSys);
     osg::Matrix res_matrix;
     res_matrix.makeRotate(
         configNode->getFloatValue("offsets/pitch-deg", 0.0)*SG_DEGREES_TO_RADIANS,
@@ -202,8 +253,10 @@ osg::Group * Particles::appendParticles(const SGPropertyNode* configNode,
         g->addDrawable(particleSys);
         callback()->particleFrame->addChild(g);
         getCommonRoot()->addChild(callback()->particleFrame.get());
+        align->setCleanupItem(callback()->particleFrame.get());
 #else
         getCommonGeode()->addDrawable(particleSys);
+        align->setCleanupItem(particleSys);
 #endif
     }
     std::string textureFile;
------------------------------------------------------------------------------
Benefiting from Server Virtualization: Beyond Initial Workload 
Consolidation -- Increasing the use of server virtualization is a top
priority.Virtualization can reduce costs, simplify management, and improve 
application availability and disaster protection. Learn more about boosting 
the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel

Reply via email to