]> git.mxchange.org Git - simgear.git/commitdiff
DeletionManager
authorTim Moore <timoore33@gmail.com>
Fri, 3 Aug 2012 15:15:15 +0000 (17:15 +0200)
committerTim Moore <timoore33@gmail.com>
Fri, 3 Aug 2012 18:10:53 +0000 (20:10 +0200)
Class for safely deleting objects that may be active in different threads.
This is now used in the implementation of spin animations.

simgear/scene/model/animation.cxx
simgear/scene/util/CMakeLists.txt
simgear/scene/util/DeletionManager.cxx [new file with mode: 0644]
simgear/scene/util/DeletionManager.hxx [new file with mode: 0644]

index 25dcb20ae7b46aa82d9853e6c15d66ea815bb32f..7e94e5e6ff3baf1f5238c1b60d81a0f21d589037 100644 (file)
@@ -44,6 +44,7 @@
 #include <simgear/structure/SGBinding.hxx>
 #include <simgear/scene/material/EffectGeode.hxx>
 #include <simgear/scene/material/EffectCullVisitor.hxx>
+#include <simgear/scene/util/DeletionManager.hxx>
 #include <simgear/scene/util/OsgMath.hxx>
 #include <simgear/scene/util/SGNodeMasks.hxx>
 #include <simgear/scene/util/SGSceneUserData.hxx>
@@ -778,7 +779,8 @@ protected:
     // more than one camera. It is probably safe to overwrite the
     // reference values in multiple threads, but we'll provide a
     // threadsafe way to manage those values just to be safe.
-    struct ReferenceValues {
+    struct ReferenceValues : public osg::Referenced
+    {
         ReferenceValues(double t, double rot, double vel)
             : _time(t), _rotation(rot), _rotVelocity(vel)
         {
@@ -800,19 +802,31 @@ void SpinAnimCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
     if (!_condition || _condition->test()) {
         double t = nv->getFrameStamp()->getReferenceTime();
         double rps = _animationValue->getValue() / 60.0;
-        ReferenceValues* refval = static_cast<ReferenceValues*>(_referenceValues.get());
-        if (!refval || refval->_rotVelocity != rps) {
-            ReferenceValues* newref = 0;
-            if (!refval) {
+        ref_ptr<ReferenceValues>
+            refval(static_cast<ReferenceValues*>(_referenceValues.get()));
+    if (!refval || refval->_rotVelocity != rps) {
+            ref_ptr<ReferenceValues> newref;
+            if (!refval.valid()) {
                 // initialization
                 newref = new ReferenceValues(t, 0.0, rps);
             } else {
                 double newRot = refval->_rotation + (t - refval->_time) * refval->_rotVelocity;
                 newref = new ReferenceValues(t, newRot, rps);
             }
+            // increment reference pointer, because it will be stored
+            // naked in _referenceValues.
+            newref->ref();
             if (_referenceValues.assign(newref, refval)) {
-                delete refval;
+                if (refval.valid()) {
+                    DeletionManager::instance()->addStaleObject(refval.get());
+                    refval->unref();
+                }
+            } else {
+                // Another thread installed new values before us
+                newref->unref();
             }
+            // Whatever happened, we can use the reference values just
+            // calculated.
             refval = newref;
         }
         double rotation = refval->_rotation + (t - refval->_time) * rps;
index 670d21af7691f06eb501890d838b53b54226ca96..4c523c9d448c8f7e7c10f0c994b08c435020cb04 100644 (file)
@@ -2,6 +2,7 @@ include (SimGearComponent)
 
 set(HEADERS 
     CopyOp.hxx
+    DeletionManager.hxx
     NodeAndDrawableVisitor.hxx
        Noise.hxx
     OsgMath.hxx
@@ -28,6 +29,7 @@ set(HEADERS
 
 set(SOURCES 
     CopyOp.cxx
+    DeletionManager.cxx
     NodeAndDrawableVisitor.cxx
        Noise.cxx
     PrimitiveUtils.cxx
diff --git a/simgear/scene/util/DeletionManager.cxx b/simgear/scene/util/DeletionManager.cxx
new file mode 100644 (file)
index 0000000..dbc24da
--- /dev/null
@@ -0,0 +1,58 @@
+// DeletionManager.hxx -- defer deletions to a safe time
+//
+// Copyright (C) 2012  Tim Moore timoore33@gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA  02110-1301, USA.
+
+#include "DeletionManager.hxx"
+
+#include <OpenThreads/ScopedLock>
+#include <osg/Node>
+#include "OsgSingleton.hxx"
+
+namespace simgear
+{
+using namespace osg;
+
+bool DeletionManager::handle(const osgGA::GUIEventAdapter& ea,
+                             osgGA::GUIActionAdapter&,
+                             osg::Object*, osg::NodeVisitor*)
+{
+    if (ea.getEventType() == osgGA::GUIEventAdapter::FRAME)
+    {
+        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+        _staleObjects.resize(0);
+    }
+    return false;
+}
+
+void DeletionManager::addStaleObject(Referenced* obj)
+{
+    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+    _staleObjects.push_back(obj);
+}
+
+void DeletionManager::install(Node* node)
+{
+    node->addEventCallback(instance());
+}
+
+DeletionManager* DeletionManager::instance()
+{
+    return SingletonRefPtr<DeletionManager>::instance();
+}
+}
+
diff --git a/simgear/scene/util/DeletionManager.hxx b/simgear/scene/util/DeletionManager.hxx
new file mode 100644 (file)
index 0000000..82d7410
--- /dev/null
@@ -0,0 +1,48 @@
+// DeletionManager.hxx -- defer deletions to a safe time
+//
+// Copyright (C) 2012  Tim Moore timoore33@gmail.com
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA  02110-1301, USA.
+
+#ifndef SIMGEAR_DELETIONMANAGER_HXX
+#define SIMGEAR_DELETIONMANAGER_HXX 1
+
+#include <vector>
+
+#include <OpenThreads/Mutex>
+#include <osg/ref_ptr>
+#include <osg/NodeCallback>
+#include <osg/Referenced>
+#include <osgGA/GUIEventHandler>
+
+namespace simgear
+{
+class DeletionManager : public osgGA::GUIEventHandler
+{
+public:
+    virtual bool handle(const osgGA::GUIEventAdapter& ea,
+                        osgGA::GUIActionAdapter& aa,
+                        osg::Object* object, osg::NodeVisitor* nv);
+    void addStaleObject(osg::Referenced* obj);
+    static void install(osg::Node* node);
+    static DeletionManager* instance();
+protected:
+    OpenThreads::Mutex _mutex;
+    std::vector<osg::ref_ptr<osg::Referenced> > _staleObjects;
+};
+}
+
+#endif